import { Repository } from 'typeorm'; import { BaseUser } from '../entities/user.entity'; import { NAuthConfig } from '../interfaces/config.interface'; import { IUser } from '../interfaces/entities.interface'; import { NAuthLogger } from '../utils/nauth-logger'; /** * Why an identity-provider request cannot proceed as it stands. */ export type IdpGateResult = { /** The user is fully authenticated; the request may proceed. */ status: 'authenticated'; user: IUser; } | { /** The user must (re-)authenticate. Park the request and send them to login. */ status: 'login_required'; reason: 'no_session' | 'password_change_required' | 'email_verification_required'; } | { /** The user is known but must not be issued anything. Fail the request outright. */ status: 'denied'; reason: 'account_disabled' | 'account_locked' | 'account_unavailable'; /** * External identifier of the account that was refused. * * Present whenever the request carried a session — which is every `denied` * verdict, since the check is what identified the account in the first place. It * is what lets a refusal be attributed in an audit trail. */ sub: string; }; /** * Identity Provider Session Gate * * Answers one protocol-neutral question: *is there a fully completed nauth login * behind this request, good enough to issue credentials to a relying party?* * * The OAuth2 authorization endpoint uses it before minting an authorization code. * Nothing about it is OAuth-specific, so a future SAML identity provider — or any * other protocol where a third party asks this application to vouch for a user — can * use the same gate rather than reimplementing the checks. * * Relationship to the login flow: reaching this point with a `CURRENT_USER` in * context already means the auth handler validated an access token, and such a token * is only issued once the challenge state machine reaches `AUTHENTICATED` — email and * phone verification, MFA setup and MFA verification all satisfied. What this gate * adds is a re-read of the account state that can change *after* a token was issued: * an administrator disabling the account, locking it, or forcing a password change * mid-session. Those must stop a third party from being handed credentials, even * though the bearer's own session is still technically valid. * * @example * ```typescript * const gate = await idpSessionGate.evaluate(); * if (gate.status === 'login_required') { * const requestId = await codeStore.parkRequest(validated); * return { redirectTo: buildLoginUrl(requestId) }; * } * if (gate.status === 'denied') { * throw new NAuthException(AuthErrorCode.OIDC_ACCESS_DENIED, 'Account unavailable'); * } * // gate.user is fully authenticated * ``` */ export declare class IdpSessionGate { private readonly userRepository; private readonly config; private readonly logger?; constructor(userRepository: Repository, config: NAuthConfig, logger?: NAuthLogger | undefined); /** * Evaluate the currently authenticated user, if any. * * Reads the user from request context (`CURRENT_USER`), then re-reads the account * from the database so that state changed since the access token was issued is * honoured. * * @returns Whether the request may proceed, needs a login, or must be refused */ evaluate(): Promise; /** * Whether the account is locked right now. * * A null `lockedUntil` is a permanent lock (an administrator disabling the * account); a past `lockedUntil` is a temporary lock that has already elapsed, and * is not treated as locked. */ private isCurrentlyLocked; /** * Whether this deployment requires a verified email before a user is considered * fully authenticated. */ private requiresEmailVerification; } //# sourceMappingURL=idp-session-gate.service.d.ts.map