@adonisjs/auth
Version:
Official authentication provider for Adonis framework
222 lines (221 loc) • 7.39 kB
TypeScript
import type { HttpContext } from '@adonisjs/core/http';
import type { ApplicationService, ConfigProvider } from '@adonisjs/core/types';
import type { AuthManager } from './auth_manager.ts';
import type { GUARD_KNOWN_EVENTS } from './symbols.ts';
/**
* Authentication response to login a user as a client.
* This response is used by Japa plugins to set up authentication
* state during testing.
*
* @example
* const response: AuthClientResponse = {
* cookies: { 'auth-token': 'abc123' },
* session: { userId: 1 },
* headers: { 'Authorization': 'Bearer token' }
* }
*/
export interface AuthClientResponse {
/**
* HTTP headers to be set for authentication
*/
headers?: Record<string, any>;
/**
* Cookies to be set for authentication
*/
cookies?: Record<string, any>;
/**
* Session data to be set for authentication
*/
session?: Record<string, any>;
}
/**
* A set of properties a guard must implement to authenticate
* incoming HTTP requests. This is the core contract that all
* authentication guards must follow.
*
* @template User - The type of the authenticated user
*
* @example
* class SessionGuard implements GuardContract<User> {
* readonly driverName = 'session'
* user?: User
* isAuthenticated = false
* authenticationAttempted = false
*
* async authenticate(): Promise<User> {
* // Implementation
* }
* }
*/
export interface GuardContract<User> {
/**
* A unique name for the guard driver (e.g., 'session', 'api', 'basic')
*/
readonly driverName: string;
/**
* Reference to the currently authenticated user.
* Undefined when not authenticated.
*/
user?: User;
/**
* Returns logged-in user or throws an exception.
* Use this when you need to ensure the user is authenticated.
*
* @throws {RuntimeException} When user is not authenticated
*/
getUserOrFail(): User;
/**
* A boolean to know if the current request has been authenticated.
* Returns false if authentication was not attempted.
*/
isAuthenticated: boolean;
/**
* Whether or not the authentication has been attempted
* during the current request. Used to differentiate between
* "not attempted" and "attempted but failed".
*/
authenticationAttempted: boolean;
/**
* Authenticates the current request and throws an
* exception if the request is not authenticated.
*
* @throws {E_UNAUTHORIZED_ACCESS} When authentication fails
*/
authenticate(): Promise<User>;
/**
* Check if the current request has been authenticated
* without throwing an exception. Use this for optional
* authentication scenarios.
*/
check(): Promise<boolean>;
/**
* The method is used to authenticate the user as client
* during testing. This method should return cookies, headers,
* or session state that can be used to simulate authentication.
*
* @param user - The user to authenticate as
* @param args - Additional arguments specific to the guard
*/
authenticateAsClient(user: User, ...args: any[]): Promise<AuthClientResponse>;
/**
* Symbol for inferring the events emitted by a specific guard.
* Used internally for type inference of guard events.
*/
[GUARD_KNOWN_EVENTS]: unknown;
}
/**
* The guard factory method is called to create an instance
* of a guard during an HTTP request. Each guard factory receives
* the HTTP context and returns a configured guard instance.
*
* @param ctx - The HTTP context for the current request
*
* @example
* const sessionGuardFactory: GuardFactory = (ctx) => {
* return new SessionGuard(ctx)
* }
*/
export type GuardFactory = (ctx: HttpContext) => GuardContract<unknown>;
/**
* Config provider for registering guards. Used for lazy loading
* of guard factories. The resolver function is called with the
* guard name and application instance to create the factory.
*
* @template Factory - The guard factory type
*
* @example
* const guardProvider: GuardConfigProvider<SessionGuardFactory> = {
* resolver: async (name, app) => {
* const sessionConfig = await app.container.make('session.config')
* return (ctx) => new SessionGuard(ctx, sessionConfig)
* }
* }
*/
export type GuardConfigProvider<Factory extends GuardFactory> = {
/**
* Resolver function that creates the guard factory
*
* @param name - The name of the guard being resolved
* @param app - The application service instance
*/
resolver: (name: string, app: ApplicationService) => Promise<Factory>;
};
/**
* Authenticators are inferred inside the user application
* from the config file. This interface is augmented automatically
* when you define your auth configuration.
*
* @example
* // After defining your auth config, this interface will be augmented:
* declare module '@adonisjs/auth/types' {
* interface Authenticators {
* web: SessionGuardFactory
* api: TokenGuardFactory
* }
* }
*/
export interface Authenticators {
}
/**
* Infer authenticators from the auth config. This utility type
* extracts the guards configuration from a config provider.
*
* @template Config - The auth config provider type
*
* @example
* type MyAuthenticators = InferAuthenticators<typeof authConfig>
* // Results in: { web: SessionGuardFactory, api: TokenGuardFactory }
*/
export type InferAuthenticators<Config extends ConfigProvider<{
default: unknown;
guards: unknown;
}>> = Awaited<ReturnType<Config['resolver']>>['guards'];
/**
* Helper to convert union to intersection. This utility type
* transforms a union of types into an intersection of types.
* Used internally for merging guard events.
*
* @template U - The union type to convert
*
* @example
* type Union = { a: string } | { b: number }
* type Intersection = UnionToIntersection<Union>
* // Results in: { a: string } & { b: number }
*/
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
/**
* Infer events based upon the configured authenticators.
* This type extracts and merges all events from all configured
* guards into a single intersection type.
*
* @template KnownAuthenticators - Record of guard names to guard factories
*
* @example
* type AuthEvents = InferAuthEvents<{
* web: SessionGuardFactory
* api: TokenGuardFactory
* }>
* // Results in intersection of all guard events
*/
export type InferAuthEvents<KnownAuthenticators extends Record<string, GuardFactory>> = UnionToIntersection<{
[K in keyof KnownAuthenticators]: ReturnType<KnownAuthenticators[K]>[typeof GUARD_KNOWN_EVENTS];
}[keyof KnownAuthenticators]>;
/**
* Auth service is a singleton instance of the AuthManager
* configured using the config stored within the user app.
* This interface is used for dependency injection and provides
* type-safe access to the auth manager.
*
* @example
* // In a service or controller:
* class UserController {
* constructor(private auth: AuthService) {}
*
* async login() {
* const user = await this.auth.createAuthenticator(ctx).authenticate()
* }
* }
*/
export interface AuthService extends AuthManager<Authenticators extends Record<string, GuardFactory> ? Authenticators : never> {
}
export {};