Authentication

To access the Avida API, you'll receive a clientId and clientSecret for each environment (test and production), enabling secure connections through either OpenID Connect or JWT standards.

All API requests are authenticated using OpenID Connect or JWT:

  1. OpenID Connect - Adds an identity layer on OAuth 2.0, verifying the end-user's identity and allowing the client to access profile information in a REST-compatible format.
  2. JWT - Attach the token as a Bearer Token in each request header. The JWT signature is verified by the authorization server, either through a validation endpoint (RFC 7517) or a locally provided key.

Security Note: Always secure your credentials. If you suspect they are compromised, reset them immediately.

OAuth2 Client Credentials

This guide provides documentation on how to authenticate to the API using the OAuth2 Client Credentials flow, and how to query the API with the received token. We will provide minimal code examples for both Node.js and C#.

Authentication Endpoints

  • Token Endpoint: /oauth2/token
    • This endpoint is used to obtain an access token.
    • Method: POST
    • Required Headers:
      • Content-Type: application/x-www-form-urlencoded
    • Body Parameters:
      • client_id: Your client ID
      • client_secret: Your client secret
      • grant_type: Must be set to client_credentials
      • scope: A space-separated list of scopes

Scopes

Scopes must be used when requesting a JWT. The following scopes below can be used:

Loan application Scopes

  • Spain:

    • loan-application:create:es: Create a loan application in Spain
    • loan-application:update:es: Update a loan application in Spain
    • loan-application:delete:es: Delete a loan application in Spain
    • loan-application:accept:es: Accept a loan application in Spain
  • Sweden:

    • loan-application:create:se: Create a loan application in Sweden
    • loan-application:update:se: Update a loan application in Sweden
    • loan-application:delete:se: Delete a loan application in Sweden
    • loan-application:accept:se: Accept a loan application in Sweden

Tets Example Request (Token Endpoint)

POST /realms/agents-test/protocol/openid-connect/token
Host: oidc-kc.test.quattro.stacc.dev
Content-Type: application/x-www-form-urlencoded

client_id=your_client_id&client_secret=your_client_secret&grant_type=client_credentials&scope=loan-application:create:es

Production Example Request (Token Endpoint)

POST /realms/agents-prod/protocol/openid-connect/token
Host: oidc-kc.prod.quattro.stacc.dev
Content-Type: application/x-www-form-urlencoded

client_id=your_client_id&client_secret=your_client_secret&grant_type=client_credentials&scope=loan-application:create:es

Example Response

{
  "access_token": "YOUR_ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": 3600
}

Querying the API

Once you have obtained the access token, you can use it to authenticate API requests by including it in the Authorization header.

  • API Endpoint: /api/resource
    • Method: GET
    • Required Headers:
      • Authorization: Bearer YOUR_ACCESS_TOKEN

Code Examples

- Node.js Example

In this example, we will use the axios library to make the HTTP requests.

const axios = require('axios');
const qs = require('qs');

// OAuth2 Client Credentials flow to get access token
async function getAccessToken() {
  const tokenUrl = 'https://oidc-kc.test.quattro.stacc.dev/realms/agents-test/protocol/openid-connect/token';
  const data = qs.stringify({
    client_id: 'your_client_id',
    client_secret: 'your_client_secret',
    grant_type: 'client_credentials',
    scope: 'loan-application:create:es'
  });

  const config = {
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  };

  const response = await axios.post(tokenUrl, data, config);
  return response.data.access_token;
}

// Query the API using the received token
async function queryApi() {
  const token = await getAccessToken();
  const apiUrl = 'https://api-public.test.quattro.stacc.dev/api/resource';

  const config = {
    headers: {
      Authorization: `Bearer ${token}`
    }
  };

  const response = await axios.get(apiUrl, config);
  console.log(response.data);
}

queryApi();

- C# Example

In this example, we will use HttpClient to make the HTTP requests.

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    private static async Task<string> GetAccessToken()
    {
        var tokenUrl = "https://oidc-kc.test.quattro.stacc.dev/realms/agents-test/protocol/openid-connect/token";
        var client = new HttpClient();
        var requestBody = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair<string, string>("client_id", "your_client_id"),
            new KeyValuePair<string, string>("client_secret", "your_client_secret"),
            new KeyValuePair<string, string>("grant_type", "client_credentials"),
            new KeyValuePair<string, string>("scopes", "loan-application:create:es")
        });

        var response = await client.PostAsync(tokenUrl, requestBody);
        var tokenResponse = await response.Content.ReadAsAsync<dynamic>();
        return tokenResponse.access_token;
    }

    private static async Task QueryApi()
    {
        var token = await GetAccessToken();
        var apiUrl = "https://api-public.test.quattro.stacc.dev/api/resource";

        var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);

        var response = await client.GetAsync(apiUrl);
        var responseBody = await response.Content.ReadAsStringAsync();
        Console.WriteLine(responseBody);
    }

    static async Task Main(string[] args)
    {
        await QueryApi();
    }
}

JWT token / Public Key (deprecated)

Acquiring a Json Web token (JWT) The JWT is an open standard, and creating a JWT can be performed in a number of ways. Examples of JWT issuers can be Azuer AD or KeyCloak amoung many others.

If you do not have an identity token issuer already, we have described a method below for generating a JWT yourselves, for testing purposes. In the integration itself, you should generate a new JWT for each request. You may, however, use the keys generated below, if you don't have another solution set up.

Step 1: Generating a key pair

JWTs are based on key pairs, which consist of a private and a public key. The private key is your own secret, and needs to be kept safe. The public key is meant for sending to collaborators (e.g. Avida) so that we can verify signatures created with your private key.

The keys should be:

  • RSA
  • At least 4096 bits long

The examples below are in bash (on Linux or similar operating systems), but you can easily perform the same tasks with other tools. You can download all the files described below from here:

  • create-key.sh
  • create-jwt.sh
  • header.json
  • payload.json

To generate a key pair, you can run the following commands [create-key.sh] :

#!/bin/bash

# Creates a private/public key pair that can be used to generate and sign a JWT.
#
# PLEASE NOTE that the private key should be kept secret, and should in no 
# circumstances be sent to anyone else.
#
# The public key, however, is not secret, and can be sent via unsecure channels,
# and is the one used by Avida to verify the signed JWT.

openssl genrsa -out Avida-key.pem 4096
openssl rsa -in Avida-key.pem -pubout -out Avida-key-public.pem

This will give you files similar to these:

Avida-key.pem:

-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEAvsOyT9P0d8lJUgbsQiSds2nmxAabf6FpdtRwE+43dkIiSn11
w0zBkWSlf6oI/YwMtMKE5CfAW30PVZfaN/w0mdr+0h9TYNgYOOBSGE0ImFbKAYo9
(...)
gu9nPHBuntCpQNBy0kv6pI7dPBZo1QIQwL8uqyDDpj3G7cweUHT930ynCyn0V9E5
PU8eGdtqQPSYs3aWtdqIrJXRYSvrSh11Gs0AkFZdETGETSsNxq9djWC8SUH+tBcy
BAZtQT5wXoKs1ovpMsE+bpYe6H+xhZWnS1erUO3pBTW+MKc+csz8dUgzNIduh1bT
a2X6IOSUN1l3COouV6SI5vYoaz4L3dv8GadMpP48H6xxtepmdY4UIHVOHKfZgX5e
dN9wnsLuNoUj9Sv30XUd76W6pMqjjVrYyfb5qPJAcQtFzd5QJ+neAKcPGPE+
-----END RSA PRIVATE KEY-----

Avida-key-public.pem:

-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvsOyT9P0d8lJUgbsQiSd
s2nmxAabf6FpdtRwE+43dkIiSn11w0zBkWSlf6oI/YwMtMKE5CfAW30PVZfaN/w0
mdr+0h9TYNgYOOBSGE0ImFbKAYo9lGwI/hA+ZXlDvfErUY1wZRk8LfDx0EQXGm23
3Rr/ZVpELQXoT7DlLCSNCLMKJtFfUyXmpz/fVf2/tnpGk0WYWm42/9oyNkI1+a3l
KwU9uXe4mpRudQyYMpysHJx4JxqymbDatvY9kPDhRJryc1IVzV6P4scFsdkiQlb3
F2TZ2smgWyAXazkc/RGIhAHIhrOOdhfvCT2O7Ogg8MKK7gdiwYbR/IbhsmwRic47
mdrx1M0KsUHvz1HzOSOh1IJ4p9ohfVEDkgjZe1U5YQsFXbc8tJbh/Es0yDXwP3tX
8ndKS0G6CaFt3eY9kneRFjVk18vmY7wBu5wsMG9Gnf6qP76t79o4CUni2Ke/13/p
AQfBpDYj3fXaIvyp4axMdaIZ4fIwDVicD9f0TQLcbtPz4sU143aSZDfEpySFDG0I
e9+3PDGIDK86dVZRXsQh10YRAE8Pa8bTGw76O84D4nVja8c4jm+YBMjkQG/6asrA
xWduGx8UJ4Zg/2em4AGtUXyLqkEIbE6SNgC/ws4DQHyY8w+EGmuGUK3d/wPXfQbU
+w03JLChStvKazqSZ/TMKh0CAwEAAQ==
-----END PUBLIC KEY-----

Remember to store the file Avida-key.pem in a safe place.

Step 2: Using the keys to create a JWT (for testing)

You need a token with the following header and payload:

Header

Save this as header.json Replace: kid with a chosen key id. This is something to easily identify the key, e.g. super-agent-key-1 We will use the kid to look up the public key we will use to validate the JWT on our side.

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "super-agent-key1"
}

Payload

Save this as payload.json. Replace:

  • iss with a chosen issuer name, e.g. super-agent-issuer
{
    "iss": "super-agent-issuer",
    "aud": "Avida-agent-test",
    "jti": "%%%JTI%%%",
    "iat": %%%IAT%%%,
    "nbf": %%%NBF%%%,
    "exp": %%%EXP%%%
}

The values in iat, nbf, and exp should be in unix time format, as described in the RFC 7519 standard.

Generating the JWT

Given that you have saved the files above in a folder along with your key file, you can run the following script to generate a valid JWT create-jwt.sh :

#!/bin/bash

keyFile=./Avida-key.pem

# Choose a validity period
VALIDITY_MINUTES=30

# Set timestamps
IAT=$(date -u +"%s")

if [ "$(uname)" = "Linux" ]; then
    EXP=$(date -u -d "+${VALIDITY_MINUTES} minutes" +"%s")
    NBR=$(date -u -d "-1 minute" +"%s")
else
    EXP=$(date -u -v+${VALIDITY_MINUTES}m +"%s") 
    NBF=$(date -u -v-1m +"%s")
fi

function b64enc() { openssl enc -base64 -A | tr '+/' '-_' | tr -d '='; }

# Create a uuid for JTI
jti=$(uuidgen)

# Read payload.json, and replace the timestamp markers and jti in the payload
actual_payload=$(sed -E "s/%%%IAT%%%/${IAT}/" < payload.json)
actual_payload=$( echo -n ${actual_payload} | sed -E "s/%%%NBF%%%/${NBF}/")
actual_payload=$( echo -n ${actual_payload} | sed -E "s/%%%EXP%%%/${EXP}/")
actual_payload=$(echo -n ${actual_payload} | sed -E "s/%%%JTI%%%/${jti}/")

# base64url encode header and payload
header=$(cat header.json | b64enc)
payload=$(echo -n "$actual_payload" | b64enc )

# Combine the two into a message
message="${header}.${payload}"

# Create a signature over the message with the keyfile, and base64url encode
signature=$( echo -n $message | openssl dgst -sha256 -binary -sign $keyFile | b64enc )

# Combine all of the three into a valid JWT
jwt="$message.$signature"

echo "$jwt"

This token will be valid for 30 days, but you can adjust this as desired.

Validating the token

There are several tools online you can use to validate the tokens. A couple of examples are:

Here you can verify that everything worked as planned, and see which information you send to us.

Step 3: Sending the public key to Avida for verification

When done, make sure you:

  • Store the private key in a safe and private place
  • Send the public key to Avida (this can be sent by email)
  • Generate a sample JWT (not the one you will be using) and send by email, so that we can verify.

Was this page helpful?