Skip to content

Authentication API

The authentication API is served by the consystence-auth service. It handles account creation, login, token management, and identity verification.

OIDC Discovery

GET /.well-known/openid-configuration

Returns the OpenID Connect discovery document. Used by site servers and clients to discover endpoints and token signing keys.

GET /.well-known/jwks.json

Returns the JSON Web Key Set used to validate JWT signatures.

curl https://account.consystence.dev/.well-known/jwks.json

Login

POST /api/auth/login

Authenticate with email and password. Returns a JWT access token and a refresh token.

Request:

{
  "email": "operator@bhp.com",
  "password": "..."
}

Response (200):

{
  "accessToken": "eyJhbGciOiJSUzI1NiIs...",
  "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2g...",
  "expiresIn": 3600,
  "tokenType": "Bearer"
}

The access token contains these claims:

{
  "sub": "a3f1c9e0-7b2d-4e8a-b5f6-1d2e3f4a5b6c",
  "email": "operator@bhp.com",
  "org": "d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
  "org_slug": "bhp",
  "org_role": "operator",
  "orgs": [
    "d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
    "e5f6a7b8-9c0d-1e2f-3a4b-5c6d7e8f9a0b"
  ],
  "platform_admin": false,
  "iat": 1708300800,
  "exp": 1708304400
}

Note

If the account has MFA enabled, the login response returns a mfaRequired: true flag and a mfaToken instead of the access token. Complete the MFA challenge to receive the full token pair.

Token Refresh

POST /api/auth/refresh

Exchange a refresh token for a new access token. Refresh tokens are single-use — each call returns a new refresh token.

Request:

{
  "refreshToken": "dGhpcyBpcyBhIHJlZnJlc2g..."
}

Response (200):

{
  "accessToken": "eyJhbGciOiJSUzI1NiIs...",
  "refreshToken": "bmV3IHJlZnJlc2ggdG9rZW4...",
  "expiresIn": 3600,
  "tokenType": "Bearer"
}

Registration

POST /api/auth/register

Create a new account. A verification email is sent automatically.

Request:

{
  "email": "user@example.com",
  "password": "...",
  "firstName": "Jane",
  "lastName": "Smith"
}

Response (201):

{
  "id": "a3f1c9e0-7b2d-4e8a-b5f6-1d2e3f4a5b6c",
  "email": "user@example.com",
  "emailVerified": false
}

Email & Phone Verification

POST /api/auth/verify-email

Confirm an email address using the code sent during registration.

Request:

{
  "email": "user@example.com",
  "code": "123456"
}

POST /api/auth/verify-phone

Confirm a phone number. A verification SMS is sent when a phone number is added to the account.

Request:

{
  "phone": "+61400000000",
  "code": "123456"
}

Multi-Factor Authentication

POST /api/auth/mfa/enable

Enable MFA for the authenticated account. Returns a TOTP secret and QR code URL for authenticator app setup.

Request:

Authorization: Bearer <access_token>

Response (200):

{
  "secret": "JBSWY3DPEHPK3PXP",
  "qrCodeUrl": "otpauth://totp/Consystence:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Consystence"
}

POST /api/auth/mfa/verify

Complete the MFA challenge during login.

Request:

{
  "mfaToken": "...",
  "code": "123456"
}

Response (200):

Returns the full access token and refresh token pair (same format as login).

Organisation Switch

POST /api/auth/switch-org

Switch the organisation context for the current session. Returns a new access token scoped to the requested organisation.

Request:

Authorization: Bearer <access_token>
Content-Type: application/json

{
  "orgId": "e5f6a7b8-9c0d-1e2f-3a4b-5c6d7e8f9a0b"
}

Response (200):

{
  "accessToken": "eyJhbGciOiJSUzI1NiIs...",
  "refreshToken": "c3dpdGNoZWQgcmVmcmVzaA...",
  "expiresIn": 3600,
  "tokenType": "Bearer"
}

Password Management

POST /api/auth/password/reset

Request a password reset email. Always returns 200 regardless of whether the email exists (to prevent enumeration).

Request:

{
  "email": "user@example.com"
}

POST /api/auth/password/change

Change the password for the authenticated account.

Request:

Authorization: Bearer <access_token>
Content-Type: application/json

{
  "currentPassword": "...",
  "newPassword": "..."
}