OIDCInteractionBridge
Package: @nauth-toolkit/oidc-provider
Type: Service
Drives the login and consent steps of a pending authorization request from your own routes.
import { OIDCInteractionBridge } from '@nauth-toolkit/oidc-provider';
Overview
Call these from ordinary routes in your application, inside your guard chain, so the request context that identifies the current user is populated. Pass the framework request and response straight through — Express objects, Fastify request/reply, or NAuthRequest.raw / NAuthResponse.raw all work.
Every method answers with a redirectTo rather than issuing a 302, so a single-page app can drive the flow with fetch and navigate itself.
Every decision is also written to your audit trail as an OIDC_* event, with the relying party attached, unless auditLogs.enabled is false.
With NestJS, inject it with @Inject(NAUTH_OIDC_BRIDGE). The shipped controller already does.
Constructing it yourself
Only needed outside NestJS, or when you register the bridge in your own module.
import { OIDCInteractionBridge } from '@nauth-toolkit/oidc-provider';
import { IdpSessionGate } from '@nauth-toolkit/core/internal';
const bridge = new OIDCInteractionBridge(
provider,
new IdpSessionGate(dataSource.getRepository(User), authConfig),
);
A third argument accepts an AuthAuditService; omit it and no audit events are written.
Methods
abort()
Abandon a pending interaction, so the relying party gets a clean access_denied instead of waiting on a browser tab the user closed.
async abort(req: unknown, res: unknown): Promise<InteractionRedirectDTO>
Parameters
req- The framework requestres- The framework response
Returns
Errors
| Code | When | Details |
|---|---|---|
OIDC_INTERACTION_NOT_FOUND | Expired or already resolved | { cause: string } |
Throws NAuthException with the code listed above.
completeConsent()
Record the user's consent decision. On approval this saves a Grant — the durable record of what this user let this client see — and resolves the interaction with its id.
async completeConsent(
req: unknown,
res: unknown,
decision: { approve: boolean; scopes?: string[] },
): Promise<InteractionRedirectDTO>
Parameters
req- The framework requestres- The framework responsedecision.approve- Whether the user approveddecision.scopes- A narrowed scope set. Omit to grant every missing scope
Returns
Errors
| Code | When | Details |
|---|---|---|
OIDC_INTERACTION_NOT_FOUND | Expired, or the grant is gone | { uid?: string, cause?: string } |
OIDC_LOGIN_REQUIRED | The session lapsed while the consent screen was open | { uid: string, reason: string } |
Throws NAuthException with the codes listed above.
A denied account does not throw — the interaction resolves with access_denied, so the returned redirectTo carries a protocol error back to the relying party. completeLogin() behaves the same way.
completeLogin()
Complete the login step for the currently authenticated user.
async completeLogin(req: unknown, res: unknown): Promise<InteractionRedirectDTO>
The account is re-read from the database here, so a user disabled, locked, or newly required to change their password since their access token was issued cannot have an id_token minted for a third party.
Parameters
req- The framework requestres- The framework response
Returns
Errors
| Code | When | Details |
|---|---|---|
OIDC_INTERACTION_NOT_FOUND | Expired or already resolved | { cause: string } |
OIDC_LOGIN_REQUIRED | No completed login behind the request | { uid: string, reason: string } |
Throws NAuthException with the codes listed above.
details.reason is the session gate's verdict: 'no_session', 'password_change_required' or 'email_verification_required'.
getState()
Describe a pending interaction so the frontend can decide what to render. Callable anonymously — the answer for a signed-out user is precisely what tells the frontend to send them to login.
async getState(req: unknown, res: unknown): Promise<InteractionStateDTO>
Parameters
req- The framework requestres- The framework response
Returns
Errors
| Code | When | Details |
|---|---|---|
OIDC_INTERACTION_NOT_FOUND | No such pending request | { cause: string } |
Throws NAuthException with the codes listed above.
Related APIs
- createOIDCInteractionController - The shipped NestJS routes
- InteractionStateDTO - What
getState()returns - OIDCSessionTerminator - The logout side