UNPKG

@perfood/couch-auth

Version:

Easy and secure authentication for CouchDB/Cloudant. Based on SuperLogin, updated and rewritten in Typescript.

191 lines (190 loc) 6.51 kB
import { Request } from 'express'; import { Document, IdentifiedDocument, MaybeRevisionedDocument } from 'nano'; export interface IdentifiedObj { name: string; type: string; } export type SessionCleanupType = 'all' | 'expired' | 'other'; export type CreateSessionOpts = { /** the email, username or UUID (depending on your config) */ login: string; /** 'local' or one of the configured OAuth providers */ provider: string; /** if `true`, interpret `login` always as UUID */ byUUID?: boolean; /** * see `security` -> `sessionConfig`. Custom session lifetime depending on the * user's roles and the config entry for this session type. */ sessionType?: string; }; /** copied from https://nodemailer.com/smtp/pooled/ because it's not included in the typings */ export interface PooledSMTPOptions { /** set to true to use pooled connections (defaults to false) instead of creating a new connection for every email */ pool?: boolean; /** is the count of maximum simultaneous connections to make against the SMTP server (defaults to 5) */ maxConnections?: number; /** limits the message count to be sent using a single connection (defaults to 100). After maxMessages is reached the connection is dropped and a new one is created for the following messages */ maxMessages?: number; } export interface CouchDbAuthDoc extends IdentifiedDocument, MaybeRevisionedDocument, IdentifiedObj { user_uid: string; user_id: string; password?: string; expires: number; roles: string[]; provider: string; password_scheme?: string; iterations?: number; derived_key?: string; salt?: string; } export interface HashResult { salt?: string; derived_key?: string; /** * timestamp of the creation of this HashResult. If `undefined`, the default * iteration number (10) is used, else the value specified in the config * (`security.iterations`) that matches the creation date. */ created?: number; } export interface LocalHashObj extends HashResult { failedLoginAttempts?: number; iterations?: number; lockedUntil?: number; } export interface SignUpObj { provider: string; timestamp: string; } export interface RegistrationForm { email: string; username?: string; password: string; confirmPassword: string; name?: string; [x: string]: any; } export interface PersonalDBCollection { [dbName: string]: IdentifiedObj; } export interface TimeRestricted { issued: number; expires: number; } export interface SessionObj extends TimeRestricted { provider: string; sessionType?: string; } export interface SessionCollection { [session: string]: SessionObj; } /** actions performed by the user and logged via `activityLog` */ export type UserAction = 'email-verified' | 'signup' | 'create-social' | 'link-social' | 'login' | 'password-reset' | 'password-change' | 'forgot-password' | 'email-changed' | 'logout' | 'logout-others' | 'logout-all' | 'refresh' | 'consents'; /** possible events that are emmitted */ export type UserEvent = UserAction | 'signup-attempt' | 'forgot-password-attempt' | 'forgot-username-attempt' | 'email-change-attempt' | 'user-db-added' | 'user-deleted' | 'confirmation-email-error'; export interface UserActivity { timestamp: string; action: UserAction; /** * Depending on the action, this is either the OAuth-provider, `'local'` or * the current session-ID */ provider: string; } export interface PasswortResetEntry extends TimeRestricted { token: string; } export interface SlUserDoc extends Document, IdentifiedObj { user_uid?: string; /** this is the `_id` in version 1 of superlogin - for login with username */ key: string; roles: string[]; providers: string[]; local: LocalHashObj; activity?: UserActivity[]; forgotPassword?: PasswortResetEntry; unverifiedEmail?: { email: string; token: string; }; /** * After an `unverifiedEmail` was confirmed, the used token is documented * until a new email change token is requested. */ lastEmailToken?: string; signUp: SignUpObj; personalDBs: PersonalDBCollection; email: string; session: SessionCollection; /** from Version 0.17.0 onwards, expired session keys are reused */ inactiveSessions: string[]; profile: any; consents?: Record<string, ConsentSlEntry[]>; } export interface ConsentConfig { minVersion: number; currentVersion: number; required: boolean; } export interface ConsentRequest { accepted: boolean; version: number; } export interface ConsentSlEntry extends ConsentRequest { timestamp: string; } export interface SlUserNew extends SlUserDoc { password?: string; confirmPassword?: string; } export interface SlRefreshSession extends TimeRestricted { provider: string; roles: string[]; token: string; /** This will still be the old `_id`, i.e. `key` now */ user_id: string; /** unique identifier of the user's DB, `including` the hyphens. */ user_uid: string; /** * If `config.security.sessionConfig` is used, this stores the type of session * that was issued when logging in. Necessary to select the correct lifetime * when extending the session. */ sessionType?: string; } export interface SlLoginSession extends SlRefreshSession { password: string; userDBs: { [db: string]: string; }; profile?: string; /** Name for Display purposes only */ name?: string; } export interface SlRequestUser { /** `"local"` or the OAuth provider */ provider?: string; /** UUID (without hyphens) of the user */ _id?: string; /** * In this context, this is the current _session_ of the user, not the `key` * in the SlUserDoc! */ key?: string; roles?: string[]; /** @deprecated Also the UUID (without hyphens) - does this make any sense? */ user_id?: string; /** If set up via `local.consents` in the config, the consents need to passed for registration. */ consents?: Record<string, ConsentRequest>; /** * If set up via `security.sessionConfig`, a custom session type can be * requested during `login`, `register`, and `password-reset`. */ sessionType?: string; } export interface SlRequest extends Request { user: SlRequestUser; } export type SlAction = (a: SlUserDoc, b: string) => Promise<SlUserDoc>;