Authentication

When a client makes a request to Chatkit, we need to be able to securely identify who they are. This is the process of authentication. Clients are provided with signed JSON Web Tokens (JWTs) that Chatkit can verify for every request that a client makes. Clients obtain JWTs by defining a token provider, which is responsible for providing a client with a valid JWT when necessary.

The JWT is signed with a private key and contains the user's ID and your Chatkit instance ID. When Chatkit receives this token, it verifies it was signed using the private key, which only you should have access too, and correctly identifies the client.

We have provided a test token provider to get you started quickly and our server SDKs provide functionality to produce your own token providers. The authentication flow below will lead you through the authentication process. Alternatively you can generate your own tokens.

The Authentication Flow

Define a Token Provider

Before a client is able to make a request to Chatkit, they require a valid JWT to prove who they are. The first step in this process is defining a token provider, which will provide the client with a token.

In the following examples we will use the Swift SDK, although the same flow should also be followed for the JS and Android SDKs. In the Chatkit Swift SDK, you define an object that conforms to the PCTokenProvider protocol and pass it as a parameter when instantiating your ChatManager object.

1
2
3
4
5
6
7
let tokenProvider = YourTokenProvider()

let chatManager = ChatManager(
    instanceId: "your-chatkit-instance-locator",
    tokenProvider: tokenProvider,
    userId: "your-user-id"
)

You are able to use your own token provider or use our provided test token provider endpoint.

Using Your Own Token Provider

There is a PCTokenProvider that is a part of the SDK which you can use as your token provider. Here's an example of how you can use it:

1
2
3
4
5
6
7
let tokenProvider = PCTokenProvider(
    url: "https://your-endpoint.com/auth",
    requestInjector: { req -> PCTokenProviderRequest in
        req.addQueryItems([URLQueryItem(name: "user_id", value: userId)])
        return req
    }
)

The requestInjector parameter is optional but will come in handy if you want to make a request to an authentication endpoint you've set up on your server and need to add a query parameter, or a body to the request, or even change the HTTP method being used.

Using the Test Token Provider

While you're trying out Chatkit and testing your integration you can also use the PCTestingTokenProvider that is part of the Swift SDK. All you need to do is provide the PCTokenProvider with your test token provider URL, which can be found on the dahsboard, and your client will receive back a valid token. This functionality can be turned on and off in your application dashboard.

Here's an example of using the PCTokenProvider with a test token provider URL:

1
2
3
let tokenProvider = PCTokenProvider(
    url: "YOUR_TEST_TOKEN_PROVIDER_URL_FROM_THE_DASHBOARD"
)

While perfect for getting up and running, the test token provider should only be used for testing purposes and disabled before your Chatkit application is in production. It does not perform any checks as to who the client is. This is something that you would need to do as part of your authentication process.

Request a Token

Once the ChatManager is created with a token provider, the client SDK will connect to the Chatkit servers. As every Chatkit request requires authentication, a valid JWT is needed. The Chatkit SDK will use the supplied PCTokenProvider to obtain a token.

The PCTokenProvider object will first check for cached, unexpired tokens and return those. If none are available it will make a request to the token provider to generate a new token with the user ID that the ChatManager was instantiated with.

If you're making a http request directly to the test token provider please use this HTTP reference.

Token Provider: Generate a Token

The token provider receives a request from a client indicating that it requires a new token. You may be using the test token provider, but for this example we'll assume you have your own token provider endpoint up and running. Your token provider will receive the request, do any authentication steps you see fit, and then respond with a valid token for the client.

All of the Chatkit server SDKs provide authentication helpers. The helpers give you what you need to be able to return tokens to your Chatkit clients. Below are examples of how to authenticate users using the server SDKs:

  • JavaScript
  • Ruby
  • PHP
  • Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Example using Express

const chatkit = new Chatkit.default({
  instanceLocator: 'your:instance:locator',
  key: 'your:key'
});

app.post('/auth', (req, res) => {
  const authData = chatkit.authenticate({
    userId: req.query.user_id
  });

  res.status(authData.status)
     .send(authData.body);
})

It's also possible to generate tokens without the help of the server SDKs using a JWT library or your own custom JWT implementation. Find more information on JWT format and signing methods here.

Client: Make Chatkit Request With Token

Now that the client has obtained a JWT from the token provider, it can make requests to Chatkit. By including the token, Chatkit can correctly identify the client. The token is added to the Chatkit HTTP request under the Authorization header, in the format Bearer <INSERT_TOKEN_HERE>, this is managed by the Swift SDK but you can use the token in your own custom HTTP requests to the Chatkit service as well.

Sudo Tokens

Some endpoint we consider as out of scope for general users, for instance you probably don't want your users to be able to delete one another. For this reason we have the concept of sudo tokens. Sudo tokens are a requirement for authentication for some endpoints, namely chatkit user creation and deletion and all roles and permisions endpoints.

If you are using the server SDKs sudo token generation will be handled for you automatically when they are required. If you are generating your own tokens then you will need to add the "su" claim when using the create or delete user endpoints, more details about adding this JWT claim can be found in the next section.

Generating Your Own Tokens

It's also possible to generate tokens without the help of the server SDKs, using a JWT library or your own custom JWT implementation. This site provides a useful list of libraries for token signing and verification and the RFC document defines the JWT standard if you would like to make a custom implementation.

Only HS256 (HMAC with SHA-256) encoded JWTs are accepted for Chatkit, so please use this signing method. Chatkit requires the following JWT payload:

  • instance: Your instance ID (the last field of the service instance locator)
  • iss: An identifier for the key used to sign the token, has the format “api_keys/<key ID>”
  • iat: The unix timestamp when the token was issued (seconds)
  • exp: The unix timestamp when the token expires; this should be later than iat
  • sub: User ID
  • su: true: Optional sudo token claim, required for the user creation and deletion endpoints

For example:

1
2
3
4
5
6
7
{
  "instance": "<instance ID>",
  "iss": "api_keys/<key ID>",
  "iat": 1508752709,
  "exp": 1508839109,
  "sub": "BrockSampson"
}

Chatkit Key and Instance ID

The third part of your service instance locator is the instance ID (available on your dashboard), this is required as the app component of the token payload, as shown above as <instance ID>.

Your Chatkit key (also available on your dashboard) has the format <key ID>:<key secret>. The <key secret> is used to sign the token, this is the private part of key and should remain secret. The <key ID> is provided in the iss claim so that we can verify the signature.

For example, we would sign the following payload with <key secret>:

1
2
3
4
5
6
7
{
  "instance": "<instance ID>",
  "iss": "api_keys/<key ID>",
  "exp": 1508839109,
  "iat": 1508752709,
  "sub": "MasterShake"
}

The resulting string is sent via your HTTP request's Authorization header in the following format

1
Authorization: Bearer <signed_token>

What's Next?

Now that you've read up on authentication, where we verify the client is who they claim, a good next step would be to take a look at how roles and permissions work, making sure clients have the correct permission to carry out their requests.

Did you find this document useful?

We are always striving to create the most accurate and informative docs as possible. If there is something especially wrong (or right) here then please let us know.