Authentication & OAuth 2.0

Guidance for managing access and refresh tokens across Bead integrations. This page covers both integration models you support today: Payments and Boarding and Entity Management.

Integration identities at a glance

Model
Client ID
Credential subject
Grant type
Token cache key
Latency posture

Payments

Payments client

Terminal username and password (for example [email protected])

Password grant (terminal scoped)

terminalId (or clientId + merchantId + terminalId if you key by all)

Optimize for low latency and high volume

Boarding and Entity Management

Boarding client

Single integrator username and password

Password grant (today)

clientId (often a single token is sufficient)

Latency is secondary and auditability is primary

Token types and lifetimes

Token
Lifetime
How it is used

Access token

3600 seconds

Sent on every API call in Authorization: Bearer <access_token>

Refresh token

36000 seconds

Exchanged with the identity server to obtain a new access token and a new refresh token

Lifetimes can vary by environment and client. Always honor the expires_in and refresh_expires_in values returned by your token endpoint.

Standard policy for both models

  1. Cache the access token and refresh two to five minutes before expiry.

  2. If an API call returns 401 Unauthorized, perform one refresh and retry the request once.

  3. Always store the newest refresh token that the identity server returns.

  4. If refresh fails with invalid_grant or the refresh token is expired, perform a full sign in.

  5. Keep tokens on the server only. Do not log tokens. Encrypt at rest if persisted.

  6. In multi process or multi worker apps, ensure only one worker performs the refresh and others reuse the result.

Payments integration (terminal scoped credentials)

Goal Fast and reliable requests at scale without authenticating on the hot path.

Policy highlights

  • Do not call the token endpoint per transaction.

  • Maintain a shared token cache keyed by terminalId (or by clientId + merchantId + terminalId if your app organizes this way).

  • Refresh proactively with a small buffer and add random jitter so many tokens do not refresh at the same second.

  • Use a leader process to perform the refresh and fan out the new pair to workers.

  • Warm the cache for your busiest terminals at service start or during off peak windows.

  • Only do a full sign in if refresh fails.

Boarding and entity management (password grant today)

Goal Safe and auditable operations where latency is less critical.

Policy highlights

  • Use the same refresh and 401 retry rules. A larger pre expiry buffer is fine since latency is not a concern.

  • A single service level token is usually sufficient for the whole administrative workload.

  • Emphasize least privilege scopes and clear audit logging of who did what and when.

Why use refresh tokens

Security and reliability first

  • Renew access without resending primary credentials.

  • The identity server can revoke a refresh token family to cut off access quickly.

  • Each refresh issues a fresh access token so roles and scopes remain current.

Performance

  • One light refresh call is faster and cheaper than a full sign in.

  • Fewer round trips and fewer failures under load.

With expires_in = 3600 and refresh_expires_in = 36000, integrators can keep a one hour access token hot and silently renew for about ten hours without handling passwords again.

Error handling quick reference

HTTP
Error string
When it happens
What to do

401

Access token missing, malformed, or expired

Refresh once and retry once. If it still fails, perform full sign in.

400

invalid_grant

Refresh token expired, revoked, or already used

Perform full sign in to obtain a new token pair.

400

invalid_client or unauthorized_client

Client is not allowed for the grant type in use

Verify client_id and grant settings.

400

invalid_scope

Requested scopes are not permitted

Adjust requested scopes.

Request examples

Payments — password grant using terminal credentials

POST https://identity.beadpay.io/realms/<realm>/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=password&
client_id=<payments_client_id>&
username=<terminalId>@beadpay.io&
password=<terminal_password>&
scope=openid profile email

Boarding — password grant using integrator credential

POST https://identity.beadpay.io/realms/<realm>/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=password&
client_id=<boarding_client_id>&
username=<integrator_username>&
password=<integrator_password>&
scope=openid profile email

Refresh (both models)

POST https://identity.beadpay.io/realms/<realm>/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&
client_id=<same_client_id_as_above>&
refresh_token=<refresh_token>

Authorization header on API calls

Authorization: Bearer <access_token>

Minimal refresh decision logic

Proactive check before calling an API

  1. If now >= issued_at + expires_in − buffer then refresh.

  2. Otherwise use the cached access token. Suggested buffer: 120 to 300 seconds. Add small random jitter in high volume systems.

Reactive fallback on failure

  1. If a request returns 401 and you have not just refreshed, perform one refresh and retry once.

  2. If it still fails, perform a full sign in and alert.

Model specific checklists to share with integrators

Payments token management

  • Maintain a shared cache keyed by terminalId, or by client + merchant + terminal if your app needs that.

  • Refresh with buffer and jitter. One leader refreshes and others reuse.

  • Never fetch a token per transaction.

  • On 401, refresh and retry once only.

  • If refresh fails, bootstrap a new pair off the hot path and alert.

Boarding and entity management token management

  • Use one backend token for administrative calls.

  • Same refresh and 401 retry rules, with a generous buffer.

  • Emphasize scopes, least privilege, and audit trails.

Last updated