/// import * as Bluebird from 'bluebird'; import { RouterContext, Middleware } from './router'; export interface Acl { isAllowed(userId: string, resource: string, permissions: string | string[]): Bluebird; addUserRoles(userId: string, roles: string | string[]): Bluebird; removeUserRoles(userId: string, roles: string | string[]): Bluebird; userRoles(userId: string): Bluebird; } /** Raised when a user is not found during authentication. */ export declare class UserNotFoundError extends Error { constructor(message?: string); } /** Raised when a token has expired. */ export declare class TokenExpiryError extends Error { constructor(message?: string); } /** Raised when a token is invalid. */ export declare class TokenInvalidError extends Error { constructor(message?: string); } /** Raised when access to a route isn't allowed */ export declare class AuthorisationError extends Error { constructor(message?: string); } /** * The payload representation of a bearer token. * This is encrypted into a secure token when sent to clients. */ export interface AuthPayload { /** The subject of the token (i.e. user identifier). */ sub: string; /** The token issue time (in unix). */ iat: number; /** The expiry time of the token (in unix). */ exp: number; } /** * A bearer authentication token that can be sent and received by clients. */ export declare type AuthToken = string; /** * Options for configuring the auth init route. */ export interface AuthInitOptions { /** The name of the header to look for the bearer token. */ header?: string; /** * Whether authentication is optional, i.e. whether * other routes should be inaccessible * if the user is not logged. Defaults to false. */ optional?: boolean; } /** * Manages backend authentication for a web application using bearer tokens. * * This should be extended by an application-specific child class * with the relevant method overrides to work with an application's * internal representation of a user model. * * It's important that the relevant middleware is used on either * the application or a router. * * @see init, login, register * @param T The type representing a user model. */ export declare abstract class Auth { /** * The secret key used to encrypt/decrypt the tokens. * * Changing the secret key will invalidate all existing logins * to the system and there is no guarantee that this will work smoothly * with whatever MVC frontend a client is using. */ protected secret: string; /** * The number of days that generated authentication tokens will * last for. This should be a high number and defaults * to two weeks. */ protected expiryDays: number; /** * The ACL authorisation to check permissions with */ protected acl: Acl; /** * @param secret The secret key. * @param expiryDays The number of days auth tokens will be valid for. */ constructor(secret: string, expiryDays?: number, acl?: Acl); /** * Produces a bearer token that can be sent to a client securely and then used * to login to the web application. * * It is crucial that this is only sent to a user upon successful * login or registration, as this token will give them full access to * the relevant user model. * * @see consumeToken * @param user The user to generate an auth token for. * @returns A promise that resolves to an auth token. */ protected produceToken(user: T): Promise; /** * Consumes a bearer token and translates it to the relevant user model. * This will fail if the user could not be found or the token has expired. * * @see produceToken * @throws TokenExpiryError, UserNotFoundError * @param token The auth token to find a user from. * @returns A promise that resolves to the user model, or rejects if not * found/the token has expired. */ protected consumeToken(token: AuthToken): Promise; /** * An abstract method that fetches a user from a relevant identifier. * This should be implemented by a child class and will be used to * find a user from a decrypted token's original identifier value. * This will fail if the user could not be found. * * @rejects UserNotFoundError * @param id The identifier. * @returns A promise that resolves to the user model, or rejects if not found. */ protected abstract getUser(id: string): Promise; /** * An abstract method that fetches the identifier for a specific user * in order to generate an auth token. * * The identifier should be unique as it in turn will be used to find a user * when the token is decrypted. It is however not necessarily a constraint * of this design to have the identifier not unique if required. * * @param user The user to get the identifier for. * @returns The user identifier. */ protected abstract getIdentifier(user: T): string; /** * An abstract method that fetches the roles for a specific user * in order to restrict access to resources/routes * * @param user The user to get the roles for * @returns The user roles */ protected abstract getRoles(user: T): Promise; /** * Log a user in using a provided router context * with all of the request information available. * This should reject with a UserNotFoundError * if the login details were incorrect. * If the promise resolves with a user, * then the a new token will be immediately * sent to the user marking a successful login. * * This must be implemented by the child * authentication manager class if a login route * is required. Without a child implementation * it will always reject. * * @rejects UserNotFoundError, Error * @see login */ protected loginUser(_ctx: RouterContext): Promise; /** * Register a user in using a provided router context * with all of the request information available. * If the promise resolves with a user, * then the a new token will be immediately * sent to the user marking a successful login. * * This must be implemented by the child * authentication manager class if a register route * is required. Without a child implementation * it will always reject. * * @rejects Error * @see login */ protected registerUser(_ctx: RouterContext): Promise; /** * A middleware used to check if the user is authed, * and if so populates the router context with the user * object. * * This should be added on the application during * its configuration. * * @returns The auth initialization middleware. */ authenticated(options?: AuthInitOptions): Middleware; /** * A middleware used to login a user. * * This should be added on the router at the relevant URL. * * @returns The auth login middleware. */ login(): Middleware; /** * A middleware used to register a user. * * This should be added on the router at the relevant URL. * * @returns The auth registration middleware. */ register(): Middleware; /** * A middleware used to ensure a user is authorised to access a route * * This should be added on the router at the relevant URL. * * @returns The authorisation middleware */ authorised(resource: string, permissions: string | string[]): Middleware; }