# Authentication & authorization Secure your application and authorize Sinch client (user) registrations. When you start `SinchClient` you must provide a user identity. The first time the application instance and the Sinch client run on behalf of a particular user, they must register with the Sinch service. Registration requires a token that authenticates the application and authorizes the user to register. After successful registration, the client obtains credentials to perform authorized requests on behalf of the application and that user, including making and receiving calls. ## Token-based user registration To authorize user registration, the application must provide a registration token to the `SinchClient`. This token should be a [JSON Web Token (JWT)](https://jwt.io/) signed with a key derived from the application secret. We recommend keeping the application secret securely on your backend, generating and signing the token on the server, then sending it over a secure channel to the application and Sinch client running on the device. ![Token-based User Registration](/assets/20210125-token_based_user_registration.pu.e41074ddc272a5f21b56c7f6434eda8006530056db06f46418fe39bdfa51e573.b66a954b.png) The following sections describe how to create and sign the JWT, and how to provide it to the `SinchClient`. ## Creating a registration token ### JWT header A registration token is a *JWT* with the following JWT header parameters: | Header Parameter | Value | Note | | --- | --- | --- | | `alg` | `HS256` | | | `kid` | `hkdfv1-{DATE}` | Where `{DATE}` is current date in UTC on format `YYYYMMDD` | Example of JWT header: ```json { "alg": "HS256", "kid": "hkdfv1-20200102" } ``` Header date The `{DATE}` used in the `kid` parameter must be the current UTC date at the time the challenge is made (when `onCredentialsRequired` is called). ### JWT claims The JWT must contain the following *claims*: | Claim | Value / Description | | --- | --- | | `iss` | `//rtc.sinch.com/applications/{APPLICATION_KEY}` | | `sub` | `//rtc.sinch.com/applications/{APPLICATION_KEY}/users/{USER_ID}` | | `iat` | See [JWT RFC 7519 section-4.1.1](https://tools.ietf.org/html/rfc7519#4.1.1) | | `exp` | See [JWT RFC 7519 section-4.1.4](https://tools.ietf.org/html/rfc7519#4.1.4) | | `nonce` | A unique cryptographic [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) | Token expiry Set the token expiration (`exp`) so that the token TTL is at least 1 minute. ### Signing the JWT The *JWT* should be signed using a *signing key* derived from the *Sinch Application Secret* as follows. Given: - A function `HMAC256(message, key)`. - A date-formatting function `FormatDate(date, format)`. - The current date as variable `now`. - *Sinch Application Secret* as variable `applicationSecret`, holding the secret as a *base64* encoded string. Derive the signing key as follows: ```text signingKey = HMAC256(BASE64-DECODE(applicationSecret), UTF8-ENCODE(FormatDate(now, "YYYYMMDD"))) ``` Note: Implementations of hash hmac256 to derive the key vary from language to language in terms of the order of the key, data and sometimes the hashing algorithm arguments passed, please pay attention to this. ### Examples Given the following input: - *Application Key* = `a32e5a8d-f7d8-411c-9645-9038e8dd051d` - *Application Secret* = `ax8hTTQJF0OPXL32r1LHMA==` (in *base64* encoded format) - *User ID* = `foo` - *nonce* = `6b438bda-2d5c-4e8c-92b0-39f20a94b34e` - Current time: `2018-01-02 03:04:05 UTC` - JWT expiry = 600 seconds (`exp` will be set to 600 seconds after `iat`) We can construct a JWT as follows: **JWT header**: ``` { "alg": "HS256", "kid": "hkdfv1-20180102" } ``` **JWT payload**: ``` { "iss": "//rtc.sinch.com/applications/a32e5a8d-f7d8-411c-9645-9038e8dd051d", "sub": "//rtc.sinch.com/applications/a32e5a8d-f7d8-411c-9645-9038e8dd051d/users/foo", "iat": 1514862245, "exp": 1514862845, "nonce":"6b438bda-2d5c-4e8c-92b0-39f20a94b34e" } ``` **Derived signing key**: The derived signing key would in this case be `AZj5EsS8S7wb06xr5jERqPHsraQt3w/+Ih5EfrhisBQ=` (*base64* encoded format) **Final encoded JWT**: Encoded output: The encoded JWT output below contains both the JSON header and payload as shown above, with the claims in exactly the same order as the example and the JSON in minified format. ```json eyJhbGciOiJIUzI1NiIsImtpZCI6ImhrZGZ2MS0yMDE4MDEwMiJ9.eyJpc3MiOiIvL3J0Yy5zaW5jaC5jb20vYXBwbGljYXRpb25zL2EzMmU1YThkLWY3ZDgtNDExYy05NjQ1LTkwMzhlOGRkMDUxZCIsInN1YiI6Ii8vcnRjLnNpbmNoLmNvbS9hcHBsaWNhdGlvbnMvYTMyZTVhOGQtZjdkOC00MTFjLTk2NDUtOTAzOGU4ZGQwNTFkL3VzZXJzL2ZvbyIsImlhdCI6MTUxNDg2MjI0NSwiZXhwIjoxNTE0ODYyODQ1LCJub25jZSI6IjZiNDM4YmRhLTJkNWMtNGU4Yy05MmIwLTM5ZjIwYTk0YjM0ZSJ9.EUltTTD4fxhkwCgLgj6qSQXKawpwQ952Ywm3OwQSARo` ``` More detailed examples on how to implement this in various languages, including reference data for unit tests, is available at [https://github.com/sinch/sinch-rtc-api-auth-examples](https://github.com/sinch/sinch-rtc-api-auth-examples). For additional information about *JWT*, along with a list of available libraries for generating signed *JWTs*, see [https://jwt.io](https://jwt.io). For detailed information about the *JWT* specification, see [https://tools.ietf.org/html/rfc7519](https://tools.ietf.org/html/rfc7519). ## Providing a registration token to `SinchClient` When starting the client (`SinchClient.start()`), the client will ask for a token via [SinchClientListener.onCredentialsRequired()](https://download.sinch.com/js/latest/reference/interfaces/SinchClientListener.html). ```javascript const sinchClient = Sinch.getSinchClientBuilder() .applicationKey("") .environmentHost("ocra.api.sinch.com") .userId("") .build(); sinchClient.addListener(sinchClientListener); sinchClient.start() ``` In your `SinchClientListener`: ```javascript onCredentialsRequired: (sinchClient, clientRegistration) => { yourAuthServer .getRegistrationToken(sinchClient.userId) .then((token) => { clientRegistration.register(token); }) .catch(() => { clientRegistration.registerFailed(); }); }; ``` Note: The client may also ask for a token on subsequent starts via [onCredentialsRequired()](https://download.sinch.com/js/latest/reference/interfaces/SinchClientListener.html#onCredentialsRequired). Only then should you provide a new JWT. If you receive "Instance creation rate exceeded" messages on user registration, verify you are using [onCredentialsRequired()](https://download.sinch.com/js/latest/reference/interfaces/SinchClientListener.html#onCredentialsRequired) correctly and investigate why your app is re‑registering the same user so frequently. If you are not sure, contact support. ## Limiting client registration with expiration time Depending on your security requirements, you may want to limit a client registration time-to-live (TTL). Limiting the client registration will effectively limit the Sinch client acting on behalf of the *User* on the particular device after the TTL has expired. This will prevent the client from making or receiving calls after the registration TTL has expired. To limit the registration in time, create the *JWT* as described in the sections above, but with the additional claim `sinch:rtc:instance:exp`. The value for this claim should be in the same format as claims `iat` and `exp`, that's a JSON numeric value representing the number of seconds since *Unix Epoch* (UTC). **Example JWT payload**: ```json { "iss": "//rtc.sinch.com/applications/a32e5a8d-f7d8-411c-9645-9038e8dd051d", "sub": "//rtc.sinch.com/applications/a32e5a8d-f7d8-411c-9645-9038e8dd051d/users/foo", "iat": 1514862245, "exp": 1514862845, "nonce":"6b438bda-2d5c-4e8c-92b0-39f20a94b34e", "sinch:rtc:instance:exp": 1515035045 } ``` Important! TTL of the registration must be `>=` 48 hours. In other words: `sinch:rtc:instance:exp - iat >= 48 * 3600`. When a Sinch client registers with a User registration token, the registration is also bound to the particular device. Limiting the TTL of the registration is device-specific and doesn't affect other potential registrations for the same *User* on other devices. Don't confuse `sinch:rtc:instance:exp` with the standard JWT claim [`exp`](https://tools.ietf.org/html/rfc7519#section-4.1.4) - they're separate claims. The former is for limiting the client registration. The latter is only for limiting the TTL of the JWT itself. Recommendation We recommend a 12 months expiry, unless you have reasons to keep it shorter. Important! The instance expiry specified in `sinch:rtc:instance:exp` will be used as the: 1. Initial instance expiry when a new instance is created 2. New instance expiry when an existing instance tries to prolong its lifetime ### Automatic extension of client registration Time-to-Live (TTL) The Sinch client will automatically request to extend the TTL of its registration by invoking SinchClientListener.onCredentialsRequired() The request to extend the client registration TTL is triggered when the Sinch client is started and the expiry of TTL is detected to be *near* in the future. *"Near in the future"* is subject to internal implementation details, but the Sinch client will try to eagerly extend its registration and will adjust the interval according to the TTL. TTL constraints You can't provide a JWT without specifying registration TTL if a JWT with limited TTL has been used before for the given user on the specific device. Once a registration has been constrained with TTL, it can be extended in time, but not indefinitely.