Authentication

Every user has to authenticate with Layer before using any Layer functionality. Authenticating with Layer may happen separately from logging into your app (especially if your app has functionality beyond messaging). There is also a corresponding deauthenticate action for authenticated users.

Layer implements a federated authentication flow, which means that it’s up to you to verify user login credentials, and then tell Layer that the user should be authenticated. This means that you must provide a custom service to verify user credentials. We do not provide this functionality.

At a high level, there are three main steps in the authentication flow:

  1. You request a nonce from Layer, which is a unique string used to identify a single authentication request.
  2. You send the nonce, along with the user’s login credentials, to your login backend.
  3. If the login credentials are correct, you generate an identity token and send it back to Layer.

We will verify your identity token, and if it looks good, we’ll let your app know that it has been authenticated. The whole flow looks like this:

Authentication flow diagram for web

Note

Nonces are only intended to be used once. Furthermore, they expire 10 minutes after they’ve been generated. For this reason, we recommend you do not store nonces anywhere. If you attempt to use a nonce that has been used or that has expired, the authentication flow will fail.

You can request a nonce at any point, as often as you’d like.

Your app can begin the authentication flow at any point before you try to load conversations or send/receive messages. If your app has captured user credentials at some other point, the entire flow can occur in the background without any user intervention.

Authenticating

/*
 * 1. Instantiate your client.
 */
var client = new layer.Client({
    appId: "layer:///apps/staging/YOUR-APP-ID",
    isTrustedDevice: false
});

/*
 * 2. On receiving a nonce via the `challenge` event,
 *    Connect to your backend to generate an Identity Token (see below). In addition
 *    to your Layer App ID, User ID, and nonce, you can choose to pass in any other
 *    parameters that make sense (such as a password), depending on your App's login
 *    process.
 */
client.on('challenge', function(evt) {
    // evt has properties `evt.nonce` and `evt.callback`.
    getIdentityToken(evt.nonce, function(identityToken) {
        /*
         * 3. Submit identity token to Layer for validation
         */
        evt.callback(identityToken);
    })
});

/*
 * 4. The `ready` event is triggered once the identity token has been
 *    validated and a Layer session created.
 */
client.on('ready', function() {
    renderMyUI(client);
});

/*
 * 5. Now that all your event handlers are setup, start the authentication process.
 *    `connect()` will obtain a nonce; which
 *    is valid for 10 minutes after creation.
 */
client.connect(myUserId);

In step 2 above, getIdentityToken is a function you provide to get an identity token from your backend. It might look something like this:

function getIdentityToken(nonce, callback) {
    xhr({
        url: 'https://myservice.com/identity',
        method: 'POST',
        data: {
            nonce: nonce
        }
    }, function(result) {
        callback(result.identity_token);
    });
}

Reusing previous authorization

When the page is reloaded, the Web SDK will try to restore the previous session. However, it will only do this if the Client’s isTrustedDevice property is true, and if you provide a userId parameter that matches the userId from the previous session:

var client = new layer.Client({
  appId: "layer:///apps/staging/YOUR-APP-ID",
  isTrustedDevice: true
});
client.connect('Frodo_the_Dodo');
  • If there is no session cached for “Frodo_the_Dodo”, then the challenge event will be emitted.
  • If there is a session but it has expired, then the challenge event will be emitted.
  • If there is a session and it is valid, the ready event will be emitted.

Alternate authentication process

You can perform most of the authentication flow on your backend server, and connect the Layer Web SDK using a session token. The Client API documents how to use the REST API to get a nonce, Identity Token, and Session Token:

  1. User attempts to log into your web site
  2. Your server requests a nonce from Layer
  3. Your server uses that nonce to create an Identity Token
  4. Your server submits that Identity Token to Layer and gets a Session Token back
  5. Your server responds to the login request, and passes back the Session Token
  6. Connect the client using the Session Token
var client = new layer.Client({
  appId: "layer:///apps/staging/YOUR-APP-ID",
});
client.connectWithSession('Frodo_the_Dodo', 'session-token');

There are trade-offs between the standard method and this alternate method:

  • The standard process lets authentication happen at any time; for sites where chat may not be the first thing the user does, this may be ideal.
  • Logging in via the alternate method requires that the user wait for a request for a nonce, and then a request for a session token — this could lead to slower logins.
  • The main advantage of the alternate process is that the time spent logging in makes a nice and simple place to do any additional authentication and be done with it.

Identity token

The identity token in the code above comes from your server. Your backend should generate this token when you provide it with valid authentication credentials for your users (typically username/email and password, although it can be a phone number or some other identifier as well). Typically, your app would request this information from the user, and pass it to your server. Your server will also need to know your Layer app ID, which you can either hard-code on the server, or pass up from the app. Finally, you will also need to pass up the nonce from the client to your server.

Common mistake

Make sure you are not modifying or processing the nonce in any way. Note that nonces are already URL-safe. Often, developers will (accidently or otherwise) url-decode the nonce, which results in plus signs (+) in the nonce being converted into spaces. This breaks the identity token.

An identity token is a JSON Web Token that describes the account details of a user within your application. The identity token consists of two parts, both JSON objects — a header (known as a “JOSE Header”) and the account details (known as the “JWT Claims Set”). These two parts are combined into a single string. This is the structure of both parts:

// JOSE Header
{
  "typ": "JWT", // String: Indicates a MIME Type of application/JWT
  "alg": "RS256", // String: Indicates the type of algorithm used to sign the token. Must be RS256
  "cty": "layer-eit;v=1", // String: Indicates a Content Type of Layer External Identity Token, version 1
  "kid": "layer:///keys/cd8c286e-f2e4-11e5-99fe-eecb000000b0" // String: Layer Key ID used to sign the token.
}

// JWT Claims Set
{
  "iss": "layer:///providers/cf0eb712-d9ab-11e5-b6a9-c01d00006542", // String: The Layer Provider ID
  "prn": "APPLICATION USER ID", // String: The ID you use to identify the user. Could be a username, email, or user ID value
  "iat": 1461023254, // Integer: Time the token was generated as an epoch timestamp
  "exp": 1461023314", // Integer: An arbitrary time in the future when this token should expire. Also an epoch timestamp
  "nce": "abcNONCE123", // String: The nonce obtained from the client.
  "first_name" : "Firstname", // Optional String: First name for the user
  "last_name" : "Lastname", // Optional String: Last name for the user
  "display_name" : "displayname", // Optional String: The name to show onscreen for the user
  "avatar_url" : "https://example.com/image.jpg" // Optional String: URL to profile photo for the user
}

You can get the Authentication Key (used for the kid field in the header) and the Provider ID (used for the iss field in the claims) from the Developer Dashboard.

Note

You determine when the token becomes invalid by setting the expiration time (exp field). If we receive your token after this expiration time, authentication will fail. However, it does not affect any other client behavior — notably, users will not be logged out when the identity token expires.

We recommend setting the expiration time at least 30 seconds into the future. It doesn’t make sense to set it further than 10 minutes into the future, as the nonce will have expired by that point. It doesn’t make sense to cache/save the identity token in your database for the same reason.

An identity token is sent back as a securely signed string, which looks nothing like the original JSON. This can be difficult to do correctly. Fortunately, prebuilt JWT libraries are available for many languages:

To make this easier, we provide sample backends:

There are also third-party libraries that generate identity tokens for you. Note that we cannot provide support for these libraries:

If you built your own library and want to be included in this list, send an email to support@layer.com.

Best practice

If you have an issue with your identity token, please make sure it is valid before contacting support.

We provide a validation tool to help you make sure all the parts of your token are valid. To use, generate an identity token from your backend and paste it into the tool. We’ll let you know if it looks good or not.

Note that this tool does not check your token’s expiration time, or whether your nonce has expired.

The validation tool is available from the Developer Dashboard.

Deauthenticating

Deauthenticating with Layer “logs out” the user from Layer, preventing them from sending and receiving messages or notifications. Depending on what your app does, this could happen separately from logging out of your app itself.

Deauthenticating will delete locally stored data (which includes the user’s conversations and messages). In addition, the Layer client will be disconnected. If you want to authenticate another user, you’ll have to re-connect the Layer client.

You can deauthenticate at any point in your app:

client.logout()

This will emit a deauthenticated event, to which you can add an event handler:

client.on('deauthenticated', function() {
  showLoginPage();
});

Note

Deauthenticating is an asynchronous operation. Don’t do anything Layer-related (including authenticating a new user) until the deauthenticated callback has been triggered.

Finally, note that sessions expire after roughly one month, at which point the deauthenticated event will be emitted. Expiration time is determined by the time the session was first generated — noteworthy if you are using connectWithSession().

Note

Staging application sessions expire every 5 minutes so that you can bullet proof your reauthentication code.

Connecting Identities