Authentication

Introduction

Scalepoint uses OAuth 2.0 "Client Credentials" flow for server-to-server API calls. It is also sometimes referred to as "2LO." or "2-legged OAuth".

This flow does not assert any individual user identity, but simply allows client (customer's backend system) to authenticate against the API with an application account.

Here is how it looks:

Authentification schema

Instead of using popular client_secret that is effectively a password, we use private_key_jwt authentication method for clients as defined in OpenID Connect Core 1.0 - Client Authentication, which requires confidential client to assert its identity by presenting a signed JWT token to the token endpoint.

So there are two tokens used in this flow:

  • Authentication Token. Client presents this to the authorization server token endpoint.
  • Access Token. Obtained from the authorization server token endpoint, used to make Resource API calls.

Access Token Request

Scalepoint provides simple to use client helper libraries in Java/.NET that abstract token generation away from you.

There are many other OAuth2 frameworks, libraries and even enterprise-class API gateways available for all platforms today that support this flow, but the implementations above should be sufficient.

The key parameters that must be fulfilled are:

Parameter Description
client_id Client identifier. Provided by Scalepoint
certificate Self-signed X.509 certificate (2048 bit RSA) with private key.
Used to sign the assertion. See below how to generate and register it.
tokenEndpointUri Scalepoint OAuth2 token endpoint, see Endpoints section for more details
scope(s) OAuth2 scope(s) to request access to. I.e. case_integration

Authentication Token signing and key management

The authentication token must be signed with a private key on the client. A self-signed RSA certificate can be used, since we don't rely on X.509 Certificate Authorities, but use peer-to-peer trust by pinning known public keys to customer accounts.

Self service key management portal isn't available initially, so customers have to send us the public key as base64 DER encoded certificate.

Multiple public keys per service account are supported to enable key rotation.

Self-signed certificate generation

You have at least these options:

Powershell snippet (Windows 10+ only) to generate a CSP certificate

New-SelfSignedCertificate -CertStoreLocation cert:\localmachine\my -dnsname <client.certificate.test> -HashAlgorithm SHA256 -KeyAlgorithm RSA -KeyLength 2048 -KeyExportPolicy Exportable -KeySpec Signature -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3") -NotAfter (Get-Date).AddDays(1095)

It is recommended to save the thumbprint from the output of this command and use it to find the certificate by in the application code. Check the client example.

makecert.exe (Windows < 10)

makecert -r -pe -n "CN=<client.certificate.test>" -b 01/01/2015 -e 01/01/2018 -eku 1.3.6.1.5.5.7.3.3 -sky signature -a sha256 -len 2048 -ss my -sr LocalMachine

If you run a Windows version lower than 10, you can use makecert.exe instead, because New-SelfSignedCertificate included in previous versions of Windows/Powershell cannot generate CSP certificate. It could come with your Windows of you can get it as part of Windows SDK, in which case it would be somewhere in C:\Program Files (x86)\Windows Kits\10\bin\x64\makecert.exe (version in the path can differ).

Here's a one-liner to install Windows SDK with makecert.exe:

iwr "https://go.microsoft.com/fwlink/p/?LinkID=698771" -OutFile "$env:TEMP\win10-sdksetup.exe"; start "$env:TEMP\win10-sdksetup.exe" "/features OptionId.WindowsSoftwareDevelopmentKit /ceip off /q" -NoNewWindow -Wait

keytool (java)

keytool -genkey -keyalg RSA -alias authkey -keysize 2048 -ext KU=digitalSignature,keyEncipherment -ext EKU=codeSigning -validity 730 -keystore keystore.jks -storepass <password> -dname "cn=<client.certificate.test>"
keytool -export -alias authkey -file certificate.cer -keystore keystore.jks -storepass <password>

Make sure to edit placeholders (in angular brackets) and optionally adjust file names (.jks and .cer) as necessary.

OpenSSL

openssl req -subj '/CN=<client.certificate.test>' -new -newkey rsa:2048 -days 1095 -x509 -keyout client.key -out client.crt

You can append "-nodes" to save private key without password, which is, however, not recommended.

Advanced: Custom client implementation

Warning!

Do this only if you really have to!

Token request

The token endpoint request must include the following elements in the POST request body:

Key Value Description
grant_type client_credentials Client Credentials flow
client_id example: future_insurance (optional) Client identifier.
client_assertion_type urn:ietf:params:oauth:client-assertion-type:jwt-bearer JWT Bearer token assertion type
client_assertion example: eyJ0eXA...FJcCY8gw (shortened) JWT token signed with client private key, check below how to generate one
scope example: api1 api2 Requested scopes, separated by space

If request succeeded, the token endpoint will return HTTP status 200 OK and a JSON body similar to this:

{
  "access_token": "eyJ0eXAiOiJKV1...sjghxBcw",
  "expires_in": 3600,
  "token_type": "Bearer"
}

The token itself is in "access_token" and the client SHOULD cache it for the duration according to "expires_in", which is in seconds.

Authentication Token (client assertion)

The JWT token must be signed with RS256 and include the following claims:

Type Value Description
"iss" example: future_insurance Client identifier
"sub" example: future_insurance The same client identifier
"aud" example: https://accounts.scalepoint.com/connect/token Token Endpoint URL
"jti" random string Unique token identifier. Subsequent requests with duplicate "jti" values will be discarded to prevent replay attacks. This is a "nonce".
"exp" example: 1444747048 Token expiration time. Recommended to keep token TTL very short (i.e. 1 minute) since these tokens are only to be used once. Clock skew is accounted for in addition to that.

Here is an example of such token's header and payload parts:

{
  "typ": "JWT",
  "alg": "RS256",
  "x5t": "GC-1BetJL2e7dVk9VhH_FlQ7Jpk"
}
Payload
{
  "jti": "35bc88e8-e61d-4aa1-8d46-4aed1798da2e",
  "sub": "future_insurance",
  "iat": 1444813734,
  "iss": "future_insurance",
  "aud": "https://accounts.scalepoint.com/connect/token",
  "exp": 1444810144,
  "nbf": 1444810134
}

Resource API Request

Once you obtain an access token from the authorization server token endpoint, you can start making actual API requests using that token.

The token must be included in the HTTP Authorization header using "Bearer" schema. The header should look like this:

Authorization: Bearer <access_token>

Here's an example in C#:

using (var apiClient = new HttpClient())
{
    var request = new HttpRequestMessage
    {
        RequestUri = new Uri(resourceUrl),
        Method = HttpMethod.Post,
        Headers = {
            Authorization = new AuthenticationHeaderValue("Bearer", accessToken) /* <-- access_token */
        },
        /* Content = ... */
    };
    var result = await apiClient.SendAsync(request).ConfigureAwait(false);
}

Endpoints

Authentication endpoint

For authentication, Scalepoint provides two endpoints – one for production and one for everything else.

Production endpoint

https://accounts.scalepoint.com/connect/token

Sandbox endpoint

https://sandbox-accounts.scalepoint.com/connect/token

You can read more about the actual flow by following one of the links: