@nestjs/authentication 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +23 -0
- package/README.md +50 -0
- package/dist/account/email-verification.handler.d.ts +23 -0
- package/dist/account/email-verification.handler.js +17 -0
- package/dist/account/email-verification.service.d.ts +46 -0
- package/dist/account/email-verification.service.js +111 -0
- package/dist/account/email.util.d.ts +14 -0
- package/dist/account/email.util.js +28 -0
- package/dist/account/in-memory-email-token.store.d.ts +12 -0
- package/dist/account/in-memory-email-token.store.js +60 -0
- package/dist/account/password-reset.handler.d.ts +19 -0
- package/dist/account/password-reset.handler.js +9 -0
- package/dist/account/password-reset.service.d.ts +69 -0
- package/dist/account/password-reset.service.js +204 -0
- package/dist/authentication.constants.d.ts +13 -0
- package/dist/authentication.constants.js +13 -0
- package/dist/authentication.module-definition.d.ts +21 -0
- package/dist/authentication.module-definition.js +147 -0
- package/dist/authentication.module.d.ts +34 -0
- package/dist/authentication.module.js +139 -0
- package/dist/context/authentication-scope.service.d.ts +39 -0
- package/dist/context/authentication-scope.service.js +64 -0
- package/dist/context/authentication.context.d.ts +28 -0
- package/dist/context/authentication.context.js +58 -0
- package/dist/context/index.d.ts +2 -0
- package/dist/context/index.js +2 -0
- package/dist/decorators/authenticate.decorator.d.ts +10 -0
- package/dist/decorators/authenticate.decorator.js +18 -0
- package/dist/decorators/current-session.decorator.d.ts +2 -0
- package/dist/decorators/current-session.decorator.js +6 -0
- package/dist/decorators/current-user.decorator.d.ts +6 -0
- package/dist/decorators/current-user.decorator.js +11 -0
- package/dist/decorators/index.d.ts +4 -0
- package/dist/decorators/index.js +4 -0
- package/dist/decorators/public.decorator.d.ts +5 -0
- package/dist/decorators/public.decorator.js +6 -0
- package/dist/errors/authentication.error.d.ts +27 -0
- package/dist/errors/authentication.error.js +33 -0
- package/dist/errors/index.d.ts +7 -0
- package/dist/errors/index.js +7 -0
- package/dist/errors/jwt.error.d.ts +9 -0
- package/dist/errors/jwt.error.js +12 -0
- package/dist/errors/magic-link.error.d.ts +18 -0
- package/dist/errors/magic-link.error.js +21 -0
- package/dist/errors/mfa-already-enrolled.error.d.ts +14 -0
- package/dist/errors/mfa-already-enrolled.error.js +17 -0
- package/dist/errors/oidc.error.d.ts +15 -0
- package/dist/errors/oidc.error.js +13 -0
- package/dist/errors/refresh-token.error.d.ts +10 -0
- package/dist/errors/refresh-token.error.js +12 -0
- package/dist/errors/secret-decryption.error.d.ts +3 -0
- package/dist/errors/secret-decryption.error.js +6 -0
- package/dist/events/authentication-events.interface.d.ts +121 -0
- package/dist/events/authentication-events.interface.js +1 -0
- package/dist/events/authentication-events.service.d.ts +19 -0
- package/dist/events/authentication-events.service.js +39 -0
- package/dist/events/authentication.channels.d.ts +4 -0
- package/dist/events/authentication.channels.js +11 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.js +3 -0
- package/dist/guards/authentication.guard.d.ts +57 -0
- package/dist/guards/authentication.guard.js +171 -0
- package/dist/guards/index.d.ts +1 -0
- package/dist/guards/index.js +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.js +52 -0
- package/dist/interceptors/authentication-scope.interceptor.d.ts +20 -0
- package/dist/interceptors/authentication-scope.interceptor.js +48 -0
- package/dist/interceptors/index.d.ts +1 -0
- package/dist/interceptors/index.js +1 -0
- package/dist/interfaces/api-key.interface.d.ts +41 -0
- package/dist/interfaces/api-key.interface.js +1 -0
- package/dist/interfaces/authenticate-options.interface.d.ts +31 -0
- package/dist/interfaces/authenticate-options.interface.js +1 -0
- package/dist/interfaces/authentication-error-options.interface.d.ts +8 -0
- package/dist/interfaces/authentication-error-options.interface.js +1 -0
- package/dist/interfaces/authentication-module-options.interface.d.ts +58 -0
- package/dist/interfaces/authentication-module-options.interface.js +1 -0
- package/dist/interfaces/authentication-registry.interface.d.ts +41 -0
- package/dist/interfaces/authentication-registry.interface.js +1 -0
- package/dist/interfaces/authentication-result.interface.d.ts +25 -0
- package/dist/interfaces/authentication-result.interface.js +1 -0
- package/dist/interfaces/authentication-storage.interface.d.ts +29 -0
- package/dist/interfaces/authentication-storage.interface.js +1 -0
- package/dist/interfaces/duration.interface.d.ts +2 -0
- package/dist/interfaces/duration.interface.js +1 -0
- package/dist/interfaces/email-token-store.interface.d.ts +52 -0
- package/dist/interfaces/email-token-store.interface.js +1 -0
- package/dist/interfaces/email-verification.interface.d.ts +18 -0
- package/dist/interfaces/email-verification.interface.js +1 -0
- package/dist/interfaces/index.d.ts +27 -0
- package/dist/interfaces/index.js +27 -0
- package/dist/interfaces/jwt-options.interface.d.ts +68 -0
- package/dist/interfaces/jwt-options.interface.js +1 -0
- package/dist/interfaces/jwt.interface.d.ts +36 -0
- package/dist/interfaces/jwt.interface.js +1 -0
- package/dist/interfaces/magic-link-store.interface.d.ts +36 -0
- package/dist/interfaces/magic-link-store.interface.js +1 -0
- package/dist/interfaces/magic-link.interface.d.ts +55 -0
- package/dist/interfaces/magic-link.interface.js +1 -0
- package/dist/interfaces/mfa-options.interface.d.ts +44 -0
- package/dist/interfaces/mfa-options.interface.js +1 -0
- package/dist/interfaces/mfa-store.interface.d.ts +70 -0
- package/dist/interfaces/mfa-store.interface.js +1 -0
- package/dist/interfaces/oidc-provider.interface.d.ts +56 -0
- package/dist/interfaces/oidc-provider.interface.js +1 -0
- package/dist/interfaces/oidc-state-store.interface.d.ts +25 -0
- package/dist/interfaces/oidc-state-store.interface.js +1 -0
- package/dist/interfaces/oidc.interface.d.ts +84 -0
- package/dist/interfaces/oidc.interface.js +1 -0
- package/dist/interfaces/password-hasher-options.interface.d.ts +17 -0
- package/dist/interfaces/password-hasher-options.interface.js +1 -0
- package/dist/interfaces/password-reset.interface.d.ts +49 -0
- package/dist/interfaces/password-reset.interface.js +1 -0
- package/dist/interfaces/refresh-token-options.interface.d.ts +10 -0
- package/dist/interfaces/refresh-token-options.interface.js +1 -0
- package/dist/interfaces/refresh-token-store.interface.d.ts +61 -0
- package/dist/interfaces/refresh-token-store.interface.js +1 -0
- package/dist/interfaces/session-store.interface.d.ts +53 -0
- package/dist/interfaces/session-store.interface.js +1 -0
- package/dist/interfaces/session.interface.d.ts +50 -0
- package/dist/interfaces/session.interface.js +1 -0
- package/dist/interfaces/sign-in-options.interface.d.ts +9 -0
- package/dist/interfaces/sign-in-options.interface.js +1 -0
- package/dist/interfaces/token.interface.d.ts +30 -0
- package/dist/interfaces/token.interface.js +1 -0
- package/dist/jwt/amr.util.d.ts +9 -0
- package/dist/jwt/amr.util.js +11 -0
- package/dist/jwt/in-memory-refresh-token.store.d.ts +29 -0
- package/dist/jwt/in-memory-refresh-token.store.js +67 -0
- package/dist/jwt/jwks.client.d.ts +34 -0
- package/dist/jwt/jwks.client.js +154 -0
- package/dist/jwt/jws.util.d.ts +45 -0
- package/dist/jwt/jws.util.js +282 -0
- package/dist/jwt/jwt-bearer.provider.d.ts +48 -0
- package/dist/jwt/jwt-bearer.provider.js +126 -0
- package/dist/jwt/jwt-signer.service.d.ts +19 -0
- package/dist/jwt/jwt-signer.service.js +36 -0
- package/dist/jwt/jwt-verifier.service.d.ts +22 -0
- package/dist/jwt/jwt-verifier.service.js +109 -0
- package/dist/jwt/token.service.d.ts +81 -0
- package/dist/jwt/token.service.js +230 -0
- package/dist/magic-link/in-memory-magic-link.store.d.ts +12 -0
- package/dist/magic-link/in-memory-magic-link.store.js +45 -0
- package/dist/magic-link/magic-link.handler.d.ts +25 -0
- package/dist/magic-link/magic-link.handler.js +14 -0
- package/dist/magic-link/magic-link.service.d.ts +79 -0
- package/dist/magic-link/magic-link.service.js +215 -0
- package/dist/mfa/in-memory-mfa.store.d.ts +25 -0
- package/dist/mfa/in-memory-mfa.store.js +73 -0
- package/dist/mfa/mfa.service.d.ts +104 -0
- package/dist/mfa/mfa.service.js +346 -0
- package/dist/mfa/otp.util.d.ts +7 -0
- package/dist/mfa/otp.util.js +52 -0
- package/dist/mfa/secret-cipher.service.d.ts +28 -0
- package/dist/mfa/secret-cipher.service.js +106 -0
- package/dist/oidc/in-memory-oidc-state.store.d.ts +13 -0
- package/dist/oidc/in-memory-oidc-state.store.js +45 -0
- package/dist/oidc/oidc-account.resolver.d.ts +23 -0
- package/dist/oidc/oidc-account.resolver.js +16 -0
- package/dist/oidc/oidc.client.d.ts +44 -0
- package/dist/oidc/oidc.client.js +286 -0
- package/dist/oidc/oidc.presets.d.ts +24 -0
- package/dist/oidc/oidc.presets.js +53 -0
- package/dist/oidc/oidc.service.d.ts +88 -0
- package/dist/oidc/oidc.service.js +259 -0
- package/dist/providers/api-key.provider.d.ts +51 -0
- package/dist/providers/api-key.provider.js +93 -0
- package/dist/providers/authentication.provider.d.ts +40 -0
- package/dist/providers/authentication.provider.js +33 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +2 -0
- package/dist/services/authentication-registry.service.d.ts +75 -0
- package/dist/services/authentication-registry.service.js +235 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.js +3 -0
- package/dist/services/password-hasher.service.d.ts +47 -0
- package/dist/services/password-hasher.service.js +170 -0
- package/dist/services/ws-authenticator.service.d.ts +38 -0
- package/dist/services/ws-authenticator.service.js +92 -0
- package/dist/session/cookies.util.d.ts +34 -0
- package/dist/session/cookies.util.js +82 -0
- package/dist/session/in-memory-session.store.d.ts +33 -0
- package/dist/session/in-memory-session.store.js +60 -0
- package/dist/session/session-cookie.provider.d.ts +36 -0
- package/dist/session/session-cookie.provider.js +58 -0
- package/dist/session/session.service.d.ts +97 -0
- package/dist/session/session.service.js +208 -0
- package/dist/session/sign-in.service.d.ts +87 -0
- package/dist/session/sign-in.service.js +206 -0
- package/dist/storage/authentication.storage.d.ts +130 -0
- package/dist/storage/authentication.storage.js +350 -0
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.js +1 -0
- package/dist/testing/index.d.ts +39 -0
- package/dist/testing/index.js +531 -0
- package/dist/utils/api-key.util.d.ts +10 -0
- package/dist/utils/api-key.util.js +10 -0
- package/dist/utils/auth-state.util.d.ts +54 -0
- package/dist/utils/auth-state.util.js +209 -0
- package/dist/utils/bearer.util.d.ts +9 -0
- package/dist/utils/bearer.util.js +21 -0
- package/dist/utils/cross-origin.util.d.ts +29 -0
- package/dist/utils/cross-origin.util.js +90 -0
- package/dist/utils/crypto.util.d.ts +19 -0
- package/dist/utils/crypto.util.js +38 -0
- package/dist/utils/duration.util.d.ts +9 -0
- package/dist/utils/duration.util.js +44 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/options.util.d.ts +20 -0
- package/dist/utils/options.util.js +44 -0
- package/dist/utils/transport-errors.util.d.ts +33 -0
- package/dist/utils/transport-errors.util.js +70 -0
- package/package.json +108 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { EmailVerificationHandler } from '../account/email-verification.handler.js';
|
|
2
|
+
import type { PasswordResetHandler } from '../account/password-reset.handler.js';
|
|
3
|
+
import type { MagicLinkHandler } from '../magic-link/magic-link.handler.js';
|
|
4
|
+
import type { OidcAccountResolver } from '../oidc/oidc-account.resolver.js';
|
|
5
|
+
import type { AuthenticationProvider } from '../providers/authentication.provider.js';
|
|
6
|
+
/**
|
|
7
|
+
* The feature handlers, by the name of the module option each one goes
|
|
8
|
+
* with: what `registerHandler()` takes. A feature needs both, its option and
|
|
9
|
+
* its handler, or the module refuses to start.
|
|
10
|
+
*/
|
|
11
|
+
export interface AuthenticationHandlers {
|
|
12
|
+
/** Delivers verification links and records verified addresses. */
|
|
13
|
+
emailVerification: EmailVerificationHandler;
|
|
14
|
+
/** Finds accounts, delivers reset links and stores new passwords. */
|
|
15
|
+
passwordReset: PasswordResetHandler;
|
|
16
|
+
/** Delivers magic links and maps an address to a user. */
|
|
17
|
+
magicLink: MagicLinkHandler;
|
|
18
|
+
/** Maps an OpenID Connect identity to a user. */
|
|
19
|
+
oidc: OidcAccountResolver;
|
|
20
|
+
}
|
|
21
|
+
export type AuthenticationHandlerName = keyof AuthenticationHandlers;
|
|
22
|
+
/** `registerProvider()` options. */
|
|
23
|
+
export interface RegisterProviderOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Where the provider runs in the chain: ascending, the first provider that
|
|
26
|
+
* returns a user wins. Default `0`. Two providers can't share an order.
|
|
27
|
+
*/
|
|
28
|
+
order?: number;
|
|
29
|
+
/** Replace the provider registered at the same `order` (tests, a wrapper around it). */
|
|
30
|
+
replace?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** `registerHandler()` options. */
|
|
33
|
+
export interface RegisterHandlerOptions {
|
|
34
|
+
/** Replace the handler already registered for the feature (tests, a wrapper around it). */
|
|
35
|
+
replace?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* What the guard calls: an `AuthenticationProvider` subclass, or any object
|
|
39
|
+
* with its `authenticate()` (and optional `challenge()`).
|
|
40
|
+
*/
|
|
41
|
+
export type CredentialProvider<TUser = any, TSession = any> = Pick<AuthenticationProvider<TUser, TSession>, 'authenticate' | 'challenge'>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AuthenticationTypes } from '../index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The user type the app declared by augmenting {@link AuthenticationTypes}.
|
|
4
|
+
* Falls back to a string-keyed record when nothing was declared.
|
|
5
|
+
*/
|
|
6
|
+
export type AuthenticatedUser = AuthenticationTypes extends {
|
|
7
|
+
user: infer U;
|
|
8
|
+
} ? U : Record<string, unknown>;
|
|
9
|
+
/** The session type declared on {@link AuthenticationTypes}, `unknown` otherwise. */
|
|
10
|
+
export type AuthenticatedSession = AuthenticationTypes extends {
|
|
11
|
+
session: infer S;
|
|
12
|
+
} ? S : unknown;
|
|
13
|
+
/**
|
|
14
|
+
* `pending`: first factor done, second factor outstanding. Such a result
|
|
15
|
+
* does not count as signed in: `SignInService.completeMfa()` finishes it.
|
|
16
|
+
* `verified`: a second factor was presented. Required by
|
|
17
|
+
* `@Authenticate({ mfa: true })`.
|
|
18
|
+
*/
|
|
19
|
+
export type MfaState = 'pending' | 'verified';
|
|
20
|
+
export interface AuthenticationResult<TUser = AuthenticatedUser, TSession = AuthenticatedSession> {
|
|
21
|
+
user: TUser;
|
|
22
|
+
/** Whatever the provider considers the session: a stored record, JWT claims, an `ApiKeySession`. */
|
|
23
|
+
session?: TSession;
|
|
24
|
+
mfa?: MfaState;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { EmailTokenStore } from './email-token-store.interface.js';
|
|
2
|
+
import type { RefreshTokenStore } from './refresh-token-store.interface.js';
|
|
3
|
+
import type { MagicLinkStore } from './magic-link-store.interface.js';
|
|
4
|
+
import type { MfaStore } from './mfa-store.interface.js';
|
|
5
|
+
import type { OidcStateStore } from './oidc-state-store.interface.js';
|
|
6
|
+
import type { SessionStore } from './session-store.interface.js';
|
|
7
|
+
/**
|
|
8
|
+
* The storage contracts, by name: what `registerSource()` takes. One
|
|
9
|
+
* provider may implement several (`{ sessions: this, refreshTokens: this }`),
|
|
10
|
+
* or several providers split them (sessions in Redis, the rest in SQL).
|
|
11
|
+
*/
|
|
12
|
+
export interface AuthenticationStorageSources {
|
|
13
|
+
sessions?: SessionStore;
|
|
14
|
+
refreshTokens?: RefreshTokenStore;
|
|
15
|
+
/** Authenticators, recovery codes and failed attempts. */
|
|
16
|
+
mfa?: MfaStore;
|
|
17
|
+
/** Pending magic links. */
|
|
18
|
+
magicLinks?: MagicLinkStore;
|
|
19
|
+
/** OAuth / OpenID Connect logins in progress. */
|
|
20
|
+
oidcStates?: OidcStateStore;
|
|
21
|
+
/** Pending password reset and email verification links. */
|
|
22
|
+
emailTokens?: EmailTokenStore;
|
|
23
|
+
}
|
|
24
|
+
export type AuthenticationStorageContract = keyof AuthenticationStorageSources;
|
|
25
|
+
/** `registerSource()` options. */
|
|
26
|
+
export interface AuthenticationStorageRegisterOptions {
|
|
27
|
+
/** Replace the source of a contract that is already registered (tests, a wrapper around it). */
|
|
28
|
+
replace?: boolean;
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** What a mailed token proves when it comes back. */
|
|
2
|
+
export type EmailTokenPurpose = 'password-reset' | 'email-verification';
|
|
3
|
+
/**
|
|
4
|
+
* A token sent by email to prove control of an address: a password reset
|
|
5
|
+
* link, or an email verification link. Stored by the SHA-256 of the token;
|
|
6
|
+
* the token itself only exists in the email.
|
|
7
|
+
*/
|
|
8
|
+
export interface EmailTokenRecord {
|
|
9
|
+
/** SHA-256 of the token. */
|
|
10
|
+
id: string;
|
|
11
|
+
purpose: EmailTokenPurpose;
|
|
12
|
+
userId: string;
|
|
13
|
+
/** The address the token was sent to, and the only one it works for. */
|
|
14
|
+
email: string;
|
|
15
|
+
/**
|
|
16
|
+
* Password resets: SHA-256 of the user's password hash when the link was
|
|
17
|
+
* sent, so a password change (by any route) invalidates the link.
|
|
18
|
+
*/
|
|
19
|
+
fingerprint?: string;
|
|
20
|
+
createdAt: Date;
|
|
21
|
+
expiresAt: Date;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Storage for password reset and email verification tokens. Implement it
|
|
25
|
+
* on your database or Redis, and register the provider with
|
|
26
|
+
* `AuthenticationStorage.registerSource({ emailTokens: this })`.
|
|
27
|
+
*
|
|
28
|
+
* `consumeEmailToken()` must be one atomic get-and-delete
|
|
29
|
+
* (`DELETE … RETURNING`, `GETDEL`), so a link works once however many
|
|
30
|
+
* requests present it. Anyone can ask for a reset link, so the store must
|
|
31
|
+
* stay bounded: drop expired tokens as new ones are saved, and cap the
|
|
32
|
+
* rest. Each method's comment has its rule, and
|
|
33
|
+
* `authenticationStoreContract()` from `@nestjs/authentication/testing`
|
|
34
|
+
* checks them.
|
|
35
|
+
*/
|
|
36
|
+
export interface EmailTokenStore {
|
|
37
|
+
/**
|
|
38
|
+
* Saves a new token (a fresh random id: a plain insert), then keeps the
|
|
39
|
+
* store bounded: deletes tokens whose `expiresAt` is at or before this
|
|
40
|
+
* one's `createdAt`, and past a cap, those that expire first.
|
|
41
|
+
*/
|
|
42
|
+
saveEmailToken(record: EmailTokenRecord): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Removes and returns the token if it exists and was issued for
|
|
45
|
+
* `purpose`, in one atomic step; `undefined` otherwise, leaving a token of
|
|
46
|
+
* another purpose in place. Of several concurrent calls, exactly one gets
|
|
47
|
+
* the record. Expired tokens may be returned: the services check expiry.
|
|
48
|
+
*/
|
|
49
|
+
consumeEmailToken(id: string, purpose: EmailTokenPurpose): Promise<EmailTokenRecord | undefined>;
|
|
50
|
+
/** Deletes the user's outstanding tokens for `purpose` (after a reset, the other reset links). */
|
|
51
|
+
deleteUserEmailTokens(userId: string, purpose: EmailTokenPurpose): Promise<void>;
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Duration } from './duration.interface.js';
|
|
2
|
+
/** What `EmailVerificationHandler.send()` delivers. */
|
|
3
|
+
export interface EmailVerificationLink {
|
|
4
|
+
userId: string;
|
|
5
|
+
/** The address to verify, and to send the link to. */
|
|
6
|
+
email: string;
|
|
7
|
+
/** `emailVerification.url` with `?token=…`. */
|
|
8
|
+
url: string;
|
|
9
|
+
expiresAt: Date;
|
|
10
|
+
}
|
|
11
|
+
export interface EmailVerificationOptions {
|
|
12
|
+
/** Page that receives `?token=…` and POSTs it back, e.g. `https://app.example.com/verify-email`. */
|
|
13
|
+
url: string;
|
|
14
|
+
/** Lifetime of a link. Default `'24h'`. */
|
|
15
|
+
ttl?: Duration;
|
|
16
|
+
/** Clock in epoch milliseconds, for tests. */
|
|
17
|
+
now?: () => number;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export * from './api-key.interface.js';
|
|
2
|
+
export * from './authenticate-options.interface.js';
|
|
3
|
+
export * from './authentication-error-options.interface.js';
|
|
4
|
+
export * from './authentication-module-options.interface.js';
|
|
5
|
+
export * from './authentication-registry.interface.js';
|
|
6
|
+
export * from './authentication-result.interface.js';
|
|
7
|
+
export * from './authentication-storage.interface.js';
|
|
8
|
+
export * from './duration.interface.js';
|
|
9
|
+
export * from './email-token-store.interface.js';
|
|
10
|
+
export * from './email-verification.interface.js';
|
|
11
|
+
export * from './jwt-options.interface.js';
|
|
12
|
+
export * from './jwt.interface.js';
|
|
13
|
+
export * from './magic-link-store.interface.js';
|
|
14
|
+
export * from './magic-link.interface.js';
|
|
15
|
+
export * from './mfa-options.interface.js';
|
|
16
|
+
export * from './mfa-store.interface.js';
|
|
17
|
+
export * from './oidc-provider.interface.js';
|
|
18
|
+
export * from './oidc-state-store.interface.js';
|
|
19
|
+
export * from './oidc.interface.js';
|
|
20
|
+
export * from './password-hasher-options.interface.js';
|
|
21
|
+
export * from './password-reset.interface.js';
|
|
22
|
+
export * from './refresh-token-options.interface.js';
|
|
23
|
+
export * from './refresh-token-store.interface.js';
|
|
24
|
+
export * from './session-store.interface.js';
|
|
25
|
+
export * from './session.interface.js';
|
|
26
|
+
export * from './sign-in-options.interface.js';
|
|
27
|
+
export * from './token.interface.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export * from './api-key.interface.js';
|
|
2
|
+
export * from './authenticate-options.interface.js';
|
|
3
|
+
export * from './authentication-error-options.interface.js';
|
|
4
|
+
export * from './authentication-module-options.interface.js';
|
|
5
|
+
export * from './authentication-registry.interface.js';
|
|
6
|
+
export * from './authentication-result.interface.js';
|
|
7
|
+
export * from './authentication-storage.interface.js';
|
|
8
|
+
export * from './duration.interface.js';
|
|
9
|
+
export * from './email-token-store.interface.js';
|
|
10
|
+
export * from './email-verification.interface.js';
|
|
11
|
+
export * from './jwt-options.interface.js';
|
|
12
|
+
export * from './jwt.interface.js';
|
|
13
|
+
export * from './magic-link-store.interface.js';
|
|
14
|
+
export * from './magic-link.interface.js';
|
|
15
|
+
export * from './mfa-options.interface.js';
|
|
16
|
+
export * from './mfa-store.interface.js';
|
|
17
|
+
export * from './oidc-provider.interface.js';
|
|
18
|
+
export * from './oidc-state-store.interface.js';
|
|
19
|
+
export * from './oidc.interface.js';
|
|
20
|
+
export * from './password-hasher-options.interface.js';
|
|
21
|
+
export * from './password-reset.interface.js';
|
|
22
|
+
export * from './refresh-token-options.interface.js';
|
|
23
|
+
export * from './refresh-token-store.interface.js';
|
|
24
|
+
export * from './session-store.interface.js';
|
|
25
|
+
export * from './session.interface.js';
|
|
26
|
+
export * from './sign-in-options.interface.js';
|
|
27
|
+
export * from './token.interface.js';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { KeyObject } from 'node:crypto';
|
|
2
|
+
import type { JwksClient } from '../jwt/jwks.client.js';
|
|
3
|
+
import type { Duration } from './duration.interface.js';
|
|
4
|
+
import type { ClaimRules, JwsAlgorithm } from './jwt.interface.js';
|
|
5
|
+
export interface JwksClientOptions {
|
|
6
|
+
/** How long a fetched key set is trusted. Default `'10m'`. */
|
|
7
|
+
cacheTtl?: Duration;
|
|
8
|
+
/**
|
|
9
|
+
* Minimum gap between refetches triggered by an unknown `kid`. Default
|
|
10
|
+
* `'30s'`. Stops a flood of tokens with random `kid`s from turning into a
|
|
11
|
+
* flood of requests to the IdP.
|
|
12
|
+
*/
|
|
13
|
+
cooldown?: Duration;
|
|
14
|
+
/** Request timeout. Default `'5s'`. */
|
|
15
|
+
timeout?: Duration;
|
|
16
|
+
fetch?: typeof fetch;
|
|
17
|
+
/** Clock in epoch milliseconds, for tests. */
|
|
18
|
+
now?: () => number;
|
|
19
|
+
}
|
|
20
|
+
export interface JwtVerifierOptions extends ClaimRules {
|
|
21
|
+
/**
|
|
22
|
+
* A static key: an HS256 secret (at least 32 bytes), or a public or
|
|
23
|
+
* private key as a `KeyObject` or PEM text (a string or a `Buffer`). A
|
|
24
|
+
* public key needs `issuer` and `audience`, as a `jwks` does: it is an
|
|
25
|
+
* identity provider's, which signs the tokens of all its clients with it.
|
|
26
|
+
* A JWK, or DER, is refused (read as bytes, it would be an HS256 secret):
|
|
27
|
+
* pass `createPublicKey({ key: jwk, format: 'jwk' })`.
|
|
28
|
+
*/
|
|
29
|
+
key?: KeyObject | string | Buffer;
|
|
30
|
+
/**
|
|
31
|
+
* A JWKS URL, or a shared {@link JwksClient}. Needs `issuer` and
|
|
32
|
+
* `audience`: an identity provider's keys sign the tokens of every one of
|
|
33
|
+
* its clients.
|
|
34
|
+
*/
|
|
35
|
+
jwks?: string | JwksClient;
|
|
36
|
+
/**
|
|
37
|
+
* Accepted `alg` values. Defaults: `['HS256']` for a secret, the key's own
|
|
38
|
+
* algorithm for an asymmetric key, `['RS256', 'ES256']` for a JWKS.
|
|
39
|
+
* `none` is never accepted.
|
|
40
|
+
*/
|
|
41
|
+
algorithms?: JwsAlgorithm[];
|
|
42
|
+
/** Required `typ` header, e.g. `at+jwt` (RFC 9068). Not checked by default. */
|
|
43
|
+
type?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface JwtSignerOptions {
|
|
46
|
+
/**
|
|
47
|
+
* An HS256 secret (at least 32 bytes), or a private key for RS256, ES256
|
|
48
|
+
* or EdDSA: a `KeyObject`, or PEM text (a string or a `Buffer`). A JWK, or
|
|
49
|
+
* DER, is refused: pass `createPrivateKey({ key: jwk, format: 'jwk' })`.
|
|
50
|
+
*/
|
|
51
|
+
key: KeyObject | string | Buffer;
|
|
52
|
+
/** Default: HS256 for a secret, the key's own algorithm for a private key. */
|
|
53
|
+
alg?: JwsAlgorithm;
|
|
54
|
+
/** Published in the header so verifiers can pick the key from a JWKS. */
|
|
55
|
+
kid?: string;
|
|
56
|
+
issuer?: string;
|
|
57
|
+
audience?: string | string[];
|
|
58
|
+
/** Lifetime of a token. Default `'15m'`: access tokens should be short-lived. */
|
|
59
|
+
ttl?: Duration;
|
|
60
|
+
/** `typ` header. Default `JWT`; RFC 9068 access tokens use `at+jwt`. */
|
|
61
|
+
type?: string;
|
|
62
|
+
/** Clock in epoch milliseconds, for tests. */
|
|
63
|
+
now?: () => number;
|
|
64
|
+
}
|
|
65
|
+
export interface JwtBearerProviderOptions extends JwtVerifierOptions {
|
|
66
|
+
/** `realm` in the `WWW-Authenticate` challenge. Default `api`. */
|
|
67
|
+
realm?: string;
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Duration } from './duration.interface.js';
|
|
2
|
+
/**
|
|
3
|
+
* Supported JWS algorithms. EdDSA means Ed25519 only: Ed448 is rejected
|
|
4
|
+
* (untested here, and rare in practice).
|
|
5
|
+
*/
|
|
6
|
+
export type JwsAlgorithm = 'HS256' | 'RS256' | 'ES256' | 'EdDSA';
|
|
7
|
+
export interface JwtClaims {
|
|
8
|
+
iss?: string;
|
|
9
|
+
sub?: string;
|
|
10
|
+
aud?: string | string[];
|
|
11
|
+
exp?: number;
|
|
12
|
+
nbf?: number;
|
|
13
|
+
iat?: number;
|
|
14
|
+
jti?: string;
|
|
15
|
+
[claim: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
export interface ClaimRules {
|
|
18
|
+
issuer?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Accepted `aud` values. `false` accepts any audience, for tokens that
|
|
21
|
+
* carry none (check the claim that names your client in `validate()`).
|
|
22
|
+
*/
|
|
23
|
+
audience?: string | string[] | false;
|
|
24
|
+
/**
|
|
25
|
+
* Leeway for `exp`, `nbf` and `iat`. Default `0`, right for the app's own
|
|
26
|
+
* tokens. Set it (`'30s'`) for another issuer's: a clock a second ahead
|
|
27
|
+
* would otherwise issue tokens "in the future".
|
|
28
|
+
*/
|
|
29
|
+
clockTolerance?: Duration;
|
|
30
|
+
/** Reject tokens issued longer ago than this (needs `iat`). */
|
|
31
|
+
maxAge?: Duration;
|
|
32
|
+
/** Claims that must be present. `exp` is required by default. */
|
|
33
|
+
required?: string[];
|
|
34
|
+
/** Clock in epoch milliseconds, for tests. */
|
|
35
|
+
now?: () => number;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface MagicLinkRecord {
|
|
2
|
+
/**
|
|
3
|
+
* SHA-256 of the token, and of the secret that binds the link to the
|
|
4
|
+
* browser that requested it (`magicLink.bindToBrowser`): the link alone
|
|
5
|
+
* does not find it.
|
|
6
|
+
*/
|
|
7
|
+
id: string;
|
|
8
|
+
email: string;
|
|
9
|
+
createdAt: Date;
|
|
10
|
+
expiresAt: Date;
|
|
11
|
+
redirectTo?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Storage for pending magic links. Implement it on your database or Redis,
|
|
15
|
+
* and register the provider with
|
|
16
|
+
* `AuthenticationStorage.registerSource({ magicLinks: this })`.
|
|
17
|
+
*
|
|
18
|
+
* `consumeMagicLink()` must be one atomic get-and-delete
|
|
19
|
+
* (`DELETE … RETURNING`, `GETDEL`), so a link works once however many
|
|
20
|
+
* requests present it. Anyone can request links, so the store must stay
|
|
21
|
+
* bounded: drop expired links as new ones are saved, and cap the rest.
|
|
22
|
+
*/
|
|
23
|
+
export interface MagicLinkStore {
|
|
24
|
+
/**
|
|
25
|
+
* Saves a new link (a fresh random id: a plain insert), then keeps the
|
|
26
|
+
* store bounded: deletes links whose `expiresAt` is at or before this
|
|
27
|
+
* one's `createdAt`, and past a cap, those that expire first.
|
|
28
|
+
*/
|
|
29
|
+
saveMagicLink(record: MagicLinkRecord): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Removes and returns the link, in one atomic step; `undefined` if there
|
|
32
|
+
* is none. Of several concurrent calls, exactly one gets the record.
|
|
33
|
+
* Expired links may be returned: `MagicLinkService` checks expiry.
|
|
34
|
+
*/
|
|
35
|
+
consumeMagicLink(id: string): Promise<MagicLinkRecord | undefined>;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { CookieAttributes } from '../session/cookies.util.js';
|
|
2
|
+
import type { Duration } from './duration.interface.js';
|
|
3
|
+
export interface MagicLink {
|
|
4
|
+
email: string;
|
|
5
|
+
url: string;
|
|
6
|
+
expiresAt: Date;
|
|
7
|
+
}
|
|
8
|
+
/** The account behind an address, as `MagicLinkHandler.resolveUser()` returns it. */
|
|
9
|
+
export interface MagicLinkAccount {
|
|
10
|
+
id: string;
|
|
11
|
+
/**
|
|
12
|
+
* The address the account has stored. The link signs the account in only
|
|
13
|
+
* when it is the link's address (compared trimmed and lowercased).
|
|
14
|
+
*/
|
|
15
|
+
email: string;
|
|
16
|
+
}
|
|
17
|
+
export interface MagicLinkOptions {
|
|
18
|
+
/** Page that receives `?token=…`, e.g. `https://app.example.com/auth/magic`. */
|
|
19
|
+
url: string;
|
|
20
|
+
/** Lifetime of a link. Default `'15m'`. */
|
|
21
|
+
ttl?: Duration;
|
|
22
|
+
/**
|
|
23
|
+
* Whether a link works only in the browser that requested it. Default
|
|
24
|
+
* `true`: `create()` sets a transaction cookie, and `consume()` refuses a
|
|
25
|
+
* link the browser holds no cookie for (`magic-link-refused`,
|
|
26
|
+
* `not-this-browser`). Without it, anyone can request a link for their
|
|
27
|
+
* own address and get someone else to open it, which signs that person's
|
|
28
|
+
* browser in to the attacker's account (login CSRF). `false` trades that
|
|
29
|
+
* for links that work on another device than the one that asked for them
|
|
30
|
+
* (requested on the laptop, opened on the phone).
|
|
31
|
+
*/
|
|
32
|
+
bindToBrowser?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Attributes of the transaction cookie, `__Host-magic_link_tx` (or
|
|
35
|
+
* `magic_link_tx` when they rule the prefix out). `secure` defaults to
|
|
36
|
+
* `true`; `SameSite` is always `Lax`, which lets the cookie through the
|
|
37
|
+
* top-level navigation from the mail client to the page.
|
|
38
|
+
*/
|
|
39
|
+
cookie?: CookieAttributes;
|
|
40
|
+
/** Clock in epoch milliseconds, for tests. */
|
|
41
|
+
now?: () => number;
|
|
42
|
+
}
|
|
43
|
+
/** The HTTP request that presents a link, as Express and Fastify provide it. */
|
|
44
|
+
export type MagicLinkRequest = {
|
|
45
|
+
headers: Record<string, string | string[] | undefined>;
|
|
46
|
+
};
|
|
47
|
+
export interface CreatedMagicLink {
|
|
48
|
+
expiresAt: Date;
|
|
49
|
+
/**
|
|
50
|
+
* The `Set-Cookie` value of the transaction cookie, already set on the HTTP
|
|
51
|
+
* response when called from a handler; send it yourself elsewhere. Absent
|
|
52
|
+
* with `bindToBrowser: false`.
|
|
53
|
+
*/
|
|
54
|
+
cookie?: string;
|
|
55
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Duration } from './duration.interface.js';
|
|
2
|
+
export interface MfaOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Encryption of TOTP secrets at rest (AES-256-GCM): `{ keys: [key] }`,
|
|
5
|
+
* newest key first. Required once `mfa` is configured: pass `false` to
|
|
6
|
+
* store plaintext deliberately (tests, throwaway in-memory setups).
|
|
7
|
+
*/
|
|
8
|
+
encryption: SecretEncryptionOptions | false;
|
|
9
|
+
/** Shown in authenticator apps. */
|
|
10
|
+
issuer?: string;
|
|
11
|
+
/** Accepted 30-second steps either side of now: an integer from 0 to 10. Default 1, per RFC 6238 §5.2. */
|
|
12
|
+
window?: number;
|
|
13
|
+
/** Failed codes allowed per `lockoutWindow` before every code is refused: an integer of at least 1. Default 5. */
|
|
14
|
+
maxAttempts?: number;
|
|
15
|
+
/** Default `'15m'`. */
|
|
16
|
+
lockoutWindow?: Duration;
|
|
17
|
+
/** Recovery codes per batch: an integer of at least 1. Default 10. */
|
|
18
|
+
recoveryCodes?: number;
|
|
19
|
+
/**
|
|
20
|
+
* How long a session that passed its first factor may wait for the second
|
|
21
|
+
* (`mfa: 'pending'`) before it expires. Default `'10m'`, never more than
|
|
22
|
+
* `session.absoluteTtl`. A pending cookie is half a credential: this keeps a
|
|
23
|
+
* stolen one from staying useful for the session's full lifetime.
|
|
24
|
+
*/
|
|
25
|
+
pendingTtl?: Duration;
|
|
26
|
+
/** Clock in epoch milliseconds, for tests. */
|
|
27
|
+
now?: () => number;
|
|
28
|
+
}
|
|
29
|
+
export interface SecretEncryptionOptions {
|
|
30
|
+
/**
|
|
31
|
+
* AES-256-GCM keys: 32-byte `Buffer`s, or strings of at least 32
|
|
32
|
+
* characters (random secrets, expanded with HKDF-SHA256; not passwords).
|
|
33
|
+
* The first key encrypts, and every key decrypts. Prepend a new key to
|
|
34
|
+
* rotate.
|
|
35
|
+
*/
|
|
36
|
+
keys: (string | Buffer)[];
|
|
37
|
+
/**
|
|
38
|
+
* Accept stored values that are not ciphertext (secrets saved before
|
|
39
|
+
* encryption was turned on) and re-encrypt them on the next successful
|
|
40
|
+
* verification. Off by default: with encryption on, a plaintext value in
|
|
41
|
+
* the store is otherwise indistinguishable from one an attacker planted.
|
|
42
|
+
*/
|
|
43
|
+
migratePlaintext?: boolean;
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export interface TotpRecord {
|
|
2
|
+
/** Sealed secret (`v1.<keyId>.…`, see `SecretCipher`); base32 plaintext only with `encryption: false`. */
|
|
3
|
+
secret: string;
|
|
4
|
+
/** `false` until the user proved the authenticator works. */
|
|
5
|
+
confirmed: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* A replacement secret (sealed like `secret`) staged by
|
|
8
|
+
* `enroll(…, { replace: true })`. `secret` stays active until `confirm()`
|
|
9
|
+
* proves the new authenticator works.
|
|
10
|
+
*/
|
|
11
|
+
pendingSecret?: string;
|
|
12
|
+
/** Last accepted time step, for replay protection. */
|
|
13
|
+
lastUsedStep?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Second-factor storage: each user's authenticator, recovery code hashes,
|
|
17
|
+
* and failed attempts. Implement it on your database or Redis, and register
|
|
18
|
+
* the provider with `AuthenticationStorage.registerSource({ mfa: this })`.
|
|
19
|
+
*
|
|
20
|
+
* Four methods are what stop a code from being accepted twice, or a burst
|
|
21
|
+
* of guesses from outrunning the lockout, and must be single atomic writes
|
|
22
|
+
* (a conditional update or delete, an upsert, a Lua script), never a read
|
|
23
|
+
* followed by a write: `saveTotp()`, `claimTotpStep()`,
|
|
24
|
+
* `consumeRecoveryCode()` and `recordMfaFailure()`. Each one's comment has
|
|
25
|
+
* the race it prevents, and `authenticationStoreContract()` from
|
|
26
|
+
* `@nestjs/authentication/testing` checks them (`concurrent: true`).
|
|
27
|
+
*
|
|
28
|
+
* Times (`now`) are epoch milliseconds from `MfaService`'s clock, never the
|
|
29
|
+
* store's. Optional fields come back absent (`undefined`), never `null`.
|
|
30
|
+
*/
|
|
31
|
+
export interface MfaStore {
|
|
32
|
+
getTotp(userId: string): Promise<TotpRecord | undefined>;
|
|
33
|
+
/**
|
|
34
|
+
* Saves the user's authenticator (an upsert), or deletes it (`null`).
|
|
35
|
+
* Never lowers the stored `lastUsedStep`: keep the larger of the stored
|
|
36
|
+
* one and the record's (`GREATEST()` in the upsert). A record read before
|
|
37
|
+
* a concurrent `claimTotpStep()` must not reopen the step it claimed.
|
|
38
|
+
*/
|
|
39
|
+
saveTotp(userId: string, record: TotpRecord | null): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Sets `lastUsedStep = step` iff the user has an authenticator and `step`
|
|
42
|
+
* is greater than the stored one (or none is stored), in one conditional
|
|
43
|
+
* write; `true` if it did. Of several concurrent calls with the same step,
|
|
44
|
+
* exactly one gets `true`: a TOTP code works once.
|
|
45
|
+
*/
|
|
46
|
+
claimTotpStep(userId: string, step: number): Promise<boolean>;
|
|
47
|
+
/** Replaces the user's recovery code hashes with `hashes` (`[]` deletes them). */
|
|
48
|
+
saveRecoveryCodes(userId: string, hashes: string[]): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Removes one recovery code hash of this user, in one conditional delete;
|
|
51
|
+
* `true` if this call removed it. Of several concurrent calls, exactly one
|
|
52
|
+
* gets `true`.
|
|
53
|
+
*/
|
|
54
|
+
consumeRecoveryCode(userId: string, hash: string): Promise<boolean>;
|
|
55
|
+
countRecoveryCodes(userId: string): Promise<number>;
|
|
56
|
+
/**
|
|
57
|
+
* Records a failed attempt at `now`, then returns the failures within
|
|
58
|
+
* `windowMs` before `now` (`at > now - windowMs`), this one included.
|
|
59
|
+
* Record first, count second, each visible to other callers as soon as it
|
|
60
|
+
* returns: parallel calls each count every attempt recorded before them,
|
|
61
|
+
* so no more than `n` of them see a count of `n` or less. `MfaService`
|
|
62
|
+
* calls it *before* checking a code, which is what stops a burst of
|
|
63
|
+
* parallel guesses.
|
|
64
|
+
*/
|
|
65
|
+
recordMfaFailure(userId: string, windowMs: number, now: number): Promise<number>;
|
|
66
|
+
/** The failures within `windowMs` before `now`, without recording one. */
|
|
67
|
+
countMfaFailures(userId: string, windowMs: number, now: number): Promise<number>;
|
|
68
|
+
/** Forgets the user's failures (after a code verified). */
|
|
69
|
+
clearMfaFailures(userId: string): Promise<void>;
|
|
70
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { JwsAlgorithm } from './jwt.interface.js';
|
|
2
|
+
export interface OidcProfile {
|
|
3
|
+
/** Config key of the provider (`google`, `github`, …). */
|
|
4
|
+
provider: string;
|
|
5
|
+
/** Stable account id at the provider. Link accounts by (provider, subject), never by email. */
|
|
6
|
+
subject: string;
|
|
7
|
+
email?: string;
|
|
8
|
+
/** Only `true` when the provider asserted it. Unverified emails must not link accounts. */
|
|
9
|
+
emailVerified: boolean;
|
|
10
|
+
name?: string;
|
|
11
|
+
picture?: string;
|
|
12
|
+
/** Verified ID token claims merged with userinfo (OIDC), or the raw userinfo (OAuth 2.0). */
|
|
13
|
+
claims: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface OAuthTokens {
|
|
16
|
+
accessToken: string;
|
|
17
|
+
refreshToken?: string;
|
|
18
|
+
idToken?: string;
|
|
19
|
+
expiresIn?: number;
|
|
20
|
+
scope?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ProfileContext {
|
|
23
|
+
provider: string;
|
|
24
|
+
tokens: OAuthTokens;
|
|
25
|
+
/** GET with the access token, JSON response. For extra API calls. */
|
|
26
|
+
fetchJson(url: string): Promise<any>;
|
|
27
|
+
}
|
|
28
|
+
export interface OidcProviderConfig {
|
|
29
|
+
/** `oidc` (default): discovery + ID token. `oauth2`: plain OAuth 2.0 (GitHub), profile from an API. */
|
|
30
|
+
kind?: 'oidc' | 'oauth2';
|
|
31
|
+
/** OIDC issuer; discovery is `${issuer}/.well-known/openid-configuration`. */
|
|
32
|
+
issuer?: string;
|
|
33
|
+
clientId: string;
|
|
34
|
+
clientSecret?: string;
|
|
35
|
+
/** Default `openid email profile` for OIDC. */
|
|
36
|
+
scopes?: string[];
|
|
37
|
+
/** Override or (for `oauth2`) supply endpoints. */
|
|
38
|
+
authorizationEndpoint?: string;
|
|
39
|
+
tokenEndpoint?: string;
|
|
40
|
+
userinfoEndpoint?: string;
|
|
41
|
+
jwksUri?: string;
|
|
42
|
+
/** Accepted ID token algorithms. Default `RS256`, `ES256`. */
|
|
43
|
+
idTokenAlgorithms?: JwsAlgorithm[];
|
|
44
|
+
/** Default `client_secret_basic` with a secret, `none` without (public client + PKCE). */
|
|
45
|
+
tokenEndpointAuthMethod?: 'client_secret_basic' | 'client_secret_post' | 'none';
|
|
46
|
+
/**
|
|
47
|
+
* Extra authorization request parameters (`prompt`, `hd`, `login_hint`,
|
|
48
|
+
* …). They travel through the browser, which can change or drop them:
|
|
49
|
+
* hints to the provider, never checks. Check what they ask for in the
|
|
50
|
+
* resolver, on the verified claims (`profile.claims.hd`, `acr`,
|
|
51
|
+
* `auth_time`).
|
|
52
|
+
*/
|
|
53
|
+
authorizationParams?: Record<string, string>;
|
|
54
|
+
/** `oauth2` only: builds the profile from the userinfo response. */
|
|
55
|
+
profile?(userinfo: any, context: ProfileContext): OidcProfile | Promise<OidcProfile>;
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|