To use the Tanker SDK, your application server needs to generate Tanker identities and Tanker public identities for your users.

Tanker identity SDK

We provide a server-side identity SDK for manipulating Tanker identities. It will allow you to generate Tanker identities for your users using your app secret.

It is available in the following languages:

You will find installation and usage guides in the packages respective readmes. If the language your server is written in is not supported yet, please contact us at contact@tanker.io.

For the rest of the server examples, we will consider a server written in Go, but the examples would easily be transposable in the other supported languages.

Generating Tanker identities

Tanker identities should be generated for each of your users when they log in with Tanker for the first time, and stored permanently alongside user records in your app's database.

They must only be given to authenticated users, so generating them in the user authentication flow makes sense:

package server

import (
    "github.com/TankerHQ/identity-go/identity"
    "github.com/pkg/errors"
)

var tankerConfig = identity.Config{
    AppID:         <AppID>,
    AppSecret:     <AppSecret>,
}

func AuthenticateUser(email string, password string) (*user, error) {
    // Authenticate the user
    user, err := Authenticate(email, password)
    if err != nil {
        return nil, err
    }

    if user.TankerIdentity == nil {
        // Create a new Tanker identity for this user
        tankerIdentity, err := identity.Create(tankerConfig, user.ID)
        if err != nil {
            return nil, err
        }
        user.TankerIdentity = tankerIdentity

        // Store it in the database
        if err := UpdateUser(user); err != nil {
            return nil, err
        }
    }

    return user, nil
}

A user ID is requested when generating a Tanker identity. It can be any string value (e.g. your own internal user ID, or a random UUID value), as long as it is unique per user.

As far as Tanker is concerned, you don't have to store the user ID since it becomes a part of the generated Tanker identity. It will be used internally by Tanker SDKs (through the Tanker identity) to unambiguously identify a user from your application.

Warning

Tanker identities are secret identities. Only an authenticated user must be able to access their own secret identity. To interact with other users, use public identities described in the next section.

Generating Tanker public identities

Tanker public identities represent a user for others. It can be distributed to any other user who would need to share with them.

A Tanker public identity is derived from a user's secret identity:

package server

import (
    "github.com/TankerHQ/identity-go/identity"
    "github.com/pkg/errors"
)

func GetPublicIdentity(email string) (*string, error) {
    user, err := GetUser(email)
    if err != nil {
        return nil, err
    }

    if user.TankerIdentity == nil {
        return nil, errors.New("User doesn't have an identity")
    }
    return identity.GetPublicIdentity(user.TankerIdentity)
}

As you can see, this can only be done if the user already has a Tanker secret identity. If you wish to share with users who didn't create their account yet, or never registered their identity with Tanker, please refer to the pre-registration sharing tutorial.

It is not required to store Tanker public identities in your database, as they can be re-generated from stored secret identities at will.

Sending the identity verification email

To verify the user's email address, Tanker needs to send them an email. This is triggered by a call to https://api.tanker.io/verification/email, containing your own email template as well as all the information Tanker needs to send your email.

The request needs to be in the following format:

POST /verification/email

// JSON body:
{
    "app_id": <app_id>,
    "auth_token": <auth_token>,
    "email_data": {
        "subject": <subject>,
        "html": <html body>,
        "text": <text body>,
        "from_name": <from name>,
        "to_email": <recipient email address>,
        "to_name": <recipient name>
    }
}

The app ID and auth token are used to authenticate your server with the email verification service. They both can be found in your dashboard, in the app's settings.

The email's body should contain the TANKER_VERIFICATION_CODE placeholder. Tanker will use this placeholder to insert the verification code in the email.

See the API documentation for more details about this API.

Note

The user's email address is never stored in plain text on Tanker's servers. It is simply checked against the hashed value previously set up, and used once to send the email.

Here is an example with text only email body:

package server

import (
    "bytes"
    "encoding/json"
    "net/http"
)

type emailData struct {
    Subject   string `json:"subject"`
    HTML      string `json:"html"`
    Text      string `json:"text"`
    FromName  string `json:"from_name"`
    ToEmail   string `json:"to_email"`
    ToName    string `json:"to_name"`
}

type requestStruct struct {
    AppID          string    `json:"app_id"`
    AuthToken      string    `json:"auth_token"`
    EmailData      emailData `json:"email_data"`
}

func SendEmailWithTanker(email string, userName: string) error {
    emailText := "Here is the code needed to verify your identity: TANKER_VERIFICATION_CODE"

    body := requestStruct{
        AppID:     <AppID>,
        AuthToken: <AuthToken>,
        Email: emailData{
            Subject:   "Verification code",
            Text:      emailText,
            FromName:  "My application",
            ToEmail:   email,
            ToName:    userName,
        },
    }

    req, _ := json.Marshal(body)
    resp, err := http.Post("https://api.tanker.io/verification/email", "application/json", bytes.NewReader(req))
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    if resp.StatusCode != 200 {
        return errors.New("Error while sending verification email. Status: " + resp.StatusCode)
    }
    return nil
}

You're now ready to install the client-side Tanker SDK in your application.