Authentication & Authorization
Secure your application and authorize Sinch client (user) registrations.
A user identity must be provided when initiating a Sinch client. The first time the application instance and the Sinch client are running on behalf of a particular user, it's required to register against the Sinch service. The step of registering a user identity against the Sinch service requires the application instance to provide a token that authenticates the Application and grants permission (authorizes) the user to register. Once the application instance has successfully registered the user identity, the client will have obtained the necessary credentials to perform further authorized requests on behalf of the Application and for that specific user to make and receive calls.
Token-based User Registration - Overview
To authorize the registration of a user, the application must provide a registration token to the SINClient
. This token should be in the form of a JSON Web Token (JWT) signed with a signing key derived from the Application Secret.
The recommended way to implement this authentication scheme is that the Application Secret should be kept securely on your server-side backend, and the signed token should be created and signed on your server, then passed via a secure channel to the application instance and Sinch client running on a device.
The following sections describes in detail how to create and sign the JWT, and how to provide it to the SINClient
.
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:
{
"alg": "HS256",
"kid": "hkdfv1-20180102"
}
Note:
The {DATE}
passed into the kid
parameter has to be valid current date at the time the challenge is made (requiresRegistrationCredentials
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 |
exp |
See JWT RFC 7519 section-4.1.4 |
nonce |
A unique cryptographic nonce |
Important!
The expiration time for the token itself (exp
) should be set so that the Time-to-Live of the token is not less than 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(key, message)
. -
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:
signingKey = HMAC256(BASE64-DECODE(applicationSecret), UTF8-ENCODE(FormatDate(now, "YYYYMMDD")))
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 afteriat
)
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:
Note:
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.
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.
For additional information about JWT, along with a list of available libraries for generating signed JWTs, see https://jwt.io. For detailed information about the JWT specification, see https://tools.ietf.org/html/rfc7519.
Providing a Registration Token to SINClient
When starting the client (-[SINClient start]
) the client will ask for a token via -[SINClientDelegate client:requiresRegistrationCredentials:]
.
NSError *error;
id<SINClient> client = [Sinch clientWithApplicationKey:@"<application key>"
environmentHost:@"ocra.api.sinch.com"
userId:@"<user id>"
error:&error];
client.delegate = ...;
[client start];
Provide the JWT Token issued by your server-side backend
- (void)client:(id<SINClient>)client
requiresRegistrationCredentials:(id<SINClientRegistration>) registrationCallback {
[yourAuthServer getRegistrationToken:[client userId]
onSuccess:(NSString* token)^{
[registrationCallback registerWithJWT:token];
}
onFailure:^(NSError* error) {
// Notify Sinch client of failure (example if your backend auth server rejects the
// user, but also if the request to the auth server fails due to temporary
// network connectivity issues.
[registrationCallback registerDidFail:error];
}];
}
Note:
The client MAY also ask for a registration token on subsequent starts via -client:requiresRegistrationCredentials: and only then should provide a new JWT.
If you receive Instance creation rate exceeded
messages on user registration, please verify you are using -client:requiresRegistrationCredentials: correctly and investigate why your application is re-registering the same user with such frequency. If you are not sure, please 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, effectively preventing the client to make or receive 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
, a JSON numeric value representing the number of seconds since Unix Epoch (UTC).
Example 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",
"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
- 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:
- Initial instance expiry when a new instance is created
- 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 -[SINClientDelegate client:requiresRegistrationCredentials:]
(just as it does on initial start and first registration.)
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 regularly try to extend its registration and will adjust the interval according to the TTL.
Note:
You can't provide a JWT without specifying registration TTL if a JWT with a limited TTL has been used before for the given User on the specific device. Once a Sinch client registration has initially been constrained with a TTL, the registration can be extended in time, but not extended indefinitely.