Authentication and Authorization

Introduction

This REST API is secured with JSON Web Token (JWT) authentication RFC7519. It is assumed that the clients of this API are capable of issuing valid JWT tokens.

JWT tokens may be obtained by requesting them from an Identity Provider (such as Keycloak) or created manually. In both cases, the public key to be used for the signature verification has to be provisioned in the IdCloud.

In the case where no Identity Provider is available, then the following section describes how to generate an RSA key pair that can be used to issue and verify JWT tokens.

Authentication

Only the JWTs signed with one of the following algorithms: “RS256”, “ES256”, “PS256” are supported. See JSON Web Algorithms (JWA) RFC7518.

The JWT security is limited to asymmetric cryptography algorithms in order to avoid storing shared secrets in the backend server. As a result, the backend only stores the public keys used to verify the signature of the tokens.

Currently supported JWT header signature algorithms

Type to be included in JWT header Comment Recommended key size
RS256 RSA using SHA-256 hash algorithm 2048 bits
ES256 ECDSA using P-256 curve and SHA-256 hash algorithm 224-255 bits
PS256 RSASSA-PSS signature using SHA-256 hash algorithm and MGF1 mask generation function with SHA-256 2048 bits

JSON web tokens

Every resource of the API is protected. In order to gain access to it, a valid JWT has to be sent along with the HTTP request in the Authorization header using the Bearer schema:

Authorization: Bearer <Base64_Encoded_JWT>

A JWT consists of three parts separated by dots (.):

  • Header
  • Payload
  • Signature

Therefore, a JWT typically looks like the following: hhhhhhh.pppppppp.ssssssssss

Header

The header part contains the algorithm to use and the type of token to generate.

‘KID’ could be used to determine the correct key among multiple public keys from the same issuer.

Header example

{
 "alg": "RS256",
 "typ": "JWT"
 "kid" : "Key1"
}

Payload

The Payload can contain the following fields:

object
iss
string

Issuer of the key

This identifies the principal who issues the JWT.

WARNING: ISS is used to lookup the enrolled Public Key in IdCloud

required
sub
string

By default this field is used for identifying the authorized entity and will be used for internal audits.

required
jti
string

Part of audit if provided

exp
string

JWT Expiration

required
role
array[string]

The name of the role required to access SCS is configured at the global level.

Note: "scs:executeScenario" is the only role needed currently

required

Payload example

{
    "iss": "Tenant1",
    "sub": "Tenant1User",
    "jti": "27ae069f-05ce-4f85-a083-dfcc19794029",
    "roles": ["scs:executeScenario"]
    "exp": "1545222654""
}

JWT signature

A cryptographic hash of both the header and the payload.

These parts are Base64URL encoded and concatenated, separated by single dots (’.’).

How to generate JWT

You may use the openssh tool to generate an RSA key pair with the following commands:

Example (RSA256)

> ssh-keygen -f key -m PEM -t rsa -b 2048
  • Generate Public Key that MUST be configured in IdCloud.
> ssh-keygen -f key.pub -e -m pkcs8 >> pkcs8.pub

The generated private key will be used to sign the JWTs on the client side and the generated public key will be provisioned into the backend to verify the signature of those JWTs (will be provided to Thales via Tenant Onboarding form).

  • There are many tools available to help with JWT generation.
  • Here is an example of how to generate it using tiny NodeJS library:
// include the lib in your project
const jwt = require('jsonwebtoken');
 
 
// Use your own private Key
const privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAmpGwL0lD1amtnxN6CQxxmHyToZElJ2deT2KN1qUEN0Rj/jWj
JOF01+5DcQDyyCbIITcV8S+wB0AlJRsUyx/xM+JbYf4zB6KjO7jDxfe+kqipWQmG
ef/HvcRWL9P5aoZoEyhG5ITCxfLFerU0R3IEiCH0qp2BtOF7pXLy5pp4fy1ZlMr2
85ITEBO4MgLSHnNSgAR9mfaEkawm77dS1DAhiQq+AiAOPAMBQfckAzSjmIpg20th
0x1gngnOMsOOUJK+KTo46x4T0rLDxh6s8VZtZcwK2l6GLxwdRRuaGf6Ry/PJ00Hg
fFg9i2GE1IiP/dg7ra2xhTfp0vcHXtECbFQsUQIDAQABAoIBAHVM0J7iA9e2/+qz
9i29wstM5yB6rO59VKX8DdXxvwROI3A8tkV7z5c62vV8GcLpI4GJc15oqTanaEkD
h0ErSXntcxontgQ6WZQuAGxROc/ErVfDkckt4iBSSnHbdPFxdLPtIfe0BLgCJ/ma
YEVD8sp4slt0UoW5hIMne8yjN4SS8Ok+DP3aiZOy4skGAixTx4wEyYlYMhch2kSo
o4fPY/H6CDiqlUnKflwdju9lkV27Ds8QBJooVYkj0i6r3IKOvB9UXiRAynqOvBdf
FerL4/GyqKqU84jPEkPvYxefnseFpzs/jgS9TBi6BmIi5xKNojxdtsZwQWiEcRUs
4yQnCr0CgYEAytOs8HZ/RrVl1VGDvkNZRhHbc49GIG2vC+d/nN0SeJIDoqAQ9myl
uabuNOPlLSqxtgkW/+Qk1YzsWcHlsY8uKyQhBeXdEFYQJbWdk7LoL/fDGT2xEgpN
HKyA+j4MIxS1tooR0fqt9/Hx+0HDL0aKTBS0MTiunwp45tiYVykoIecCgYEAwxdJ
wWRX2hn0d+lpnMWUyo/FNHHCchKUtNXaGfQ9KvPWKROMagFIqK9xvNLEizucowxQ
K1csOTeuiiJW6kZy5UsxC1JNz6bmAJaIjjdn0+mmH9qckewKkPeNcoBTruGNB96m
gSfQBImgtXP70HoBycPaCk6cSU/tv3V3lSOg6QcCgYAC4NIZb3UK6dQSHOADuSzx
I5u7nhLeru/G+XgEH9b9QwUuL5tOA+iuI8JJmdpMs8hlzuc2pmQna6KG+4to46FC
F3cogESM0MvV3SfpSqak1507JHb4zJCfkYsbAfpmHQsfFgJ+ulHxrMtER4CfkR6x
SbHs6OMBesKQdA5lXj4ljQKBgQCLV2HVoG7jF3C2CN/nGnQorcFjsPD5+u19r9Sk
fv8FY72N/ylmOV6FJTJudHfvHnfFOTE1k4DBqVSf0uETWZgMz8TK2lE7RHC48Mu+
EDK3eAWwcLstulLdsgK0SpX6rZzGhy+TxjTcWNSRZbLw94O5cYqVnAoijtU3z5XG
zvjKFwKBgE3rmd110jQOPERdjVRN9Gnq5QT5tTno7cAuoQLbjoNAadndrXToVtD+
mtXyakQvXSwRzXRcbWO8qhTKCnoroOJL0/+h52ICr+AEb2jCENblUmjpUyNrTPHD
sYPSB+lI0GhkHut9FjEPlLWBSDMcU/MMAFmDZuF9zai+uB00j+7Y
-----END RSA PRIVATE KEY-----
`;
 
// prepare the payload, with your tenantID and the appropriate role
const payload = {
 jti: "27ae069f-05ce-4f85-a083-dfcc19794029",
 roles: ["scs:executeScenario"]
};
 
// set some options, containing the reserved claims, the algorithm to use…
const options = {
 algorithm: 'RS256',
 issuer: "dummyTenant",
 expiresIn:  "1h",
 subject:  "dummyUser",
};
 
// and let sign… in one line your token is generated
const token = jwt.sign(payload, privateKey, options);
console.info(token);

Example output

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyN2FlMDY5Zi0wNWNlLTRmODUtYTA4My1kZmNjMTk3OTQwMjkiLCJyb2xlcyI6WyJzY3M6ZXhlY3V0ZVNjZW5hcmlvIl0sImlhdCI6MTU1MDA
0NzEyMCwiZXhwIjoxNTUwMDUwNzIwLCJpc3MiOiJkdW1teVRlbmFudCIsInN1YiI6ImR1bW15VXNlciJ9.U4ia_sIqlwabb7Rug80xmtpqDkE7HLbEhPZIRRGxKWrgfYzPRsz2iPDfaMjXKZcwyRxV9-DNAj
a21fqcDTquPdM8-NEuWxPcacHu1vX9GK0nu9Lfu2I_nw0ShR-GeIrolWM45OppSNGg-sckZoBfCrTudMjg2yBqJAzTH8-lC6eCBLD4CyIKXoB36lPbRfHtA7ja6ZjJElbvzuRfH9dGrZmlc80wJiPrVtAF7b
BYsDiBnq0I8StDkrzHxbqDEgI8Atv85RQDqpnooIVDBADmYdtBj9ArU-3LKCldbiCyCrtyQUw93RydujBDHIDBaUR3GWzNW4lLp_mR552cVqLu1Q