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


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.


 * 1. Instantiate your client.
var client = Layer.init({
    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

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

 * 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.

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) {
        url: '',
        method: 'POST',
        data: {
            nonce: nonce
    }, function(result) {

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 = Layer.init({
  appId: "layer:///apps/staging/YOUR-APP-ID",
  isTrustedDevice: true
  • 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 = Layer.init({
  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.

Multiple Authenticated Tabs

For a web application, tabs can have two meanings:

  • Tabs within your application
  • Tabs representing distinct windows within your web browser

Authenticating with Multiple Users

For tabs within your application, the Layer Client can only authenticate as a single user and for a single application ID. There is no way at this time within a single browser tab to authenticate as multiple users or multiple application IDs.

For a browser that has multiple windows or tabs open, the story is somewhat different:

  • Each tab manages its own authentication and its own websocket
  • Each tab may be used to authenticate as a separate user or separate Application ID
  • The WebXDK will write user info and Session Tokens to the browser’s localStorage if the Layer Client is initialized with isTrustedDevice: true
    • This will cause other tabs with different users to overwrite this data. While this should still work and be safe, it is best to change to isTrustedDevice: false (which is default)

Authenticating with a Single User

If each tab is authenticating as the same user, tabs may share a single Session Token, or may each generate their own Session Token. If isTrustedDevice: true then they will try to share, this is done by having the first tab write the Session Token to localStorage and the other tabs will read from that.

There are conditions however where this does not work well.

  1. Opening 10 tabs/windows at once, and all of them will see that there is no Session Token yet in localStorage and all will generate their own all at the same time
  2. Opening 10 tabs and have them find in localStorage a Session Token that will expire soon. Once it expires, all 10 will try and reauthenticate at once

These patterns lead to your server and Layer’s server getting hammered with authentication requests and is best avoided, especially if there are no constraints on how many tabs may be involved.

If your application follows a pattern where its expected to open many tabs all with the same authenticated user, it is recommended to designate a master tab/master window that handles authentication and reauthentication, and to have all other tabs receive their Session Token through some other means such as window.postMessage or monitoring localStorage for new Session Tokens. These other tabs would implement an empty client.on('challenge', function() {}) and would not attempt to authenticate/reauthenticate but would simply wait for a Session Token from the master tab.

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" : "" // 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.


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

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 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:


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

client.on('deauthenticated', function() {


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().


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

When Users Open Multiple Browser Tabs

If your user has openned more than one tab that connects to Layer’s servers, its important to understand how this will behave.

If isTrustedDevice is used

If isTrustedDevice is used, then the Session Token will be written to localStorage, and will be shared with all tabs. If the user logs out of one tab, it deletes the Layer Session for all tabs. Typically this is good; typically what actually happens:

  • User clicks to log out of your application
  • Your application calls client.logout() which delete’s the Layer Session Token shared by all tabs
  • Your application deletes any Session Tokens used by your own Web Server
  • All tabs should no longer be authenticated with your server nor with Layer’s Server

Note that there are special cases where authentication starts in multiple tabs at the same time; in this case tabs will not share a Session Token; see the next section for how this should be handled.

If isTrustedDevice is not used

If the Session Token is not stored in localStorage, then the Session Token is not shared among tabs of your browser. Typically what happens:

  • User clicks to log out of your application
  • Your application calls client.logout() which delete’s the Layer Session Token of one tab only
  • Your application deletes any Session Tokens used by your own Web Server
  • All other tabs have also lost their Session Tokens on your own Web Server
  • All other tabs still have a Layer Session Token that you must delete as they are still valid


For each tab that loses its authentication, its important to call logout() on your Layer Client to insure that all Session Tokens are deleted. While the security risk of someone finding this token is small, best practice is to detect when your web application’s session has been terminated and insure that the Layer Session Token is also terminated.

Connecting Identities