Authenticate with JWT assertion token

ClearID Developer Guide

Content type
Guides > Developer guides
Product line
ClearID
Language
English
Applies to
Genetec ClearID

OAuth 2.0 and JSON Web Token (JWT) are the authentication methods used by Genetec ClearID™ to implement machine-to-machine authentication. The ClearID Secure Token Service (STS) is responsible for authenticating the client machine through OAuth and returning a JWT bearer token once authenticated, which allows users to access the API.

To use the ClearID API, the client application must authenticate with the token endpoint of the Secure Token Service (STS). This service returns an access token that remains valid for one hour. The access token can be used to access the API Endpoints.


image

ClearID uses JWTs as Authorization Grants as detailed in RFC 7523 section 2.1.

How to authenticate with the Token Endpoint

To authenticate, a POST request must be sent to the Secure Token Service (STS) endpoint /connect/token.

The token endpoints expects the POST Method to have three parameters in the HTTP body:

  • client_id: This information is contained in the JSON file downloaded from ClearID.

  • grant_type: It should always be urn:ietf:params:oauth:grant-type:jwt-bearer.

  • assertion: it is a JWT in base 64 see the details later in this article.

The context type is always: application/x-www-form-urlencoded.

Example of POST data sent for /connect/token:

json
client_id = 6625221f-4e66-4bc8-8305-cb8cbd87b21f:cleariddemos
grant_type = urn:ietf:params:oauth:grant-type:jwt-bearer
assertion = eyJhbGciOiJSUzUxMiIsImtpZCI6IjY2MjUyMjFmLTRlNjYtNGJjOC04MzA1LWNiOGNiZDg3YjIxZjpjbGVhcmlkZGVtb3MiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiI2NjI1MjIxZi00ZTY2LTRiYzgtODMwNS1jYjhjYmQ4N2IyMWY6Y2xlYXJpZGRlbW9zIiwianRpIjoiYzBkYTYyNWY0ZjYxNDNiNmFiOGIwMWRmYjJkNzU1YjciLCJuYmYiOjE2Mzk4NDM4OTQsImV4cCI6MTYzOTg0NzQ5NCwiaWF0IjoxNjM5ODQzODk0LCJpc3MiOiI2NjI1MjIxZi00ZTY2LTRiYzgtODMwNS1jYjhjYmQ4N2IyMWY6Y2xlYXJpZGRlbW9zIiwiYXVkIjoiaWFtcy1zdHMifQ.XU1HJDxE2mBjPDtHl65BUQAcWf42LXJw-pcUL5kQjKlGuD_a5H20Chq6F5K7Ov-XfM5sYpKRj4gDczVRDhVJqblAa5h54E13iuobFvnDZDQViTwrsPHvGOtSifDl3qw1hhljaYDvX7PAOvnSYG3hHAOvNpFvLxbqlAE8PgAx2v1Z-PCu0jJfa9djLcHWFINL3xiYo0VF-Jex2-N8nx8-xT5mFOIlO6D5Zp74frR5Anc7JP1BvPfYNgLmNSCir7ogT-KwFVxS8QedMDuSV038BRVTDOQ-NH-FHHrlNKIirgeWgoYscTXtD9j15nXj-bEgQFMCg-ZxxUtZ67OCJyzmsg

Since it is URL encoded, the resulting HTTPS request looks like this:

Sample request

json
POST /connect/token
Host: sts.clearid.io
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Content-Length: 897

    client_id=6625221f%2D4e66%2D4bc8%2D8305%2Dcb8cbd87b21f%3Acleariddemos
    grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant%2Dtype%3Ajwt%2Dbearer&
    assertion=eyJhbGciOiJSUzUxMiIsImtpZCI6IjY2MjUyMjFmLTRlNjYtNGJjOC04MzA1LWNiOGNiZDg3YjIxZjpjbGVhcmlkZGVtb3MiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiI2NjI1MjIxZi00ZTY2LTRiYzgtODMwNS1jYjhjYmQ4N2IyMWY6Y2xlYXJpZGRlbW9zIiwianRpIjoiYzBkYTYyNWY0ZjYxNDNiNmFiOGIwMWRmYjJkNzU1YjciLCJuYmYiOjE2Mzk4NDM4OTQsImV4cCI6MTYzOTg0NzQ5NCwiaWF0IjoxNjM5ODQzODk0LCJpc3MiOiI2NjI1MjIxZi00ZTY2LTRiYzgtODMwNS1jYjhjYmQ4N2IyMWY6Y2xlYXJpZGRlbW9zIiwiYXVkIjoiaWFtcy1zdHMifQ.XU1HJDxE2mBjPDtHl65BUQAcWf42LXJw-pcUL5kQjKlGuD_a5H20Chq6F5K7Ov-XfM5sYpKRj4gDczVRDhVJqblAa5h54E13iuobFvnDZDQViTwrsPHvGOtSifDl3qw1hhljaYDvX7PAOvnSYG3hHAOvNpFvLxbqlAE8PgAx2v1Z-PCu0jJfa9djLcHWFINL3xiYo0VF-Jex2-N8nx8-xT5mFOIlO6D5Zp74frR5Anc7JP1BvPfYNgLmNSCir7ogT-KwFVxS8QedMDuSV038BRVTDOQ-NH-FHHrlNKIirgeWgoYscTXtD9j15nXj-bEgQFMCg-ZxxUtZ67OCJyzmsg

The STS base address is different depending on the environment that you have. Currently, there are two different base addresses. In the future, there may be more addresses added.

Do not hardcode it in your code. You can find the base URL in the JSON file downloaded from ClearID. See the next section to find out more.

 

If the authentication succeeds, the Secure Token Service (STS) returns an access token of the type "Bearer".

The response should look like the example below.

The expires_in key contains the number of seconds before you must request a new token.

NB: The longest token that you can request for ClearID is 60 minutes.

Successful response from /connect/token

json
{

  "access_token": "eyJhbGciOiJSUzUxMiIsImtpZCI6IjIwMTgtMDEtMjYtaWFtcy1zaWduaW5nLWNyZWRlbnRpYWwiLCJ0eXAiOiJhdCtqd3QifQ.eyJuYmYiOjE2NDAwMzAxMjIsImV4cCI6MTY0MDAzMzcyMiwiaXNzIjoiaHR0cHM6Ly9zdHMtZGVtby5jbGVhcmlkLmlvIiwiY2xpZW50X2lkIjoiNjYyNTIyMWYtNGU2Ni00YmM4LTgzMDUtY2I4Y2JkODdiMjFmOmNsZWFyaWRkZW1vcyIsInN1YiI6IjY2MjUyMjFmLTRlNjYtNGJjOC04MzA1LWNiOGNiZDg3YjIxZiIsImF1dGhfdGltZSI6MTY0MDAzMDEyMiwiaWRwIjoibG9jYWwiLCJlbWFpbCI6IjY2MjUyMjFmLTRlNjYtNGJjOC04MzA1LWNiOGNiZDg3YjIxZiIsInJvbGUiOiJTZXJ2aWNlIiwiYWNjb3VudF9pZCI6ImNsZWFyaWRkZW1vcyIsImNsZWFyaWRkZW1vc19zdGF0ZSI6IkFjdGl2ZSIsImNsZWFyaWRkZW1vc19yb2xlIjoiYWRtaW4iLCJjbGVhcmlkZGVtb3NfaXNfZGVsZWdhdGUiOmZhbHNlLCJqdGkiOiIwMDUwRjA3ODk2MjRCNjlGREM5NjFEMTA4QkQ1RDc3MiIsImlhdCI6MTY0MDAzMDEyMiwic2NvcGUiOlsiaWFtcy1hbGwtcGVybWlzc2lvbnMtZGVsZWdhdGVkIiwiaWFtcy1hcGkiLCJpYW1zLXJvbGVzIiwib3BlbmlkIl0sImFtciI6WyJhc3NlcnRpb24iXX0.kO3QzR9KP8pQxu4juBtpotk1Gdfpt095f9V8Xx75tW3ZzjK5kNB8ZEjJKe34p8oe_YAou_6xFL_lrIc3L0X4I9qJaV-8RDnCzyw2hWw2Vh4TGpwNgfM-BE6e7NZzfvWsmByYCrQQqLNqtKyPirjNgYeO_dLtGdfSbHpBayV7r-nuurGNAc1I0Y5wtoo6vbuKtmXCYl59mD22kYE4o2ucVtt94P8RkoXPD6eTY0TNB-C1e1IQyGrMdlqcmff9TiUhrAIwSWmxr4E-4JlYdVqahZoLSg2ZnmpnSCAnQbCy568SEa-is9WbSO2LNhsKBW7_URa7rQ2-oDyC8h2pCDFXhg",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "iams-all-permissions-delegated iams-api iams-roles openid"
}

How to find the STS base address, client_id, accountid, kid, key to sign

To build generic code that can work with any ClearID customer, the code you develop should not contain a hardcoded base URL, account ID, or cryptographic keys.

The administrator of a ClearID account can download a JSON file that your integration can use with a configuration file. That JSON file can be downloaded by any administrator of the ClearID account in Administration > Automation.

After creating a Service User on the automation page, you can then generate a new key. You will then be able to download the authentication, which is a useful JSON document.


Sample principal page displaying Generate key and Download authentication key buttons

Each time you click Generate Key, the previous key associated with this Service User becomes invalid and can no longer be used to authenticate.

The JSON downloaded from ClearID should be securely stored. It contains the credentials of a service account (administrative level) to integrate with ClearID.

Each customer you support provides this JSON file to allow your integration to work.

The JSON file contains:

  • accountid: This accountid is required in every API call that you make to ClearID.

  • *clientid: This is required in the authentication process. It functions similarly to a username, while the password acts as a signature using a private key.

  • key: This is the private key required to sign the JWT token during the authentication process. It is a serialized JSON Web Key.

  • stsUrl: This is the base URL of the service implementing the OAuth /connect/token endpoint required to authentication.

  • identityServiceUrl: This is the base URL of the Identity Service API. This is the API that 90% of the ClearID integrations are using.

  • Other well-known API endpoints: principalServiceUrl, roleServiceUrl. See the API Endpoints for more details.

json
{
  "accountId": "adwe23cse",
  "clientId": "6c0daac0-ad9c-49b0-bccf-e64dd3fae87a:adwe23cse",
  "identityRequestServiceUrl": "https://api-demo.clearid.io/identityrequest",
  "identityServiceUrl": "https://identityservice-demo.clearid.io",
  "key": {
    "kid": "6c0daac0-ad9c-49b0-bccf-e64dd3fae87a:cleariddemos",
    "keyType": "RSA",
    "algorithm": "RS512",
    "exponent": "AQAB",
    "modulus": "ui0UqPfRKKKnUZ1699I2WPb3gtoc4Echc0D25L6nDFRz1gshxY9GWxxmhqObglK3V-eu8vwI5AVaFQsLpVzz0JzKEN4-b1cZwzCPyZiMacs7XFucQqcULxYL1xN0PVGLAGHOUipctG6DY1DiZCS0G-qFU_pL92IJ9pDI5gpk2mvagxIzn8sP1ojesmWKTYTshBIDMyklhB_k_2mVrmv_qlUi-AkPmlxMgpK2DLQN-V0xxg6wFXqWkhZdYj2f7DV-7_YMl_u9GdbWa3IGKRwIm0HriCBPhzVdyFyJiEr7B7kScvCt_RKRs5kPRGobqTnjV2lCtppjbMUwTFLPli5b6Q",
    "d": "PRy8KeTC9wRBSRSY_001Asn6oCzJisM-ky8RfC-q9Oyp42pfCRMJRLITY4HD86kEPuoxrtgVcQfitIKeLYdQDzvQRm41b2XXco93u3SELtwD3cLCjcx7XyNs-ooLv28LYjI4wBbgvGeEYG72CWpU5s76OgEwu4EmhRWspHpn9ZwdrdtcEph0DiXvZE9Cf10g6O7MPV6ZFYfXVFbj8bzftEGDgr2M8Mm-rK51k-FGYuBzgL9ExCAFoMZej4PwrFR5609dcDY2A3py7vFuRk9mCk2VBbkuxE2drH0vyxSRQhLTfF_JEK2y1lyizwABdVfUA4fCmGqWuM-VKWzhwRg34w",
    "dp": "HH_CEcH-yN2XNjh_TAvZ2g6Jeu9xq_lYAD5al2UhKxyfZtqPG1ffr8rHTzOJRAg7u3twa3kW10ymNkjhk6qiXGyXgpASDmONPDoC9zsyEt42dGbpCQTQeSDYM2pKiWX81Y5U53oyVz_wtQJh7ZXlXSPeSwVNnQD6wEg5z_wtfW8",
    "dq": "E-iPGV5XzlH1uwpc8tsuXdfky3XVP77dduZMWiGiLtPxJSKSulS61151ZmgRlI2Yzx6Kt2gx2xRkl5yu1g-VA_axI_a4loxbUz01t4s9eSKYHhgEy89yD1-pugpDrgdSHfE1zdXBYVG2563OVJv5B9XwsUBi9tot_bJBhKKnEzk",
    "inverseQ": "I_vh5RefyV6Ki4dl6-aJw6fbO6iDIVj6h5BOnn_WRehhhLY17um6FJSp3bvzlwWDIfPdGJv07XMtWBrsqOzX1QbmnvfDo2EYj5HrSgjIdII8FXqM1IKIl7DChtfWKApA6pakjPFU0JF4aUCVm-g0n6USw2WSUuKSBS00L565a-c",
    "p": "u3fHgoHGKCU1XSMc3pmnZqlr4UrdhygO11V1IytcsDYghDnQGhR60Fj8EXFng6yjnnCyMWy5UqXf9OBdpZwzd_6pg60szF5Xt5-SQzjyt5_U5kNOfyKmTAo1m0m3yfN3fv1DMA1ofNV5OmGqVPGBtauNKnatFwMneW8vXIcXWMs",
    "q": "_jxopq5zKcpUDZKn3hYCcgu0WFMKdFVCu1laaNqA68DySTbdU5O2YKN0ke5wxEx9JHtnDk_gPPgzrds1aXlFA_nenG0r9d74mN5TpENLCvpGqzSfBM0DVUlIg-PzpMOMiKVmT_2RA4viI8BzDRWhnJTgohL3YdPyBsviA8y0q5s"
  },
  "principalServiceUrl": "https://principalservice-demo.clearid.io",
  "roleServiceUrl": "https://roleservice-demo.clearid.io",
  "stsUrl": "https://sts-demo.clearid.io",
  "teamServiceUrl": "https://roleservice-demo.clearid.io",
  "webhooksServiceUrl": "https://api-demo.clearid.io/webhooks"
}

How to create the assertion token

The assertion token is a JWT token that contains three standard sections:

  1. The header defining the format of the signature.

  2. The payload that contains details about your request.

  3. The signature that proves your identity. The signature is generated by using the key provided in the JSON file.

JWT Assertion Token before it gets encoded in Base64

json
{
 alg: "RS512",
 kid: "6c0daac0-ad9c-49b0-bccf-e64dd3fae87a:adwe23cse",
 typ: "JWT"
}.
{
 sub: "6c0daac0-ad9c-49b0-bccf-e64dd3fae87a:adwe23cse",
 jti: "9f0ad933bebe496f8483da730e519e67",
 nbf: 1637789750,
 exp: 1637793350,
 iat: 1637789750,
 iss: "6c0daac0-ad9c-49b0-bccf-e64dd3fae87a:adwe23cse",
 aud: "iams-sts"
}.
[signature]

The complete definition of the JWT claims can be found in the RFC 7519

The header of this JWT contains:

  • alg is the value found in key:algorithm of the JSON file

  • kid is the value found in key:kid of the JSON file

  • typ is always JWT

The payload contains standard JWT claim fields:

  • sub is the subject and it should be the value of clientId in the JSON file.

  • jti the JWT ID is a unique identifier of 32 digits that you should generate from a UUID generator to make sure it is unique.

  • nbf means "Not before". It refers to the NumericDate when the token starts to be valid.

  • exp is the expiration time of the token as a NumericDate. The maximum duration allowed by ClearID is 60 minutes. This value should be smaller or equal to nbf + 3600.

  • iat is the time that the token is issued. It is the current time in NumericDate.

  • iss is the issuer of the JWT in our context. It is the value of clientId in the JSON file.

  • aud is the audience for this claim, in our context. It is always iams-sts for ClearID.

NB: NumericDate is a standard format for the number of seconds since EPOCH in UTC.

The JSON file contains a serialized JSON Web Key that should be used to sign the assertion token required to authenticate.

Refer to our Code samples for authentication examples in different languages (C#, Java and Javascript).

To generate a signed JWT, use a standard framework.

In .NET use the namespace Microsoft.IdentityModel.Tokens.

How to generate JWT assertion token in C#

csharp
private string GetAssertion(string clientId, string serializedJsonWebKey)
        {
            var jsonWebKey = new JsonWebKey(serializedJsonWebKey);

            var signingCredentials = new SigningCredentials(jsonWebKey, "RS512")
            {
                //Needed to automatically set the kid in the JWT header:
                Key = { KeyId = jsonWebKey.Kid }
            };

            var now = DateTime.UtcNow;
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Issuer = clientId,
                Audience = "iams-sts",
                SigningCredentials = signingCredentials,
                Expires = now.AddHours(1), // IMPORTANT: maximum token lifetime allowed by the STS is 1 hour
                IssuedAt = now,
                Subject = new ClaimsIdentity(new[] { new Claim(JwtRegisteredClaimNames.Sub, clientId), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")) })
            };

            var handler = new JwtSecurityTokenHandler();
            var token = handler.CreateJwtSecurityToken(tokenDescriptor);
            var assertion = handler.WriteToken(token);
            return assertion;
        }