UNPKG

@hapi/bell

Version:

Third-party login plugin for hapi

310 lines (286 loc) 10.4 kB
import { AuthCredentials, Plugin, Request } from '@hapi/hapi'; declare module '@hapi/hapi' { interface ServerAuth { strategy(name: string, scheme: 'bell', options: BellOptions): void; } } export interface StringLikeMap { [key: string]: string | number; } export type Provider = | 'arcgisonline' | 'auth0' | 'azure' | 'bitbucket' | 'cognito' | 'digitalocean' | 'discord' | 'dropbox' | 'facebook' | 'fitbit' | 'foursquare' | 'github' | 'gitlab' | 'google' | 'googleplus' | 'instagram' | 'linkedin' | 'live' | 'medium' | 'meetup' | 'nest' | 'okta' | 'phabricator' | 'pingfed' | 'pinterest' | 'reddit' | 'salesforce' | 'slack' | 'spotify' | 'stripe' | 'trakt' | 'tumblr' | 'twitch' | 'twitter' | 'vk' | 'wordpress' | 'yahoo'; export type RequestPassThrough = (request: Request) => PromiseLike<AuthCredentials> | AuthCredentials; export interface OptionalOptions { /** * the name of the cookie used to manage the temporary state. * Defaults to 'bell-provider' where 'provider' is the provider name (or 'custom' for custom providers). * For example, the Twitter cookie name defaults to 'bell-twitter'. */ cookie?: string | undefined; /** * sets the cookie secure flag. * Defaults to true. */ isSecure?: boolean | undefined; /** * sets the cookie HTTP only flag. * Defaults to true. */ isHttpOnly?: boolean | undefined; /** * cookie time-to-live in milliseconds. * Defaults to null (session time-life - cookies are deleted when the browser is closed). */ ttl?: number | undefined; /** * the domain scope. * Defaults to null (no domain). */ domain?: string | undefined; /** * provider-specific query parameters for the authentication endpoint. * It may be passed either as an object to merge into the query string, * or a function which takes the client's request and returns an object. * Each provider supports its own set of parameters which customize the user's login experience. * For example: * * Facebook supports `display` ('page', 'popup', or 'touch'), `auth_type`, `auth_nonce`. * * Google supports `access_type`, `approval_prompt`, `prompt`, `login_hint`, `user_id`, `hd`. * * Twitter supports `force_login`, `screen_name`. * * Linkedin supports `fields`. */ providerParams?: StringLikeMap | ((request: Request) => StringLikeMap) | undefined; /** * allows passing query parameters from a bell protected endpoint to the auth request. * It will merge the query params you pass along with the providerParams and any other predefined ones. * Be aware that this will override predefined query parameters! * Default to false. */ allowRuntimeProviderParams?: StringLikeMap | boolean | undefined; /** * Each built-in vendor comes with the required scope for basic profile information. * Use scope to specify a different scope as required by your application. * It may be passed either as an object to merge into the query string, * or a function which takes the client's request and returns an object. * Consult the provider for their specific supported scopes. */ scope?: string[] | ((request: Request) => string[]) | undefined; /** * skips obtaining a user profile from the provider. * Useful if you need specific scopes, * but not the user profile. * Defaults to false. */ skipProfile?: boolean | undefined; /** * a configuration object used to customize the provider settings. * The built-in 'twitter' provider accepts the `extendedProfile` & `getMethod` options. * option which allows disabling the extra profile request when the provider * returns the user information in the callback (defaults to true). * The built-in 'github' and 'phabricator' providers accept the uri * option which allows pointing to a private enterprise installation (e.g. 'https://vpn.example.com'). * See Providers documentation for more information. */ config?: | { extendedProfile?: boolean | undefined; getMethod?: string | undefined } | { uri?: string | undefined } | undefined; /** * provider-specific query parameters for the token endpoint. * It may be passed either as an object to merge into the query string, * or a function which takes the client's request and returns an object. */ tokenParams?: StringLikeMap | ((request: Request) => StringLikeMap) | undefined; /** * an object of key-value pairs that specify additional * URL query parameters to send with the profile request to the provider. * The built-in facebook provider, * for example, could have fields specified to determine the fields returned from the user's graph, * which would then be available to you in the auth.credentials.profile.raw object. */ profileParams?: StringLikeMap | undefined; /** * allows passing additional OAuth state from initial request. * This must be a function returning a string, * which will be appended to the bell internal state parameter for OAuth code flow. */ runtimeStateCallback?(req: Request): string; // THESE ARE IN THE *REQUIRED* section but are actually not... /** * A boolean indicating whether or not you want the redirect_uri to be forced to https. * Useful if your hapi application runs as http, but is accessed through https. */ forceHttps?: boolean | undefined; /** * Set the base redirect_uri manually if it cannot be inferred properly from server settings. * Useful to override port, protocol, and host if proxied or forwarded. */ location?: string | ((req: Request) => string) | undefined; } export interface RequiredProviderOptions { /** * the cookie encryption password. * Used to encrypt the temporary state cookie used by the module in * between the authorization protocol steps. */ password: string; /** * the OAuth client identifier (consumer key). */ clientId: string; /** * the OAuth client secret (consumer secret) */ clientSecret: string; } export interface KnownProviderOptions extends RequiredProviderOptions, OptionalOptions { provider: Provider; } /** * @param uri the requested resource URI (bell will add the token or authentication header as needed). * @param params any URI query parameters (cannot include them in the URI due to signature requirements). */ export type AuthedRequest = (uri: string, params?: { [key: string]: string }) => Promise<object>; export interface Credentials { provider: Provider | 'custom'; token: string; query: StringLikeMap; /** * Varying data depending on provider. */ profile?: object | undefined; } export interface Credentials1 extends Credentials { secret: string; } export interface Credentials2 extends Credentials { refreshToken?: string | undefined; expiresIn?: number | undefined; } export interface CustomProtocol { /** * The name of the protocol. * @default custom */ name?: string | undefined; /** * the authorization endpoint URI. */ auth: string; /** * the access token endpoint URI. */ token: string; /** * a headers object with additional headers required by the provider * (e.g. GitHub required the 'User-Agent' header which is set by default). */ headers?: { [key: string]: string; } | undefined; } /** * a function used to obtain user profile information and normalize it. * @param credentials the credentials object. * Change the object directly within the function (profile information is typically stored under credentials.profile). * @param params the parsed information received from the provider (e.g. token, secret, and other custom fields). * @param get an OAuth helper function to make authenticated requests using the credentials received. */ export type ProfileGetter<C extends Credentials> = ( this: CustomProviderOptions, credentials: C, params: { [key: string]: string }, get: AuthedRequest, ) => Promise<void>; export interface CustomProtocol1 extends CustomProtocol { /** * the authorization protocol used. */ protocol: 'oauth'; /** * the OAuth signature method. Must be one of: * * 'HMAC-SHA1' - default * * 'RSA-SHA1' - in that case, the clientSecret is your RSA private key */ signatureMethod?: 'HMAC-SHA1' | 'RSA-SHA1' | undefined; /** * the temporary credentials (request token) endpoint). */ temporary?: string | undefined; profile: ProfileGetter<Credentials1>; } export type PkceSetting = 'plain' | 'S256'; export interface CustomProtocol2 extends CustomProtocol { /** * the authorization protocol used. */ protocol: 'oauth2'; /** * an array of scope strings. */ scope?: string[] | ((query: StringLikeMap) => string[]) | undefined; /** * boolean that determines if OAuth client id and client secret will be sent * as parameters as opposed to an Authorization header. * Defaults to false. */ useParamsAuth?: boolean | undefined; /** * If specified, uses proof key exchange. */ pkce?: PkceSetting | undefined; /** * the scope separator character. Only required when a provider has a broken OAuth 2.0 implementation. Defaults to space (Facebook and GitHub default to comma). */ scopeSeparator?: string | undefined; profile: ProfileGetter<Credentials2>; } export interface CustomProviderOptions extends RequiredProviderOptions, OptionalOptions { provider: CustomProtocol1 | CustomProtocol2; } export type BellOptions = CustomProviderOptions | KnownProviderOptions; export const plugin: Plugin<BellOptions>; /** * Enables simulation mode. */ export function simulate(credentialsFunc: RequestPassThrough): void; /** * [See docs](https://github.com/hapijs/bell/blob/master/API.md#simulated-authentication) * Disables simulation mode */ export function simulate(state: false): void;