Authentication

OAuth Authentication

OAuth 2.1 Authorization Code flow with PKCE and optional OpenID Connect for Billabex.

Billabex uses OAuth 2.1 Authorization Code flow with PKCE for secure API access. OpenID Connect (OIDC) is available when you include the openid scope. This guide explains the flow, supported features, token lifetimes, refresh behavior, and all available endpoints.

Overview

At a high level, the flow looks like this:

  1. You create an OAuth client in the Developer Portal and configure allowed redirect URIs and scopes.
  2. Your app redirects the user to the authorization endpoint with PKCE parameters and requested scopes.
  3. The user signs in, reviews consent, and approves access.
  4. You receive an authorization code on your redirect URI.
  5. You exchange the code (plus the PKCE verifier) for tokens at the token endpoint.
  6. You call the API with the access token and refresh it when needed.

OAuth in Billabex is:

  • User-centric: access is granted by a user
  • Token-based: no API keys
  • Scoped: permissions are explicit and minimal
  • Time-bound: all tokens have a limited lifetime

Token Types and Lifetimes

Billabex issues several token types. Each has a specific purpose and a fixed TTL.

Token TypeTTL (seconds)TTL (human)Description
Access Token36001 hourUsed to call the public API
Refresh Token259200030 daysUsed to obtain new access tokens
Authorization Code60010 minutesTemporary code exchanged for tokens
ID Token (OIDC)60010 minutesIdentity token (OIDC best practice)

Notes:

  • Access tokens are intentionally short-lived.
  • Authorization codes and ID tokens follow OIDC security best practices.
  • Expired tokens are rejected automatically.

OAuth Actors

An OAuth flow involves three parties:

  • Resource Owner – the user granting access
  • Client Application – your application
  • Authorization Server – Billabex OAuth server

Your application never handles user credentials directly.

Supported OAuth 2.1 Features

Billabex follows OAuth 2.1 conventions with secure defaults.

  • Authorization code flow only (response_type=code)
  • PKCE required (S256 recommended, plain supported for legacy clients)
  • Refresh tokens with rotation on every use
  • Token endpoint authentication
    • none for public clients
    • client_secret_basic or client_secret_post for confidential clients
  • Dynamic client registration (RFC 7591 / 7592)
  • Token revocation (RFC 7009)

The Developer Portal creates confidential clients by default and shows the client_secret only once.

OAuth Endpoints

All OAuth endpoints are under the API base URL.

Authorization
GET [baseURL]/api/oauth/authorize

Token
POST [baseURL]/api/oauth/token

Revocation
POST [baseURL]/api/oauth/revoke

UserInfo (OIDC)
GET [baseURL]/api/oauth/userinfo

Dynamic registration
POST [baseURL]/api/oauth/register

Client configuration management
GET/PUT/DELETE [baseURL]/api/oauth/register/{clientId}

Discovery and JWKS

Public endpoints at the root domain:

  • [baseURL]/.well-known/oauth-authorization-server
  • [baseURL]/.well-known/openid-configuration
  • [baseURL]/.well-known/jwks.json

Authorization Request

Redirect the user to the authorization endpoint with the following parameters:

  • client_id (required)
  • redirect_uri (required, must match exactly)
  • response_type=code (required)
  • scope (recommended)
  • code_challenge (required)
  • code_challenge_method=S256 (recommended)
  • state (required)
  • nonce (required when using openid)

Always validate state (and nonce for OIDC).

Authorization Code

After user approval, Billabex redirects back to your redirect_uri with:

  • code
  • state

The authorization code:

  • Is valid for 10 minutes
  • Can be used only once

Token Exchange (authorization_code)

POST [baseURL]/api/oauth/token

Required fields:

  • grant_type=authorization_code
  • code
  • redirect_uri
  • code_verifier
  • client_id
  • client_secret (confidential clients)

Successful response:

{
  "access_token": "...",
  "refresh_token": "...",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "...",
  "id_token": "..."
}

id_token is present only when openid is granted.

Refreshing Access Tokens

Access tokens expire after 1 hour.
Use the refresh token to obtain a new access token.

Refresh Token Rotation Policy

Billabex enforces refresh token rotation.

This means:

  • Every refresh request revokes the previous refresh token
  • A new refresh token is issued on each refresh
  • Only the most recently issued refresh token remains valid

Important clarifications:

  • Refreshing an access token does not revoke access by itself
  • The refresh operation invalidates the previous refresh token
  • You must persist the new refresh token immediately
  • Reusing an old refresh token will fail

Refresh Token Request

POST [baseURL]/api/oauth/token

{
  "grant_type": "refresh_token",
  "refresh_token": "CURRENT_REFRESH_TOKEN",
  "client_id": "CLIENT_ID",
  "client_secret": "CLIENT_SECRET"
}

Response:

{
  "access_token": "...",
  "refresh_token": "...",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "..."
}

Accessing the API

Send the access token as a Bearer token in the Authorization header on all API calls.

Scopes are enforced per endpoint. Use the Scopes guide to request the minimum required permissions.

Token Revocation

Revoke tokens when a user disconnects your integration.

Fields:

  • token
  • token_type_hint (optional)

OpenID Connect (OIDC)

OIDC is enabled when the openid scope is requested.

OIDC Scopes

  • openid
  • profile
  • email

ID Token

  • Returned only when openid is granted
  • Must be validated (signature, issuer, audience, expiry, nonce)

UserInfo Endpoint

Returns user claims allowed by granted scopes.

Security Best Practices

  • Always use HTTPS
  • Always use PKCE
  • Validate state and nonce
  • Store tokens securely
  • Rotate refresh tokens atomically
  • Never log tokens
  • Request the minimum scopes needed

Next Steps

Support

Questions about OAuth or OIDC?
Contact us via the website contact form.