Authentication for the Clearance API

Clearance Developer Guide

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

Authentication is the process by which a user or integration's identity is verified and authorized. There are two types of authentication mechanisms for Genetec Clearance™ depending on whether a user (OpenID Connect) or an integration (OAuth2) is accessing the API. Both authentication methods ensure the security of your Clearance data.

User from a Web browser point

When you are calling the Clearance API directly from a browser, you should always use OpenID Connect to authenticate the user, and then use the bearer token in the API. The Clearance authentication automatically uses Azure Active Directory B2B and B2C to authenticate the users.

Request from a back-end service

OAuth2: When another integration needs to communicate with Clearance, we use a combination of private and public keys to authenticate the service. The keys are available in the JSON connection file generated after creating an integration account in Clearance.


Request for back-end service

The Clearance STS (Secure Token Services) is responsible for generating a JWT Bearer Token that can be used in the HTTP header of every REST API call. Bearer tokens have an expiration date and the caller is responsible for renewing the tokens before the expiration date.

The API client is responsible for renewing the access token before its expiration date. The response returned by the Token endpoint contains the information necessary to calculate the access token's expiration date.


STS renew

To obtain an access token, you need to call the /token endpoint using the OAUTH2 protocol with the sub-section RFC7523. To do that, you need to use the values contained in the JSON connection file.

  • *client_id: The value should be @.

  • grant_type: The value should always be urn:ietf:params:oauth:grant-type:jwt-bearer as referenced by the RFC7523.

  • assertion: The value should be a JSON Web Token signed using the ServicePrincipalKey.

A typical call should look like this:

curl -X POST -d "client_id=<ServicePrincipalId>@<TenantId>&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<ENTER TOKEN ASSERTION HERE>" https://clearance-a-sts.geneteccloud.com/connect/token

To generate a token assertion, you need to create a new JSON Web Token and sign it with the key provided in the JSON connection file:

string clientId = "<ServicePrincipalId>@<TenantId>";
var handler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
  Issuer = clientId,
  SigningCredentials = new SigningCredentials(
    new RsaSecurityKey(... ServicePrincipalKey from config.json ...),   JsonWebKeySignatureAlgorithm.RS256)
};
var token = (JwtSecurityToken)handler.CreateToken(tokenDescriptor);
string tokenAssertion = handler.WriteToken(token);
import jwt = require("jsonwebtoken");
import fetch = require("node-fetch");
import pemjwk = require("pem-jwk");
import { OAuthTokenModel } from "./model/oauthtokenmodel";
import { TenantSettings } from "./model/tenantsettings";

export class OAuth2Client {

    private readonly m_tenantSettings: TenantSettings;

    constructor(tenantSettings: TenantSettings) {
        this.m_tenantSettings = tenantSettings;
    }

    public async getServicePrincipalAccessToken(): Promise<string> {

        const client_id: string = `${this.m_tenantSettings.ServicePrincipalId}@${this.m_tenantSettings.TenantId}`;

        const pemKey = pemjwk.jwk2pem(this.m_tenantSettings.ServicePrincipalKey);
        const now: number = new Date().valueOf() / 1000;
        const requestToken = jwt.sign({ iss: client_id, iat: now, exp: now + (60 * 60), nbf: now}, pemKey, { algorithm: "RS256"});
        const requestModel: OAuthTokenModel = {
            client_id,
            grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
            assertion: requestToken
        };

        const requestInfo: RequestInit = {
            method: "POST",
            body: JSON.stringify(requestModel),
            headers: {
                "Content-Type": "application/json"
            },
        };

        const response = await fetch(`${this.m_tenantSettings.SecurityTokenServiceBaseAddresses[0]}/token`, requestInfo);
        if (response.status === 200) {
            return (await response.json()).access_token;
        }
        throw response.text();
    }
}
import json
import time
from jwcrypto import jwk, jws, jwt
from jwcrypto.common import json_encode
import requests 
import datetime

with open('config.json') as config_json_file:
    data = json.load(config_json_file)
    now = int(time.time()) 
    client_id = data['ServicePrincipalId'] + '@' + data['TenantId']
    expkey = data['ServicePrincipalKey']
    key = jwk.JWK(**expkey)
    token = jwt.JWT(header={"alg": "RS256", "kid": key.key_id},
                    key=key,
                    claims={"iss": client_id, "sub": client_id, "iat": now, "exp": now + (60 * 60), "nbf": now})
    print(token.claims)
    token.make_signed_token(key)
    assertion = token.serialize(True)
    print(assertion)
    r = requests.post(url = data["SecurityTokenServiceBaseAddresses"][0] + "/token",
                      json = {
                        "client_id": client_id,
                        "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
                        "assertion": assertion
                        }) 
    print r.json()["access_token"]

Once authenticated, the JWT Bearer Token should be included in the authorization header of every API request.

Example of GET API for an Evidence on the tenant “tenant123”:

curl -X GET --header 'Accept: application/json' --header 'Authorization: Bearer eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhNTEyIiwia2lkIjoiNzFFODNEMDQ4NjIxMTg0RTMxOENEMDUxREEwMzhBRjQ2MjQ1QTkyMiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiamRveW9uQGdlbmV0ZWMuY29tIiwiaHR0cDovL3NjaGVtYXMuZ2VuZXRlYy5jb20vd3MvMjAxNi8wMy9pZGVudGl0eS9jbGFpbXMvcHJpbWFyeWtpZCI6InVybjp1c2VyOmpkb3lvbmRlbW86amRveW9uQGdlbmV0ZWMuY29tOjMiLCJodHRwOi8vc2NoZW1hcy5nZW5ldGVjLmNvbS93cy8yMDE2LzAzL2lkZW50aXR5L2NsYWltcy9wcmltYXJ5aWQiOiIzIiwiaHR0cDovL3NjaGVtYXMuZ2VuZXRlYy5jb20vd3MvMjAxNi8wMy9pZGVudGl0eS9jbGFpbXMvcHJpbWFyeXR5cGUiOiJ1c2VyIiwiaHR0cDovL3NjaGVtYXMuZ2VuZXRlYy5jb20vd3MvMjAxNi8wMy9pZGVudGl0eS9jbGFpbXMvdGVuYW50aWQiOiJqZG95b25kZW1vIiwiaWF0IjoxNTA0NjM3NTg2LCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9naXZlbm5hbWUiOiJKb25hdGhhbiIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL3N1cm5hbWUiOiJEb3lvbiIsImh0dHA6Ly9zY2hlbWFzLmdlbmV0ZWMuY29tL3dzLzIwMTYvMDMvaWRlbnRpdHkvY2xhaW1zL2dyb3Vwa2lkIjoidXJuOmdyb3VwOmpkb3lvbmRlbW86L1RlbmFudCBBZG1pbmlzdHJhdG9yOjEiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOlsidGVuYW50YWRtaW4iLCJkZXZvcCJdLCJuYmYiOjE1MDQ2MzY2ODYsImV4cCI6MTUwNDY4MDc4NiwiaXNzIjoiaHR0cHM6Ly9jbGVhcmFuY2UtYS1zdHMuZ2VuZXRlY2Nsb3VkLmNvbS9jb25uZWN0IiwiYXVkIjoiY2xpZW50In0.lKs2Hqb7RAWH5o5A44YK1MzmGzCcoBmhMwtVzsUt5RtpIGqRU6SZD5NNRRXENoOg2GvfRAd6MDgk-2uplNgYSojOxp1YrPx5tAkYvFdcYCwJBw7c0RWM8doZ1gKdmHoqVZOGCGBB4PaJirlcr5z69VphCX_AX3-QX9ay9I1WiRlHdiry4v21z7gQ2UoeorsrMtbs_1EAqHS_1B_XJzL7uSW8nJv1pXf3LD247DMR-IH3sx-uAdQg_DU2LTuHm2a3MOo_1WLEot3SzRnASB2Bnj_3APPlUg80rnhfo8uJeEIEXubNVSygk5f0Ik0PuPlSBFX8f-B8l8nMtkAV3Xbo1w' 'https://clearance-a-ds.geneteccloud.com/api/v1/tenant/tenant123/evidence/30'