๐ Authentication and 2FA Management
How to implement authentication quickly and securely with the AUDD Mint.
When connecting to our API, security is our top priority. To protect sensitive data and ensure only trusted clients gain access, we use a layered authentication model combining IP whitelisting, mutual TLS, credentials, and two-factor authentication.
IP Whitelisting RequiredBefore you can begin interacting with the AUDD Mint, your IP address(es) will need to be whitelisted within our system. Reach out to our team via your dedicated slack channel to complete this step.
๐งฉ mTLS
We require you to create your own root CA and provide its certificate to us. You will then use a client certificate signed by that CA.
You will then be able to use the client.key and client.pem in your https clients. For example, using nodejs:
const axios = require('axios');
const https = require('https');
const fs = require('fs');
// Read the key and cert files
const key = fs.readFileSync('client.key');
const cert = fs.readFileSync('client.pem');
const httpsAgent = new https.Agent({
key: key,
cert: cert,
rejectUnauthorized: true,
});
axios.get('https://distributor-api-staging.audd.digital/...', {
httpsAgent: httpsAgent,
})๐ช Gaining Access
When your account is set up, youโll receive an email at your nominated address with a link to create your password. Your username and password let our system recognise you and give you access.
Alongside your login details, weโll also generate an API key for you. This key is used during the initial authentication step to securely connect to our system. Once youโve authenticated, youโll receive a JWT (JSON Web Token) - from that point on, youโll use the JWT as a bearer token for ongoing access instead of the API key.
๐ 2FA Setup
Even with IP whitelisting, mTLS, and passwords, 2FA adds protection against stolen credentials or certificates by requiring a possession factor tied to the user or system. This ensures stronger identity assurance for both humans and machines and meets compliance expectations for strong authentication.
To set up 2FA via the API, you will first need to generate a shared secret by making a GET request to /login/two-factor/secret
curl --cert client.crt --key client.key https://distributor-api-staging.audd.digital/login/two-factor/secret -H "Authorization: 5pv515CM2uL4VAEXu5zEVDf..."This will return a json object of the form
{"secret":"2Qs5WzZ3TzEvBhEIcIov","secretBase32Encoded":"3EFTSWZWO5HTCLYGCEEHBCRP"}You will use the secretBase32Encoded value as the secret for TOTP generation. As an example, this code can be generated using the otpauth npm package with the following code:
import otpauth from "otpauth";
const totp = new otpauth.TOTP({
secret: "3EFTSWZWO5HTCLYGCEEHBCRP",
issuer: "AUDD",
label: "[email protected]",
});
const code = totp.generate();Now that you are able to generate TOTP codes using the shared secret, you need to register that shared secret as an MFA method in our systems. This is done by making a POST request to /mfa/enable:
This endpoint registers your MFA secret and returns a list of recovery codes.
How to use the recovery codesThe recovery codes can be used in place of the TOTP when logging into the Portal or via the API.
๐ค Logging In
You are now set up to log in and begin using the rest of our API. To login, make a POST request to /mfa/login
This endpoint returns a JWT (token) and refresh token. You will then be able to authenticate to the rest of our API by using the JWT as a bearer token in the Authorization header: Authorization: Bearer ${token}.
The JWT expires in 5 minutes and can be refreshed using the refresh token which expires in 15 minutes.
To refresh your JWT, make a POST request to /login/jwt/refresh
This endpoint returns a new token and refresh token that you can use to continue accessing our API.
Typescript Example
Below is a comprehensive example showing programmatic MFA setup and login.
/**
* Example script demonstrating how to authenticate with the AUDD Digital API.
* Uses mutual TLS (mTLS) and TOTP-based multi-factor authentication (MFA).
*
* - Loads credentials and certificates from environment variables
* - Generates and registers a new MFA secret via /login/two-factor/secret
* - Enables MFA with /mfa/enable and supports login via /mfa/login
* - Demonstrates access token usage and refresh token flow
*
* Intended for developers integrating with the AUDD API sandbox to test secure
* authentication workflows.
*/
import https from "https";
import fs from "fs";
import axios from "axios";
import { TOTP } from "otpauth";
// -----------------------------------------------------------------------------
// Configuration and environment variables
// -----------------------------------------------------------------------------
// Load paths to client key/cert for mTLS authentication
const clientKeyFile = process.env.CLIENT_KEY_FILE!;
const clientCertFile = process.env.CLIENT_CERT_FILE!;
// Load credentials and secrets from environment variables
const apiKey = process.env.API_KEY!; // API key used to authorize setup calls
const mfaSecret = process.env.MFA_SECRET!; // Pre-registered MFA secret for login
const username = process.env.USERNAME!; // User account name
const password = process.env.PASSWORD!; // User password
// Sandbox API base URL (change to production as needed)
const url = "https://api.sandbox.audd.digital";
// -----------------------------------------------------------------------------
// HTTPS agent setup for mutual TLS (mTLS)
// -----------------------------------------------------------------------------
// Create an HTTPS agent using client certificate and key for secure communication
const agent = new https.Agent({
key: fs.readFileSync(clientKeyFile), // private key
cert: fs.readFileSync(clientCertFile), // client certificate
});
// Create an Axios HTTP client pre-configured with the mTLS agent and base URL
const client = axios.create({
baseURL: url,
httpsAgent: agent,
});
// -----------------------------------------------------------------------------
// Helper: Generate a TOTP (Time-based One-Time Password)
// -----------------------------------------------------------------------------
// Generates a 6-digit TOTP using the shared MFA secret
const generateTotp = (secret: string) => {
const generator = new TOTP({ secret });
return generator.generate();
};
// -----------------------------------------------------------------------------
// Step 1: Set up Multi-Factor Authentication (MFA)
// -----------------------------------------------------------------------------
const setUpMfa = async () => {
// Request a new MFA secret from the API (only needed once per user)
let res = await client.get("/login/two-factor/secret", {
headers: { Authorization: apiKey },
});
// Extract the secret (Base32-encoded) from the response
const secret = res.data.secretBase32Encoded;
// Display the secret so the user can store it (e.g., in a password manager or env var)
console.log(`MFA secret: ${secret}`);
// Construct the registration payload
const body = {
username,
password,
mfaSecretB32: secret,
mfaCode: generateTotp(secret), // Generate a code using the new secret
};
console.log(`Request body: `, body);
// Send the MFA enablement request to register the secret
res = await client.post("/mfa/enable", body, {
headers: { Authorization: apiKey },
});
};
// -----------------------------------------------------------------------------
// Step 2: Log in with MFA credentials
// -----------------------------------------------------------------------------
const loginMfa = async () => {
// Send username, password, and a freshly generated TOTP code
let res = await client.post(
"/mfa/login",
{
username,
password,
mfaCode: generateTotp(mfaSecret),
},
{
headers: {
Authorization: apiKey,
},
}
);
// The response includes an access token, refresh token, and expiry info
return {
token: res.data.token,
refreshToken: res.data.refreshToken,
expiryInstant: res.data.tokenExpirationInstant,
};
};
// -----------------------------------------------------------------------------
// Step 3: Refresh JWT access token
// -----------------------------------------------------------------------------
const refreshToken = async (tokens: {
token: string;
refreshToken: string;
}) => {
// Exchange the expired/expiring access token for a new one
let res = await client.post("/login/jwt/refresh", {
accessToken: tokens.token,
refreshToken: tokens.refreshToken,
});
// Return the refreshed tokens
return {
token: res.data.token,
refreshToken: res.data.refreshToken,
};
};
// -----------------------------------------------------------------------------
// Step 4: Example protected API request (fetch user data)
// -----------------------------------------------------------------------------
const getUsers = async (token: string) => {
// Access a protected endpoint using the Bearer token
const res = await client.get("/users", {
headers: { Authorization: `Bearer ${token}` },
});
return res.data;
};
// -----------------------------------------------------------------------------
// End-to-end example request flow
// -----------------------------------------------------------------------------
const exampleRequestFlow = async () => {
// 1. Log in with MFA to obtain tokens
const tokenInfo = await loginMfa();
console.log("initial login result:", tokenInfo);
// 2. Make an authenticated API request
const userRes = await getUsers(tokenInfo.token);
console.log("user get data:", userRes);
// 3. Refresh the access token using the refresh token
const refreshRes = await refreshToken(tokenInfo);
console.log("refresh result:", refreshRes);
};
// -----------------------------------------------------------------------------
// Execution
// -----------------------------------------------------------------------------
// Run MFA setup only once per user to register the secret
// setUpMfa();
// Run the example authentication and request flow
exampleRequestFlow();
Updated about 2 months ago
