Authentication Providers
Providers are the server-side connectors between the AuthModule and an external system (SAP Commerce, CDC, a custom IdP). They validate credentials, obtain and refresh tokens, and load user data. Three base classes exist, registered together via the AuthModule's providers option; the AuthService fans out to them by role.
UserAuthProvider
Authenticates registered users. Since v9 the contract covers both the deprecated password flow and the OIDC authorization code flow:
abstract class UserAuthProvider<TUser, TOptions, TState> {
// --- abstract: every provider must implement these ---
abstract validateToken(token: ApiServiceToken | null): Promise<boolean>;
abstract logout(tokens?: ApiServiceTokens): Promise<void | boolean>;
abstract refresh(refreshToken: string, expiresAt?: number): Promise<UserLoginResponse<TUser, TState> | null>;
abstract loadUser(tokens: Map<string, ApiServiceToken>, state?: TState): Promise<TUser | null>;
// --- flow entry points (interface, mandatory since v9) ---
login(credentials?: AuthCredentials): Promise<UserLoginResponse<TUser, TState> | null>; // password flow (deprecated)
token(credentials?: AuthCredentials): Promise<UserLoginResponse<TUser, TState> | null>; // OIDC code exchange (native)
loginUrl(): Promise<string>; // OIDC: build the IdP authorize URL
redirectCallback(): Promise<UserLoginResponse<TUser, TState>>; // OIDC: handle the IdP redirect
// --- optional lifecycle hooks ---
loginSuccess(result) / loginError(exception, result?)
refreshSuccess(result) / refreshError(exception, result?)
redirectCallbackSuccess(result) / redirectCallbackError(exception, result?)
initialize(server: CoreServer)
}
The lifecycle hooks let a provider shape the response or run side effects after the core flow — e.g. CommerceUserAuthProvider.redirectCallbackSuccess() merges the anonymous cart and wishlist into the freshly logged-in user's account.
The reference implementation is CommerceUserAuthProvider (@archibald/commerce): OIDC discovery via openid-client, PKCE (S256) and state validation through short-lived httpOnly cookies, token introspection for validateToken, and refresh-token revocation on logout. To customize, extend it:
import { CommerceUserAuthProvider } from '@archibald/commerce/auth';
export class MyB2BUserAuthProvider extends CommerceUserAuthProvider {
override async loadUser(tokens, state) { ... }
}
SystemAuthProvider
Authenticates the server itself against a backend (client-credentials style). After every successful user login (any protocol), the AuthService calls each registered SystemAuthProvider's login(mainToken, state) and merges the returned tokens into the session token payload — each provider contributes a claim under its own name.
StaticAuthProvider
Provides anonymous/guest tokens with pre-configured credentials (e.g. CommerceStaticAuthProvider using hybris.oauth). The AuthModule validates static tokens on every request (onRequest extension) and transparently re-acquires them when a backend answers 401 (onPreResponse extension).
Registration
new AuthModule({
providers: [
new CommerceUserAuthProvider({
config: () => this.configService.get('hybris.api'),
credentials: () => this.configService.get('hybris.oauth')
}),
new CommerceStaticAuthProvider({
config: () => this.configService.get('hybris.api'),
credentials: () => this.configService.get('hybris.oauth')
})
],
options: () => ({ ... })
});
Each provider's tokens end up as a named claim in the encrypted session token, alongside the user claim — see Secure Token Handling.
Relates to
- AuthModule — where providers are registered.
- AuthService — orchestrates the provider fan-out.
- OIDC Login Flow — how
loginUrl/redirectCallback/tokenare driven.