@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,39 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Injectable } from '@nestjs/common';
|
|
8
|
+
import { Subject } from 'rxjs';
|
|
9
|
+
import { channelFor } from './authentication.channels.js';
|
|
10
|
+
/**
|
|
11
|
+
* The audit trail of sign-ins, sign-outs, second-factor changes, password
|
|
12
|
+
* resets, email verifications and refused magic links. Each event is also
|
|
13
|
+
* published on its `node:diagnostics_channel` channel
|
|
14
|
+
* (`nestjs:authentication:<type>`), for tooling that runs outside Nest.
|
|
15
|
+
* Listeners cannot change the outcome: a throwing channel subscriber is
|
|
16
|
+
* reported on the next tick, not in the sign-in that emitted.
|
|
17
|
+
*/
|
|
18
|
+
let AuthenticationEvents = class AuthenticationEvents {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.subject = new Subject();
|
|
21
|
+
/** Every event of this application, in order. */
|
|
22
|
+
this.events$ = this.subject.asObservable();
|
|
23
|
+
}
|
|
24
|
+
/** @internal Called by the module's services. */
|
|
25
|
+
emit(event) {
|
|
26
|
+
const target = channelFor(event.type);
|
|
27
|
+
if (target.hasSubscribers) {
|
|
28
|
+
target.publish(event);
|
|
29
|
+
}
|
|
30
|
+
this.subject.next(event);
|
|
31
|
+
}
|
|
32
|
+
onApplicationShutdown() {
|
|
33
|
+
this.subject.complete();
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
AuthenticationEvents = __decorate([
|
|
37
|
+
Injectable()
|
|
38
|
+
], AuthenticationEvents);
|
|
39
|
+
export { AuthenticationEvents };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Channel } from 'node:diagnostics_channel';
|
|
2
|
+
import type { AuthenticationEvent } from './authentication-events.interface.js';
|
|
3
|
+
/** `nestjs:authentication:<type>`, one `node:diagnostics_channel` channel per event. */
|
|
4
|
+
export declare function channelFor(type: AuthenticationEvent['type']): Channel;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { channel } from 'node:diagnostics_channel';
|
|
2
|
+
const channels = new Map();
|
|
3
|
+
/** `nestjs:authentication:<type>`, one `node:diagnostics_channel` channel per event. */
|
|
4
|
+
export function channelFor(type) {
|
|
5
|
+
let found = channels.get(type);
|
|
6
|
+
if (!found) {
|
|
7
|
+
found = channel(`nestjs:authentication:${type}`);
|
|
8
|
+
channels.set(type, found);
|
|
9
|
+
}
|
|
10
|
+
return found;
|
|
11
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type CanActivate, type ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import { HttpAdapterHost, Reflector } from '@nestjs/core';
|
|
3
|
+
import { AuthenticationRegistry } from '../services/authentication-registry.service.js';
|
|
4
|
+
import { AUTHENTICATION_GUARD_BRAND } from '../authentication.constants.js';
|
|
5
|
+
/**
|
|
6
|
+
* Runs the registered providers in order and records the first result on
|
|
7
|
+
* the call.
|
|
8
|
+
*
|
|
9
|
+
* | Route | No credentials | Valid | Invalid |
|
|
10
|
+
* | --- | --- | --- | --- |
|
|
11
|
+
* | default | 401 | pass | 401 |
|
|
12
|
+
* | `@Authenticate({ optional: true })` | pass, user `null` | pass | 401 |
|
|
13
|
+
* | `@Public()` | providers not called | not called | not called |
|
|
14
|
+
*
|
|
15
|
+
* A result with `mfa: 'pending'` (second factor outstanding) does not count
|
|
16
|
+
* as signed in: 401 `mfa_required` where a user is required, anonymous on
|
|
17
|
+
* optional routes. `@Authenticate({ mfa: true })` needs `mfa: 'verified'`,
|
|
18
|
+
* and `@Authenticate({ verifiedEmail: true })` a verified address (403).
|
|
19
|
+
*
|
|
20
|
+
* Providers run once per call: the raw result is cached on the request, the
|
|
21
|
+
* GraphQL operation's context, or per ws message. With
|
|
22
|
+
* `@Authenticate({ providers })`, a cached result from another provider is
|
|
23
|
+
* ignored.
|
|
24
|
+
*
|
|
25
|
+
* Where Nest runs no global guard, neither does this one: on GraphQL field
|
|
26
|
+
* resolvers (`@ResolveField`), unless the GraphQL module sets
|
|
27
|
+
* `fieldResolverEnhancers: ['guards']`, and on the message handlers of a
|
|
28
|
+
* hybrid app, unless it connects them with
|
|
29
|
+
* `app.connectMicroservice(options, { inheritAppConfig: true })`. There,
|
|
30
|
+
* route options are not enforced.
|
|
31
|
+
*/
|
|
32
|
+
export declare class AuthenticationGuard implements CanActivate {
|
|
33
|
+
private readonly reflector;
|
|
34
|
+
private readonly adapterHost;
|
|
35
|
+
private readonly registry;
|
|
36
|
+
/**
|
|
37
|
+
* How `@nestjs/authorization` recognizes this guard, subclasses included,
|
|
38
|
+
* whatever their names: it fails at startup when this guard would run
|
|
39
|
+
* after its own.
|
|
40
|
+
*/
|
|
41
|
+
static readonly [AUTHENTICATION_GUARD_BRAND] = true;
|
|
42
|
+
constructor(reflector: Reflector, adapterHost: HttpAdapterHost, registry: AuthenticationRegistry);
|
|
43
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
44
|
+
/** Class options with the method's merged over them, field by field. */
|
|
45
|
+
private route;
|
|
46
|
+
private authenticate;
|
|
47
|
+
/**
|
|
48
|
+
* A ws socket keeps its last user (`client.user`) for code that reads it on
|
|
49
|
+
* messages that run no provider (`@Public()`): a message refused for its
|
|
50
|
+
* credentials says the connection has none now, its session revoked or its
|
|
51
|
+
* token expired. `@nestjs/authorization` asks for each message's own user
|
|
52
|
+
* instead (`userOf` in auth-state.util.ts).
|
|
53
|
+
*/
|
|
54
|
+
private forgetConnection;
|
|
55
|
+
private challenges;
|
|
56
|
+
private fail;
|
|
57
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var _a;
|
|
11
|
+
import { Injectable } from '@nestjs/common';
|
|
12
|
+
import { HttpAdapterHost, Reflector } from '@nestjs/core';
|
|
13
|
+
import { hasVerifiedEmail } from '../account/email.util.js';
|
|
14
|
+
import { getRawResult, setAuthState, setRawResult } from '../utils/auth-state.util.js';
|
|
15
|
+
import { AuthenticationRegistry } from '../services/authentication-registry.service.js';
|
|
16
|
+
import { AUTHENTICATION_GUARD_BRAND, AUTHENTICATION_METADATA } from '../authentication.constants.js';
|
|
17
|
+
import { AuthenticationError } from '../errors/authentication.error.js';
|
|
18
|
+
import { refusal } from '../utils/transport-errors.util.js';
|
|
19
|
+
/** Which provider produced a result, for `@Authenticate({ providers })` on a cached result. */
|
|
20
|
+
const producedBy = new WeakMap();
|
|
21
|
+
const MFA_REQUIRED = { message: 'Second factor required', code: 'mfa_required' };
|
|
22
|
+
const EMAIL_UNVERIFIED = { status: 403, message: 'Email address not verified', code: 'email_unverified' };
|
|
23
|
+
/**
|
|
24
|
+
* Runs the registered providers in order and records the first result on
|
|
25
|
+
* the call.
|
|
26
|
+
*
|
|
27
|
+
* | Route | No credentials | Valid | Invalid |
|
|
28
|
+
* | --- | --- | --- | --- |
|
|
29
|
+
* | default | 401 | pass | 401 |
|
|
30
|
+
* | `@Authenticate({ optional: true })` | pass, user `null` | pass | 401 |
|
|
31
|
+
* | `@Public()` | providers not called | not called | not called |
|
|
32
|
+
*
|
|
33
|
+
* A result with `mfa: 'pending'` (second factor outstanding) does not count
|
|
34
|
+
* as signed in: 401 `mfa_required` where a user is required, anonymous on
|
|
35
|
+
* optional routes. `@Authenticate({ mfa: true })` needs `mfa: 'verified'`,
|
|
36
|
+
* and `@Authenticate({ verifiedEmail: true })` a verified address (403).
|
|
37
|
+
*
|
|
38
|
+
* Providers run once per call: the raw result is cached on the request, the
|
|
39
|
+
* GraphQL operation's context, or per ws message. With
|
|
40
|
+
* `@Authenticate({ providers })`, a cached result from another provider is
|
|
41
|
+
* ignored.
|
|
42
|
+
*
|
|
43
|
+
* Where Nest runs no global guard, neither does this one: on GraphQL field
|
|
44
|
+
* resolvers (`@ResolveField`), unless the GraphQL module sets
|
|
45
|
+
* `fieldResolverEnhancers: ['guards']`, and on the message handlers of a
|
|
46
|
+
* hybrid app, unless it connects them with
|
|
47
|
+
* `app.connectMicroservice(options, { inheritAppConfig: true })`. There,
|
|
48
|
+
* route options are not enforced.
|
|
49
|
+
*/
|
|
50
|
+
let AuthenticationGuard = class AuthenticationGuard {
|
|
51
|
+
constructor(reflector, adapterHost, registry) {
|
|
52
|
+
this.reflector = reflector;
|
|
53
|
+
this.adapterHost = adapterHost;
|
|
54
|
+
this.registry = registry;
|
|
55
|
+
}
|
|
56
|
+
async canActivate(context) {
|
|
57
|
+
const route = this.route(context);
|
|
58
|
+
if (route.public) {
|
|
59
|
+
// Nothing is written for http/graphql/rpc (another resolver of the same
|
|
60
|
+
// GraphQL operation may need the user); ws marks just this message.
|
|
61
|
+
if (context.getType() === 'ws') {
|
|
62
|
+
setAuthState(context, null, { perCallOnly: true });
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
const only = route.providers;
|
|
67
|
+
const all = this.registry.providers;
|
|
68
|
+
const providers = only ? all.filter((p) => only.some((type) => p instanceof type)) : all;
|
|
69
|
+
let raw = getRawResult(context);
|
|
70
|
+
if (only && raw && !providers.includes(producedBy.get(raw))) {
|
|
71
|
+
raw = undefined;
|
|
72
|
+
}
|
|
73
|
+
if (raw === undefined) {
|
|
74
|
+
raw = await this.authenticate(context, providers, !only);
|
|
75
|
+
// A restricted run does not speak for the other routes sharing the carrier.
|
|
76
|
+
if (!only) {
|
|
77
|
+
setRawResult(context, raw);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const pending = raw?.mfa === 'pending';
|
|
81
|
+
const result = pending ? null : raw;
|
|
82
|
+
if (!result) {
|
|
83
|
+
if (route.optional) {
|
|
84
|
+
setAuthState(context, null);
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if (!only) {
|
|
88
|
+
this.forgetConnection(context);
|
|
89
|
+
}
|
|
90
|
+
if (pending) {
|
|
91
|
+
return this.fail(context, MFA_REQUIRED);
|
|
92
|
+
}
|
|
93
|
+
return this.fail(context, {}, this.challenges(context, providers));
|
|
94
|
+
}
|
|
95
|
+
if (route.mfa && result.mfa !== 'verified') {
|
|
96
|
+
return this.fail(context, MFA_REQUIRED);
|
|
97
|
+
}
|
|
98
|
+
if (route.verifiedEmail) {
|
|
99
|
+
const handler = this.registry.handler('emailVerification');
|
|
100
|
+
const verified = handler?.isVerified ? await handler.isVerified(result.user) : hasVerifiedEmail(result.user);
|
|
101
|
+
if (!verified) {
|
|
102
|
+
return this.fail(context, EMAIL_UNVERIFIED);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
setAuthState(context, result);
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
/** Class options with the method's merged over them, field by field. */
|
|
109
|
+
route(context) {
|
|
110
|
+
return {
|
|
111
|
+
...this.reflector.get(AUTHENTICATION_METADATA, context.getClass()),
|
|
112
|
+
...this.reflector.get(AUTHENTICATION_METADATA, context.getHandler()),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
async authenticate(context, providers, everyProvider) {
|
|
116
|
+
for (const provider of providers) {
|
|
117
|
+
try {
|
|
118
|
+
const result = await provider.authenticate(context);
|
|
119
|
+
if (result?.user) {
|
|
120
|
+
producedBy.set(result, provider);
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
if (error instanceof AuthenticationError) {
|
|
126
|
+
if (everyProvider || error.status === 401) {
|
|
127
|
+
this.forgetConnection(context);
|
|
128
|
+
}
|
|
129
|
+
const { status, message, code } = error;
|
|
130
|
+
return this.fail(context, { status, message, code, cause: error }, error.challenge);
|
|
131
|
+
}
|
|
132
|
+
throw error; // a store outage is a 500, not a 401
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* A ws socket keeps its last user (`client.user`) for code that reads it on
|
|
139
|
+
* messages that run no provider (`@Public()`): a message refused for its
|
|
140
|
+
* credentials says the connection has none now, its session revoked or its
|
|
141
|
+
* token expired. `@nestjs/authorization` asks for each message's own user
|
|
142
|
+
* instead (`userOf` in auth-state.util.ts).
|
|
143
|
+
*/
|
|
144
|
+
forgetConnection(context) {
|
|
145
|
+
if (context.getType() === 'ws') {
|
|
146
|
+
setAuthState(context, null);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
challenges(context, providers) {
|
|
150
|
+
// Once each: a JWT and an API key provider in one realm accept the same `Bearer realm="…"`.
|
|
151
|
+
const list = new Set(providers.map((p) => p.challenge?.(context)).filter((c) => !!c));
|
|
152
|
+
return [...list].join(', ') || undefined;
|
|
153
|
+
}
|
|
154
|
+
async fail(context, reason, challenge) {
|
|
155
|
+
throw await refusal(context, reason, { challenge, adapterHost: this.adapterHost });
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
_a = AUTHENTICATION_GUARD_BRAND;
|
|
159
|
+
/**
|
|
160
|
+
* How `@nestjs/authorization` recognizes this guard, subclasses included,
|
|
161
|
+
* whatever their names: it fails at startup when this guard would run
|
|
162
|
+
* after its own.
|
|
163
|
+
*/
|
|
164
|
+
AuthenticationGuard[_a] = true;
|
|
165
|
+
AuthenticationGuard = __decorate([
|
|
166
|
+
Injectable(),
|
|
167
|
+
__metadata("design:paramtypes", [Reflector,
|
|
168
|
+
HttpAdapterHost,
|
|
169
|
+
AuthenticationRegistry])
|
|
170
|
+
], AuthenticationGuard);
|
|
171
|
+
export { AuthenticationGuard };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './authentication.guard.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './authentication.guard.js';
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export { AuthenticationModule } from './authentication.module.js';
|
|
2
|
+
export type { AuthenticationModuleAsyncOptions } from './authentication.module-definition.js';
|
|
3
|
+
export { AUTHENTICATION_MODULE_OPTIONS } from './authentication.constants.js';
|
|
4
|
+
export { AuthenticationRegistry } from './services/index.js';
|
|
5
|
+
export { AuthenticationStorage } from './storage/index.js';
|
|
6
|
+
export { AuthenticationGuard } from './guards/index.js';
|
|
7
|
+
export { Authenticate, CurrentSession, CurrentUser, Public } from './decorators/index.js';
|
|
8
|
+
export { AuthenticationContext } from './context/index.js';
|
|
9
|
+
export { WsAuthenticator } from './services/index.js';
|
|
10
|
+
export { AuthenticationProvider } from './providers/index.js';
|
|
11
|
+
export { ApiKeyProvider } from './providers/index.js';
|
|
12
|
+
export { AuthenticationError, JwtError, MagicLinkError, MfaAlreadyEnrolledError, RefreshTokenError, } from './errors/index.js';
|
|
13
|
+
export { AuthenticationEvents, type AuthenticationEmailVerifiedEvent, type AuthenticationEvent, type AuthenticationMagicLinkRefusedEvent, type AuthenticationMfaDisabledEvent, type AuthenticationMfaEnabledEvent, type AuthenticationMfaFailedEvent, type AuthenticationMfaVerifiedEvent, type AuthenticationPasswordResetEvent, type AuthenticationPasswordResetRequestedEvent, type AuthenticationRecoveryCodesGeneratedEvent, type AuthenticationRefreshTokenReusedEvent, type AuthenticationSignInEvent, type AuthenticationSignOutEvent, } from './events/index.js';
|
|
14
|
+
export type { ApiKeyProviderOptions, ApiKeyRecord, ApiKeySession, AuthenticateOptions, AuthenticationErrorOptions, AuthenticationHandlerName, AuthenticationHandlers, AuthenticationModuleOptions, AuthenticationOptionsFactory, AuthenticationResult, AuthenticationStorageContract, AuthenticationStorageRegisterOptions, AuthenticationStorageSources, CreatedMagicLink, CredentialProvider, Duration, EmailTokenPurpose, EmailTokenRecord, EmailTokenStore, EmailVerificationLink, EmailVerificationOptions, GeneratedApiKey, IssuedSession, IssueTokensOptions, JwksClientOptions, JwsAlgorithm, JwtBearerProviderOptions, JwtClaims, JwtSignerOptions, JwtVerifierOptions, MagicLink, MagicLinkAccount, MagicLinkOptions, MagicLinkRecord, MagicLinkRequest, MagicLinkStore, MfaOptions, MfaState, MfaStore, OAuthTokens, OidcOptions, OidcProfile, OidcProviderConfig, OidcRedirect, OidcRequest, OidcResolveContext, OidcStartOptions, OidcStateStore, OidcTransaction, PasswordHasherOptions, PasswordResetAccount, PasswordResetLink, PasswordResetOptions, PasswordResetResult, RefreshTokenOptions, RefreshTokenRecord, RefreshTokenStore, RegisterHandlerOptions, RegisterProviderOptions, ResetPasswordOptions, SessionOptions, SessionRecord, SessionStore, SignInOptions, TokenPair, TotpRecord, } from './interfaces/index.js';
|
|
15
|
+
export { SessionCookieProvider } from './session/session-cookie.provider.js';
|
|
16
|
+
export { InMemorySessionStore } from './session/in-memory-session.store.js';
|
|
17
|
+
export { SessionService } from './session/session.service.js';
|
|
18
|
+
export { SignInService } from './session/sign-in.service.js';
|
|
19
|
+
export { PasswordHasher } from './services/index.js';
|
|
20
|
+
export { InMemoryMfaStore } from './mfa/in-memory-mfa.store.js';
|
|
21
|
+
export { MfaService } from './mfa/mfa.service.js';
|
|
22
|
+
export { JwksClient } from './jwt/jwks.client.js';
|
|
23
|
+
export { JwtBearerProvider } from './jwt/jwt-bearer.provider.js';
|
|
24
|
+
export { JwtSigner } from './jwt/jwt-signer.service.js';
|
|
25
|
+
export { JwtVerifier } from './jwt/jwt-verifier.service.js';
|
|
26
|
+
export { InMemoryRefreshTokenStore } from './jwt/in-memory-refresh-token.store.js';
|
|
27
|
+
export { TokenService } from './jwt/token.service.js';
|
|
28
|
+
export { MagicLinkHandler } from './magic-link/magic-link.handler.js';
|
|
29
|
+
export { MagicLinkService } from './magic-link/magic-link.service.js';
|
|
30
|
+
export { InMemoryMagicLinkStore } from './magic-link/in-memory-magic-link.store.js';
|
|
31
|
+
export { InMemoryEmailTokenStore } from './account/in-memory-email-token.store.js';
|
|
32
|
+
export { EmailVerificationHandler } from './account/email-verification.handler.js';
|
|
33
|
+
export { EmailVerificationService } from './account/email-verification.service.js';
|
|
34
|
+
export { PasswordResetHandler } from './account/password-reset.handler.js';
|
|
35
|
+
export { PasswordResetService } from './account/password-reset.service.js';
|
|
36
|
+
export { OidcAccountResolver } from './oidc/oidc-account.resolver.js';
|
|
37
|
+
export { OidcService } from './oidc/oidc.service.js';
|
|
38
|
+
export { InMemoryOidcStateStore } from './oidc/in-memory-oidc-state.store.js';
|
|
39
|
+
export { github, google, microsoft } from './oidc/oidc.presets.js';
|
|
40
|
+
/**
|
|
41
|
+
* Augment once per app to type `@CurrentUser('key')`,
|
|
42
|
+
* `AuthenticationContext.user` and `AuthenticationContext.session`:
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* declare module '@nestjs/authentication' {
|
|
46
|
+
* interface AuthenticationTypes {
|
|
47
|
+
* user: User;
|
|
48
|
+
* }
|
|
49
|
+
* }
|
|
50
|
+
*/
|
|
51
|
+
export interface AuthenticationTypes {
|
|
52
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Module
|
|
2
|
+
export { AuthenticationModule } from './authentication.module.js';
|
|
3
|
+
export { AUTHENTICATION_MODULE_OPTIONS } from './authentication.constants.js';
|
|
4
|
+
// Registration: credential providers and feature handlers are providers of your modules that register here
|
|
5
|
+
export { AuthenticationRegistry } from './services/index.js';
|
|
6
|
+
// Storage: the contracts below are interfaces your providers implement, registered here
|
|
7
|
+
export { AuthenticationStorage } from './storage/index.js';
|
|
8
|
+
// Routes and the current user
|
|
9
|
+
export { AuthenticationGuard } from './guards/index.js';
|
|
10
|
+
export { Authenticate, CurrentSession, CurrentUser, Public } from './decorators/index.js';
|
|
11
|
+
export { AuthenticationContext } from './context/index.js';
|
|
12
|
+
export { WsAuthenticator } from './services/index.js';
|
|
13
|
+
// Writing a credential provider
|
|
14
|
+
export { AuthenticationProvider } from './providers/index.js';
|
|
15
|
+
// API keys
|
|
16
|
+
export { ApiKeyProvider } from './providers/index.js';
|
|
17
|
+
// Errors: `AuthenticationError` is the base class of every error the package throws to apps
|
|
18
|
+
export { AuthenticationError, JwtError, MagicLinkError, MfaAlreadyEnrolledError, RefreshTokenError, } from './errors/index.js';
|
|
19
|
+
// Audit events (also on `nestjs:authentication:<type>` diagnostics channels)
|
|
20
|
+
export { AuthenticationEvents, } from './events/index.js';
|
|
21
|
+
// Sessions
|
|
22
|
+
export { SessionCookieProvider } from './session/session-cookie.provider.js';
|
|
23
|
+
export { InMemorySessionStore } from './session/in-memory-session.store.js';
|
|
24
|
+
export { SessionService } from './session/session.service.js';
|
|
25
|
+
export { SignInService } from './session/sign-in.service.js';
|
|
26
|
+
// Passwords
|
|
27
|
+
export { PasswordHasher } from './services/index.js';
|
|
28
|
+
// Second factor (TOTP and recovery codes)
|
|
29
|
+
export { InMemoryMfaStore } from './mfa/in-memory-mfa.store.js';
|
|
30
|
+
export { MfaService } from './mfa/mfa.service.js';
|
|
31
|
+
// JWTs, access and refresh tokens
|
|
32
|
+
export { JwksClient } from './jwt/jwks.client.js';
|
|
33
|
+
export { JwtBearerProvider } from './jwt/jwt-bearer.provider.js';
|
|
34
|
+
export { JwtSigner } from './jwt/jwt-signer.service.js';
|
|
35
|
+
export { JwtVerifier } from './jwt/jwt-verifier.service.js';
|
|
36
|
+
export { InMemoryRefreshTokenStore } from './jwt/in-memory-refresh-token.store.js';
|
|
37
|
+
export { TokenService } from './jwt/token.service.js';
|
|
38
|
+
// Magic links
|
|
39
|
+
export { MagicLinkHandler } from './magic-link/magic-link.handler.js';
|
|
40
|
+
export { MagicLinkService } from './magic-link/magic-link.service.js';
|
|
41
|
+
export { InMemoryMagicLinkStore } from './magic-link/in-memory-magic-link.store.js';
|
|
42
|
+
// Password reset and email verification
|
|
43
|
+
export { InMemoryEmailTokenStore } from './account/in-memory-email-token.store.js';
|
|
44
|
+
export { EmailVerificationHandler } from './account/email-verification.handler.js';
|
|
45
|
+
export { EmailVerificationService } from './account/email-verification.service.js';
|
|
46
|
+
export { PasswordResetHandler } from './account/password-reset.handler.js';
|
|
47
|
+
export { PasswordResetService } from './account/password-reset.service.js';
|
|
48
|
+
// OAuth 2.0 / OpenID Connect
|
|
49
|
+
export { OidcAccountResolver } from './oidc/oidc-account.resolver.js';
|
|
50
|
+
export { OidcService } from './oidc/oidc.service.js';
|
|
51
|
+
export { InMemoryOidcStateStore } from './oidc/in-memory-oidc-state.store.js';
|
|
52
|
+
export { github, google, microsoft } from './oidc/oidc.presets.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type CallHandler, type ExecutionContext, type NestInterceptor } from '@nestjs/common';
|
|
2
|
+
import { HttpAdapterHost } from '@nestjs/core';
|
|
3
|
+
import { Observable } from 'rxjs';
|
|
4
|
+
import { AuthenticationScope } from '../context/authentication-scope.service.js';
|
|
5
|
+
/**
|
|
6
|
+
* @internal Opens the scope with what the guard recorded, around the
|
|
7
|
+
* subscription to `next.handle()`, not just the call: an inner interceptor
|
|
8
|
+
* may call its own `next.handle()` only when it is subscribed, and again per
|
|
9
|
+
* attempt (`@nestjs/resilience` retries), and the handler runs in the async
|
|
10
|
+
* context of that call. Subscribing inside `run()` covers every such call,
|
|
11
|
+
* pipes, the handler and everything they await. An `AuthenticationError`
|
|
12
|
+
* escaping the handler becomes the transport's error for its status (a 401,
|
|
13
|
+
* or a 409).
|
|
14
|
+
*/
|
|
15
|
+
export declare class AuthenticationScopeInterceptor implements NestInterceptor {
|
|
16
|
+
private readonly scope;
|
|
17
|
+
private readonly adapterHost;
|
|
18
|
+
constructor(scope: AuthenticationScope, adapterHost: HttpAdapterHost);
|
|
19
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Injectable } from '@nestjs/common';
|
|
11
|
+
import { HttpAdapterHost } from '@nestjs/core';
|
|
12
|
+
import { catchError, from, mergeMap, Observable, throwError } from 'rxjs';
|
|
13
|
+
import { getAuthState } from '../utils/auth-state.util.js';
|
|
14
|
+
import { AuthenticationError } from '../errors/authentication.error.js';
|
|
15
|
+
import { refusal } from '../utils/transport-errors.util.js';
|
|
16
|
+
import { AuthenticationScope, runCall } from '../context/authentication-scope.service.js';
|
|
17
|
+
/**
|
|
18
|
+
* @internal Opens the scope with what the guard recorded, around the
|
|
19
|
+
* subscription to `next.handle()`, not just the call: an inner interceptor
|
|
20
|
+
* may call its own `next.handle()` only when it is subscribed, and again per
|
|
21
|
+
* attempt (`@nestjs/resilience` retries), and the handler runs in the async
|
|
22
|
+
* context of that call. Subscribing inside `run()` covers every such call,
|
|
23
|
+
* pipes, the handler and everything they await. An `AuthenticationError`
|
|
24
|
+
* escaping the handler becomes the transport's error for its status (a 401,
|
|
25
|
+
* or a 409).
|
|
26
|
+
*/
|
|
27
|
+
let AuthenticationScopeInterceptor = class AuthenticationScopeInterceptor {
|
|
28
|
+
constructor(scope, adapterHost) {
|
|
29
|
+
this.scope = scope;
|
|
30
|
+
this.adapterHost = adapterHost;
|
|
31
|
+
}
|
|
32
|
+
intercept(context, next) {
|
|
33
|
+
const scope = { result: getAuthState(context) ?? null, context };
|
|
34
|
+
return new Observable((subscriber) => this.scope.run(scope, () => runCall(scope, () => next.handle().subscribe(subscriber)))).pipe(catchError((error) => {
|
|
35
|
+
if (!(error instanceof AuthenticationError)) {
|
|
36
|
+
return throwError(() => error);
|
|
37
|
+
}
|
|
38
|
+
const mapped = refusal(context, { status: error.status, message: error.message, code: error.code, cause: error }, { challenge: error.challenge, adapterHost: this.adapterHost });
|
|
39
|
+
return from(mapped).pipe(mergeMap((exception) => throwError(() => exception)));
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
AuthenticationScopeInterceptor = __decorate([
|
|
44
|
+
Injectable(),
|
|
45
|
+
__metadata("design:paramtypes", [AuthenticationScope,
|
|
46
|
+
HttpAdapterHost])
|
|
47
|
+
], AuthenticationScopeInterceptor);
|
|
48
|
+
export { AuthenticationScopeInterceptor };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './authentication-scope.interceptor.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './authentication-scope.interceptor.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface ApiKeyProviderOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Starts every key, e.g. `cat` for `cat_<id>_<secret>`: 1-16 lowercase
|
|
4
|
+
* letters and digits, starting with a letter. Secret scanners find leaked
|
|
5
|
+
* keys by it; register it with yours (GitHub push protection, for one).
|
|
6
|
+
*/
|
|
7
|
+
prefix: string;
|
|
8
|
+
/** `realm` in the `WWW-Authenticate` challenge. Default `api`. */
|
|
9
|
+
realm?: string;
|
|
10
|
+
/** Clock in epoch milliseconds, for tests. */
|
|
11
|
+
now?: () => number;
|
|
12
|
+
}
|
|
13
|
+
/** A new key, from `ApiKeyProvider.generate()`. */
|
|
14
|
+
export interface GeneratedApiKey {
|
|
15
|
+
/** The whole key. Show it to its owner once, and store only `id` and `hash`. */
|
|
16
|
+
key: string;
|
|
17
|
+
/** The public part, which `findKey()` looks up: the key's row in your table. */
|
|
18
|
+
id: string;
|
|
19
|
+
/** SHA-256 of `key`, base64url. */
|
|
20
|
+
hash: string;
|
|
21
|
+
}
|
|
22
|
+
/** A key as your table has it, returned by `ApiKeyProvider.findKey()`. */
|
|
23
|
+
export interface ApiKeyRecord<TUser> {
|
|
24
|
+
/** The `hash` that `generate()` returned. */
|
|
25
|
+
hash: string;
|
|
26
|
+
/** Who the key acts as. */
|
|
27
|
+
user: TUser;
|
|
28
|
+
/** Refused from this moment on. */
|
|
29
|
+
expiresAt?: Date | null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* `@CurrentSession()` and `AuthenticationContext.session` for a request
|
|
33
|
+
* signed in with an API key.
|
|
34
|
+
*/
|
|
35
|
+
export interface ApiKeySession {
|
|
36
|
+
/** Tells this session from a `SessionRecord` or `JwtClaims`. */
|
|
37
|
+
method: 'api-key';
|
|
38
|
+
/** The key's public id. */
|
|
39
|
+
keyId: string;
|
|
40
|
+
expiresAt?: Date;
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ProviderClass } from '../providers/authentication.provider.js';
|
|
2
|
+
export interface AuthenticateOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Let anonymous callers through; `@CurrentUser()` is then `null`.
|
|
5
|
+
* Credentials that are present are still verified, and bad ones get a
|
|
6
|
+
* 401: silently ignoring an expired token would hide the signal to
|
|
7
|
+
* refresh it.
|
|
8
|
+
*/
|
|
9
|
+
optional?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Require a verified second factor (step-up): a session that completed
|
|
12
|
+
* MFA, or a JWT whose `amr` claim contains `mfa`, `otp` or `hwk`.
|
|
13
|
+
*/
|
|
14
|
+
mfa?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Require a user whose email address is verified: 403 `email_unverified`
|
|
17
|
+
* otherwise. Checked with `EmailVerificationHandler.isVerified(user)`, or
|
|
18
|
+
* `user.emailVerified === true` without a handler.
|
|
19
|
+
*/
|
|
20
|
+
verifiedEmail?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Only these providers may authenticate the route: classes, matched with
|
|
23
|
+
* `instanceof`, so a base class such as `SessionCookieProvider` covers its
|
|
24
|
+
* subclasses. Credentials of any other provider count as none.
|
|
25
|
+
*/
|
|
26
|
+
providers?: ProviderClass[];
|
|
27
|
+
}
|
|
28
|
+
/** @internal What the guard reads: the class options, with the method's merged over them. */
|
|
29
|
+
export interface RouteAuthentication extends AuthenticateOptions {
|
|
30
|
+
public?: boolean;
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface AuthenticationErrorOptions {
|
|
2
|
+
/** `WWW-Authenticate` challenge sent with the 401 over HTTP, e.g. `ApiKey header="x-api-key"`. */
|
|
3
|
+
challenge?: string;
|
|
4
|
+
/** Machine-readable reason, sent as the body's `error` field (`mfa_required`). */
|
|
5
|
+
code?: string;
|
|
6
|
+
/** The error behind this one, for logs. */
|
|
7
|
+
cause?: unknown;
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { EmailVerificationOptions } from './email-verification.interface.js';
|
|
2
|
+
import type { PasswordResetOptions } from './password-reset.interface.js';
|
|
3
|
+
import type { JwtSignerOptions } from './jwt-options.interface.js';
|
|
4
|
+
import type { RefreshTokenOptions } from './refresh-token-options.interface.js';
|
|
5
|
+
import type { MagicLinkOptions } from './magic-link.interface.js';
|
|
6
|
+
import type { MfaOptions } from './mfa-options.interface.js';
|
|
7
|
+
import type { OidcOptions } from './oidc.interface.js';
|
|
8
|
+
import type { PasswordHasherOptions } from './password-hasher-options.interface.js';
|
|
9
|
+
import type { SessionOptions } from './session.interface.js';
|
|
10
|
+
/**
|
|
11
|
+
* Configuration values: what `forRoot()` takes, and what `forRootAsync()`'s
|
|
12
|
+
* factory returns. Injectable as `AUTHENTICATION_MODULE_OPTIONS`. Classes
|
|
13
|
+
* are never options: credential providers and feature handlers are
|
|
14
|
+
* providers of your own modules that register themselves with
|
|
15
|
+
* `AuthenticationRegistry`, and stores with `AuthenticationStorage`.
|
|
16
|
+
*/
|
|
17
|
+
export interface AuthenticationModuleOptions {
|
|
18
|
+
session?: SessionOptions;
|
|
19
|
+
password?: PasswordHasherOptions;
|
|
20
|
+
/** Enables TOTP enrollment. Requires `encryption`. */
|
|
21
|
+
mfa?: MfaOptions;
|
|
22
|
+
/** Goes with a registered `MagicLinkHandler` (`'magicLink'`): each fails at startup without the other. */
|
|
23
|
+
magicLink?: MagicLinkOptions;
|
|
24
|
+
/**
|
|
25
|
+
* The access tokens `TokenService` issues, and that `JwtBearerProvider`
|
|
26
|
+
* verifies unless it is given its own `key` or `jwks`.
|
|
27
|
+
*/
|
|
28
|
+
accessToken?: JwtSignerOptions;
|
|
29
|
+
refreshToken?: RefreshTokenOptions;
|
|
30
|
+
/** Goes with a registered `OidcAccountResolver` (`'oidc'`): each fails at startup without the other. */
|
|
31
|
+
oidc?: OidcOptions;
|
|
32
|
+
/** Goes with a registered `PasswordResetHandler` (`'passwordReset'`): each fails at startup without the other. */
|
|
33
|
+
passwordReset?: PasswordResetOptions;
|
|
34
|
+
/** Goes with a registered `EmailVerificationHandler` (`'emailVerification'`): each fails at startup without the other. */
|
|
35
|
+
emailVerification?: EmailVerificationOptions;
|
|
36
|
+
/**
|
|
37
|
+
* Lets the app run in production while a contract it uses has no
|
|
38
|
+
* registered store, on the in-memory default (one instance, state lost on
|
|
39
|
+
* restart). Default `false`: startup fails, naming the contracts the
|
|
40
|
+
* configured features use without a store, and so does the first read of
|
|
41
|
+
* any other contract without one. Storage itself is never an option:
|
|
42
|
+
* providers register it with `AuthenticationStorage.registerSource()`.
|
|
43
|
+
*/
|
|
44
|
+
allowInMemoryStorage?: boolean;
|
|
45
|
+
}
|
|
46
|
+
/** The two switches that decide what the module registers, at the top level of `forRoot()` and `forRootAsync()`. */
|
|
47
|
+
export interface AuthenticationModuleExtras {
|
|
48
|
+
/** Default `true`. */
|
|
49
|
+
isGlobal?: boolean;
|
|
50
|
+
/** Registers `AuthenticationGuard` as a global guard. Default `true`. */
|
|
51
|
+
globalGuard?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/** What `forRoot()` takes: the values, and the two switches. */
|
|
54
|
+
export type AuthenticationModuleForRootOptions = AuthenticationModuleOptions & AuthenticationModuleExtras;
|
|
55
|
+
/** What a `forRootAsync({ useClass })` or `useExisting` class implements. */
|
|
56
|
+
export interface AuthenticationOptionsFactory {
|
|
57
|
+
createAuthenticationOptions(): AuthenticationModuleOptions | Promise<AuthenticationModuleOptions>;
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|