Skip to main content

AuthService

The AuthService contains the server-side core logic of the authentication system: it orchestrates the providers, encrypts/decrypts the JWE session tokens, and syncs the authenticated server context. It is registered by the AuthModule and available via dependency injection; the AuthController is a thin HTTP layer over it.

import { AuthService, USER_CLAIM } from '@archibald/auth';

USER_CLAIM ('user') is the token claim holding the (filtered) user object; each provider's tokens are stored under a claim named after the provider.

Flow methods

Each flow method returns a LoginResult<User, State> ({ token, tokenExpiresAt, refresh, refreshExpiresAt, user, redirectUrl?, state?, exception? }) — on failure the token is cleared and exception is set instead of throwing.

MethodDescription
login(credentials)Password login: UserAuthProvider.login() → system providers → loadUser → sign & set tokens. Claims are stamped authProtocol: 'password'.
token(credentials)OIDC code exchange (native flow): identical pipeline via UserAuthProvider.token(), claims stamped authProtocol: 'oidc'.
loginUrl()Returns { loginUrl } from UserAuthProvider.loginUrl() — the IdP authorize URL (web OIDC flow, step 1).
redirectCallback()Handles the IdP redirect: UserAuthProvider.redirectCallback() → system providers → loadUser → sign & set tokens → returns redirectUrl.
refresh(refreshToken)Refreshes the session. Concurrent calls for the same refresh token are de-duplicated; the original authProtocol is preserved, so password- and OIDC-sessions refresh identically.
logout()No arguments (since v9 — tokens come from the request context). Logs out all system providers, then the user provider with both access and refresh token. Returns { isLoggedOut }.
check(token?)Boolean logged-in check for the current request.
loadUser() / getUser()Loads the user through the UserAuthProvider API.

Lifecycle hooks

loginSuccess(result), loginError(exception, result?), refreshSuccess, refreshError, redirectCallbackSuccess, redirectCallbackError — each delegates to the same-named hook on the UserAuthProvider when implemented. The default success shaping: header strategy returns { token, tokenExpiresAt, refresh, refreshExpiresAt, user }; cookie strategy returns only { user } (tokens never leave the server).

Token handling

Session tokens are JWE (encrypted, not just signed): alg: 'dir', enc: 'A256GCM', key derived from the configured secret — which therefore must be exactly 32 characters. The payload is the claim map built by TokenPayload plus sub ('login' or 'refresh'), iat, exp, and iss (= app.canonicalBaseUrl, validated on decrypt). Optional raw-deflate compression via the token.compress option.

MethodDescription
getToken(type?)Reads the current request's token — type is 'token' (default) or 'refreshToken'. Cookie strategy: from the nct/ncr cookie; header strategy: from Authorization: Bearer …. Prefers freshly renewed tokens from session.artifacts.
decodeToken(token?)Decrypts and validates. Returns the payload, { exp: 0 } for an expired token (distinguishable from a broken one), or null.
isTokenValid(decoded)true when the decoded payload's exp is in the future.
checkSignAndSetToken(payloads, subject, options?)Signs the token payloads into JWE tokens and calls syncAuthenticatedContext() — flips the server context to authenticated and, in the cookie strategy, sets the nct/ncr cookies.
clearToken()Clears the session tokens/cookies.
getCookieOptions(type)Cookie options for 'token' or 'refresh', from the module options plus computed expires.
getAuthHeaders()Auth headers for outgoing backend requests based on the current session.

Secret rotation: when token.secret_rotation / refresh.secret_rotation is configured, decryption transparently retries with the rotation secret, allowing zero-downtime secret changes.

Provider management

MethodDescription
registerProvider(provider) / registerProviders(providers)Called by the AuthModule during startup.
getProviders() / getStaticProviders()Access registered providers.
initializeProviders()Runs each provider's initialize() (on server start, in server context).
refreshStatic() / getStaticClaim()Re-acquire / read static (guest) provider tokens.

Options & defaults

AuthService.options are the resolved AuthModule options, deep-merged over these defaults:

{
strategy: { type: 'cookie' },
token: {
expirationTime: '5m', secret: '', secret_rotation: '', compress: false,
filter: (user) => user,
cookie: { expiresIn: '10m', sameSite: 'lax' }
},
refresh: {
expirationTime: '1y', secret: '', secret_rotation: '',
cookie: { expiresIn: '1y', sameSite: 'lax' }
}
}

token.filter controls which user fields are embedded in the token (DefaultTokenUser — keep it small; the full user is loaded through the API when needed).

Errors

Exported error classes thrown/returned by the service and providers: CredentialsInvalidError, TokenMissingError, TokenCreationError, TokenDecryptionError, TokenInvalidError, UserUnauthorizedError, ClaimMissingError, RedirectUrlMissingError, MultipleProviderError.

Relates to

  • AuthModule — registers this service, the controller, routes, and Hapi auth strategies.
  • getSession() — read the authenticated session anywhere in the backend.
  • Secure Token Handling — conceptual view of the token lifecycle.