@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,64 @@
|
|
|
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 { AsyncLocalStorage } from 'node:async_hooks';
|
|
8
|
+
import { Injectable } from '@nestjs/common';
|
|
9
|
+
/**
|
|
10
|
+
* The call the interceptor is handling, for the param decorators, which have no instance to ask:
|
|
11
|
+
* one store for the process, entered with the instance's own by `AuthenticationScopeInterceptor`.
|
|
12
|
+
*/
|
|
13
|
+
const calls = new AsyncLocalStorage();
|
|
14
|
+
/** @internal Runs `fn` as the handling of this call (the interceptor, around `next.handle()`). */
|
|
15
|
+
export function runCall(scope, fn) {
|
|
16
|
+
return calls.run(scope, fn);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* @internal What the handler of this call sees: the result the guard recorded for it, when the
|
|
20
|
+
* interceptor is handling this handler (param decorators are resolved inside it).
|
|
21
|
+
*/
|
|
22
|
+
export function scopedResult(context) {
|
|
23
|
+
const call = calls.getStore();
|
|
24
|
+
return call?.context && call.context.getHandler() === context.getHandler() ? call.result : undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @internal The per-call scope behind `AuthenticationContext` and
|
|
28
|
+
* `SignInService`: its own `AsyncLocalStorage`, opened around each handler
|
|
29
|
+
* by `AuthenticationScopeInterceptor`.
|
|
30
|
+
*/
|
|
31
|
+
let AuthenticationScope = class AuthenticationScope {
|
|
32
|
+
constructor() {
|
|
33
|
+
this.storage = new AsyncLocalStorage();
|
|
34
|
+
}
|
|
35
|
+
get current() {
|
|
36
|
+
return this.storage.getStore();
|
|
37
|
+
}
|
|
38
|
+
run(scope, fn) {
|
|
39
|
+
return this.storage.run(scope, fn);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The HTTP request and response of the current call: an HTTP handler, or
|
|
43
|
+
* a GraphQL resolver whose context carries `req` (and `res`).
|
|
44
|
+
*/
|
|
45
|
+
exchange() {
|
|
46
|
+
const context = this.current?.context;
|
|
47
|
+
switch (context?.getType()) {
|
|
48
|
+
case 'http': {
|
|
49
|
+
const http = context.switchToHttp();
|
|
50
|
+
return { request: http.getRequest(), response: http.getResponse() };
|
|
51
|
+
}
|
|
52
|
+
case 'graphql': {
|
|
53
|
+
const gql = context.getArgByIndex(2);
|
|
54
|
+
return gql?.req ? { request: gql.req, response: gql.res } : undefined;
|
|
55
|
+
}
|
|
56
|
+
default:
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
AuthenticationScope = __decorate([
|
|
62
|
+
Injectable()
|
|
63
|
+
], AuthenticationScope);
|
|
64
|
+
export { AuthenticationScope };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AuthenticatedSession, AuthenticatedUser, AuthenticationResult } from '../interfaces/authentication-result.interface.js';
|
|
2
|
+
import { AuthenticationScope } from './authentication-scope.service.js';
|
|
3
|
+
/**
|
|
4
|
+
* The current user and session, readable from any singleton provider
|
|
5
|
+
* without passing the request down. Correct in the handler and in
|
|
6
|
+
* everything it calls or awaits, however many requests run at once. Empty
|
|
7
|
+
* in middleware, guards and exception filters, in interceptors that run
|
|
8
|
+
* before the module's own (an app's `APP_INTERCEPTOR` declared ahead of it:
|
|
9
|
+
* read `@CurrentUser()` or `request.user` there), and outside requests.
|
|
10
|
+
* A stream a handler returns but did not create (a shared `Subject`) runs
|
|
11
|
+
* its operators in the scope of whoever emits: read the user before
|
|
12
|
+
* building it.
|
|
13
|
+
*/
|
|
14
|
+
export declare class AuthenticationContext<TUser = AuthenticatedUser, TSession = AuthenticatedSession> {
|
|
15
|
+
private readonly scope;
|
|
16
|
+
constructor(scope?: AuthenticationScope);
|
|
17
|
+
/** The user, or `null` when anonymous or outside a request. */
|
|
18
|
+
get user(): TUser | null;
|
|
19
|
+
get session(): TSession | null;
|
|
20
|
+
get isAuthenticated(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The user, or an {@link AuthenticationError}: a 401 on any transport when
|
|
23
|
+
* thrown under a handler, a plain error in a queue worker.
|
|
24
|
+
*/
|
|
25
|
+
requireUser(): TUser;
|
|
26
|
+
/** Runs `fn` as `result.user`, for queue workers, cron jobs and tests. */
|
|
27
|
+
run<R>(result: AuthenticationResult<TUser, TSession> | null, fn: () => R): R;
|
|
28
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
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 { AuthenticationError } from '../errors/authentication.error.js';
|
|
12
|
+
import { AuthenticationScope } from './authentication-scope.service.js';
|
|
13
|
+
/**
|
|
14
|
+
* The current user and session, readable from any singleton provider
|
|
15
|
+
* without passing the request down. Correct in the handler and in
|
|
16
|
+
* everything it calls or awaits, however many requests run at once. Empty
|
|
17
|
+
* in middleware, guards and exception filters, in interceptors that run
|
|
18
|
+
* before the module's own (an app's `APP_INTERCEPTOR` declared ahead of it:
|
|
19
|
+
* read `@CurrentUser()` or `request.user` there), and outside requests.
|
|
20
|
+
* A stream a handler returns but did not create (a shared `Subject`) runs
|
|
21
|
+
* its operators in the scope of whoever emits: read the user before
|
|
22
|
+
* building it.
|
|
23
|
+
*/
|
|
24
|
+
let AuthenticationContext = class AuthenticationContext {
|
|
25
|
+
constructor(scope = new AuthenticationScope()) {
|
|
26
|
+
this.scope = scope;
|
|
27
|
+
}
|
|
28
|
+
/** The user, or `null` when anonymous or outside a request. */
|
|
29
|
+
get user() {
|
|
30
|
+
return this.scope.current?.result?.user ?? null;
|
|
31
|
+
}
|
|
32
|
+
get session() {
|
|
33
|
+
return this.scope.current?.result?.session ?? null;
|
|
34
|
+
}
|
|
35
|
+
get isAuthenticated() {
|
|
36
|
+
return !!this.scope.current?.result?.user;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The user, or an {@link AuthenticationError}: a 401 on any transport when
|
|
40
|
+
* thrown under a handler, a plain error in a queue worker.
|
|
41
|
+
*/
|
|
42
|
+
requireUser() {
|
|
43
|
+
const user = this.user;
|
|
44
|
+
if (!user) {
|
|
45
|
+
throw new AuthenticationError();
|
|
46
|
+
}
|
|
47
|
+
return user;
|
|
48
|
+
}
|
|
49
|
+
/** Runs `fn` as `result.user`, for queue workers, cron jobs and tests. */
|
|
50
|
+
run(result, fn) {
|
|
51
|
+
return this.scope.run({ result }, fn);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
AuthenticationContext = __decorate([
|
|
55
|
+
Injectable(),
|
|
56
|
+
__metadata("design:paramtypes", [AuthenticationScope])
|
|
57
|
+
], AuthenticationContext);
|
|
58
|
+
export { AuthenticationContext };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AuthenticateOptions, RouteAuthentication } from '../interfaces/authenticate-options.interface.js';
|
|
2
|
+
/** Merges into the metadata already on the class or method, so decorators can be stacked. */
|
|
3
|
+
export declare function route(value: RouteAuthentication): ClassDecorator & MethodDecorator;
|
|
4
|
+
/**
|
|
5
|
+
* Configures authentication for a controller or a handler. Every route
|
|
6
|
+
* already requires a signed-in user; use this to relax that (`optional`),
|
|
7
|
+
* tighten it (`mfa`, `verifiedEmail`, `providers`), or require it again under a `@Public()`
|
|
8
|
+
* class. Method options merge over class options, field by field.
|
|
9
|
+
*/
|
|
10
|
+
export declare const Authenticate: (options?: AuthenticateOptions) => ClassDecorator & MethodDecorator;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AUTHENTICATION_METADATA } from '../authentication.constants.js';
|
|
2
|
+
/** Merges into the metadata already on the class or method, so decorators can be stacked. */
|
|
3
|
+
export function route(value) {
|
|
4
|
+
const defined = Object.fromEntries(Object.entries(value).filter(([, field]) => field !== undefined));
|
|
5
|
+
const decorator = (target, _key, descriptor) => {
|
|
6
|
+
const holder = descriptor ? descriptor.value : target;
|
|
7
|
+
const existing = Reflect.getMetadata(AUTHENTICATION_METADATA, holder);
|
|
8
|
+
Reflect.defineMetadata(AUTHENTICATION_METADATA, { ...existing, ...defined }, holder);
|
|
9
|
+
};
|
|
10
|
+
return decorator;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Configures authentication for a controller or a handler. Every route
|
|
14
|
+
* already requires a signed-in user; use this to relax that (`optional`),
|
|
15
|
+
* tighten it (`mfa`, `verifiedEmail`, `providers`), or require it again under a `@Public()`
|
|
16
|
+
* class. Method options merge over class options, field by field.
|
|
17
|
+
*/
|
|
18
|
+
export const Authenticate = (options = {}) => route({ ...options, public: false });
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createParamDecorator } from '@nestjs/common';
|
|
2
|
+
import { resultOf } from '../utils/auth-state.util.js';
|
|
3
|
+
/** The provider's session object (a `SessionRecord`, JWT claims, an `ApiKeySession`), or `null`. */
|
|
4
|
+
export const CurrentSession = createParamDecorator((_, context) => {
|
|
5
|
+
return resultOf(context)?.session ?? null;
|
|
6
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The authenticated user, or `null` on `@Public()` and anonymous optional
|
|
3
|
+
* calls. `@CurrentUser('email')` picks one property; the key is checked
|
|
4
|
+
* against the `AuthenticationTypes` augmentation.
|
|
5
|
+
*/
|
|
6
|
+
export declare const CurrentUser: (...dataOrPipes: (string | import("@nestjs/common").ParameterDecoratorOptions | import("@nestjs/common").PipeTransform<any, any> | import("@nestjs/common").Type<import("@nestjs/common").PipeTransform<any, any>> | undefined)[]) => ParameterDecorator;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createParamDecorator } from '@nestjs/common';
|
|
2
|
+
import { resultOf } from '../utils/auth-state.util.js';
|
|
3
|
+
/**
|
|
4
|
+
* The authenticated user, or `null` on `@Public()` and anonymous optional
|
|
5
|
+
* calls. `@CurrentUser('email')` picks one property; the key is checked
|
|
6
|
+
* against the `AuthenticationTypes` augmentation.
|
|
7
|
+
*/
|
|
8
|
+
export const CurrentUser = createParamDecorator((key, context) => {
|
|
9
|
+
const user = resultOf(context)?.user ?? null;
|
|
10
|
+
return key && user ? user[key] : user;
|
|
11
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { route } from './authenticate.decorator.js';
|
|
2
|
+
/**
|
|
3
|
+
* Skips authentication: no provider runs, and `@CurrentUser()` is `null`.
|
|
4
|
+
* For health checks, the public catalog, and the routes that sign users in.
|
|
5
|
+
*/
|
|
6
|
+
export const Public = () => route({ public: true });
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AuthenticationErrorOptions } from '../interfaces/authentication-error-options.interface.js';
|
|
2
|
+
/**
|
|
3
|
+
* The base class of this package's errors, and on its own the error for
|
|
4
|
+
* credentials that are missing or failed verification: a 401 on every
|
|
5
|
+
* transport.
|
|
6
|
+
*
|
|
7
|
+
* - Thrown by a provider, the guard answers with it and sends `challenge`
|
|
8
|
+
* as the `WWW-Authenticate` header.
|
|
9
|
+
* - Thrown by a handler or anything it calls (`requireUser()`, a failed
|
|
10
|
+
* `TokenService.refresh()`), the module's interceptor turns it into the
|
|
11
|
+
* transport's error for its `status`: an HTTP 401 (409 for
|
|
12
|
+
* `MfaAlreadyEnrolledError`), GraphQL `UNAUTHENTICATED`, a `WsException`
|
|
13
|
+
* or an `RpcException`.
|
|
14
|
+
* - Elsewhere (a queue worker), it is a plain `Error`.
|
|
15
|
+
*/
|
|
16
|
+
export declare class AuthenticationError extends Error {
|
|
17
|
+
/**
|
|
18
|
+
* 401, or 409 for `MfaAlreadyEnrolledError`: the caller's fault, not an
|
|
19
|
+
* outage, so other packages classify it without importing this class
|
|
20
|
+
* (`@nestjs/resilience` neither retries it nor counts it against a
|
|
21
|
+
* circuit breaker).
|
|
22
|
+
*/
|
|
23
|
+
readonly status: 401 | 403 | 409;
|
|
24
|
+
readonly challenge?: string;
|
|
25
|
+
readonly code?: string;
|
|
26
|
+
constructor(message?: string, { challenge, code, cause }?: AuthenticationErrorOptions);
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The base class of this package's errors, and on its own the error for
|
|
3
|
+
* credentials that are missing or failed verification: a 401 on every
|
|
4
|
+
* transport.
|
|
5
|
+
*
|
|
6
|
+
* - Thrown by a provider, the guard answers with it and sends `challenge`
|
|
7
|
+
* as the `WWW-Authenticate` header.
|
|
8
|
+
* - Thrown by a handler or anything it calls (`requireUser()`, a failed
|
|
9
|
+
* `TokenService.refresh()`), the module's interceptor turns it into the
|
|
10
|
+
* transport's error for its `status`: an HTTP 401 (409 for
|
|
11
|
+
* `MfaAlreadyEnrolledError`), GraphQL `UNAUTHENTICATED`, a `WsException`
|
|
12
|
+
* or an `RpcException`.
|
|
13
|
+
* - Elsewhere (a queue worker), it is a plain `Error`.
|
|
14
|
+
*/
|
|
15
|
+
export class AuthenticationError extends Error {
|
|
16
|
+
constructor(message = 'Unauthorized', { challenge, code, cause } = {}) {
|
|
17
|
+
super(message, cause === undefined ? undefined : { cause });
|
|
18
|
+
/**
|
|
19
|
+
* 401, or 409 for `MfaAlreadyEnrolledError`: the caller's fault, not an
|
|
20
|
+
* outage, so other packages classify it without importing this class
|
|
21
|
+
* (`@nestjs/resilience` neither retries it nor counts it against a
|
|
22
|
+
* circuit breaker).
|
|
23
|
+
*/
|
|
24
|
+
this.status = 401;
|
|
25
|
+
this.name = new.target.name;
|
|
26
|
+
if (challenge !== undefined) {
|
|
27
|
+
this.challenge = challenge;
|
|
28
|
+
}
|
|
29
|
+
if (code !== undefined) {
|
|
30
|
+
this.code = code;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './authentication.error.js';
|
|
2
|
+
export * from './jwt.error.js';
|
|
3
|
+
export * from './magic-link.error.js';
|
|
4
|
+
export * from './mfa-already-enrolled.error.js';
|
|
5
|
+
export * from './oidc.error.js';
|
|
6
|
+
export * from './refresh-token.error.js';
|
|
7
|
+
export * from './secret-decryption.error.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './authentication.error.js';
|
|
2
|
+
export * from './jwt.error.js';
|
|
3
|
+
export * from './magic-link.error.js';
|
|
4
|
+
export * from './mfa-already-enrolled.error.js';
|
|
5
|
+
export * from './oidc.error.js';
|
|
6
|
+
export * from './refresh-token.error.js';
|
|
7
|
+
export * from './secret-decryption.error.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AuthenticationError } from './authentication.error.js';
|
|
2
|
+
/**
|
|
3
|
+
* A token failed verification: malformed, badly signed, expired, for
|
|
4
|
+
* another issuer or audience. An {@link AuthenticationError} (401), so a
|
|
5
|
+
* route that lets one escape answers 401 on any transport.
|
|
6
|
+
*/
|
|
7
|
+
export declare class JwtError extends AuthenticationError {
|
|
8
|
+
constructor(message: string);
|
|
9
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AuthenticationError } from './authentication.error.js';
|
|
2
|
+
/**
|
|
3
|
+
* A token failed verification: malformed, badly signed, expired, for
|
|
4
|
+
* another issuer or audience. An {@link AuthenticationError} (401), so a
|
|
5
|
+
* route that lets one escape answers 401 on any transport.
|
|
6
|
+
*/
|
|
7
|
+
export class JwtError extends AuthenticationError {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'JwtError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AuthenticationError } from './authentication.error.js';
|
|
2
|
+
/**
|
|
3
|
+
* A link was presented in a browser other than the one that requested it
|
|
4
|
+
* (see `magicLink.bindToBrowser`). The one refusal `consume()` tells
|
|
5
|
+
* apart: the customer can act on it (open the link where they asked for
|
|
6
|
+
* it, or request a new one here), and it is decided before the link is
|
|
7
|
+
* looked up, so it reveals nothing about the token. Unknown, used, expired
|
|
8
|
+
* and refused links share one answer, `null`.
|
|
9
|
+
*
|
|
10
|
+
* An `AuthenticationError`: a route that lets it escape answers 401 on any
|
|
11
|
+
* transport, with `not_this_browser` as the body's `error`, the way
|
|
12
|
+
* `TokenService.issue()` answers `mfa_required`.
|
|
13
|
+
*/
|
|
14
|
+
export declare class MagicLinkError extends AuthenticationError {
|
|
15
|
+
/** Why the link was refused: the only reason apps are told. */
|
|
16
|
+
readonly reason: 'not-this-browser';
|
|
17
|
+
constructor();
|
|
18
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AuthenticationError } from './authentication.error.js';
|
|
2
|
+
/**
|
|
3
|
+
* A link was presented in a browser other than the one that requested it
|
|
4
|
+
* (see `magicLink.bindToBrowser`). The one refusal `consume()` tells
|
|
5
|
+
* apart: the customer can act on it (open the link where they asked for
|
|
6
|
+
* it, or request a new one here), and it is decided before the link is
|
|
7
|
+
* looked up, so it reveals nothing about the token. Unknown, used, expired
|
|
8
|
+
* and refused links share one answer, `null`.
|
|
9
|
+
*
|
|
10
|
+
* An `AuthenticationError`: a route that lets it escape answers 401 on any
|
|
11
|
+
* transport, with `not_this_browser` as the body's `error`, the way
|
|
12
|
+
* `TokenService.issue()` answers `mfa_required`.
|
|
13
|
+
*/
|
|
14
|
+
export class MagicLinkError extends AuthenticationError {
|
|
15
|
+
constructor() {
|
|
16
|
+
super('Open the link in the browser you requested it from, or request a new one here', { code: 'not_this_browser' });
|
|
17
|
+
/** Why the link was refused: the only reason apps are told. */
|
|
18
|
+
this.reason = 'not-this-browser';
|
|
19
|
+
this.name = 'MagicLinkError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AuthenticationError } from './authentication.error.js';
|
|
2
|
+
/**
|
|
3
|
+
* Thrown by `MfaService.enroll()` when the user already has a confirmed
|
|
4
|
+
* authenticator and `replace` was not requested: overwriting it would turn
|
|
5
|
+
* the second factor off until the new one is confirmed. A route that lets
|
|
6
|
+
* it escape answers 409 on any transport. To replace an authenticator, call
|
|
7
|
+
* `enroll(…, { replace: true })` from a step-up route
|
|
8
|
+
* (`@Authenticate({ mfa: true })`), or `disable()` first.
|
|
9
|
+
*/
|
|
10
|
+
export declare class MfaAlreadyEnrolledError extends AuthenticationError {
|
|
11
|
+
readonly userId: string;
|
|
12
|
+
readonly status = 409;
|
|
13
|
+
constructor(userId: string);
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AuthenticationError } from './authentication.error.js';
|
|
2
|
+
/**
|
|
3
|
+
* Thrown by `MfaService.enroll()` when the user already has a confirmed
|
|
4
|
+
* authenticator and `replace` was not requested: overwriting it would turn
|
|
5
|
+
* the second factor off until the new one is confirmed. A route that lets
|
|
6
|
+
* it escape answers 409 on any transport. To replace an authenticator, call
|
|
7
|
+
* `enroll(…, { replace: true })` from a step-up route
|
|
8
|
+
* (`@Authenticate({ mfa: true })`), or `disable()` first.
|
|
9
|
+
*/
|
|
10
|
+
export class MfaAlreadyEnrolledError extends AuthenticationError {
|
|
11
|
+
constructor(userId) {
|
|
12
|
+
super('Authenticator already enrolled');
|
|
13
|
+
this.userId = userId;
|
|
14
|
+
this.status = 409;
|
|
15
|
+
this.name = 'MfaAlreadyEnrolledError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class OidcError extends Error {
|
|
2
|
+
/**
|
|
3
|
+
* `request`: bad or forged callback (400). `verification`: the IdP's
|
|
4
|
+
* answer failed checks (401). `unavailable`: the IdP is down or
|
|
5
|
+
* misconfigured (502), which is no fault of the user's.
|
|
6
|
+
*/
|
|
7
|
+
readonly kind: 'request' | 'verification' | 'unavailable';
|
|
8
|
+
constructor(message: string,
|
|
9
|
+
/**
|
|
10
|
+
* `request`: bad or forged callback (400). `verification`: the IdP's
|
|
11
|
+
* answer failed checks (401). `unavailable`: the IdP is down or
|
|
12
|
+
* misconfigured (502), which is no fault of the user's.
|
|
13
|
+
*/
|
|
14
|
+
kind: 'request' | 'verification' | 'unavailable');
|
|
15
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class OidcError extends Error {
|
|
2
|
+
constructor(message,
|
|
3
|
+
/**
|
|
4
|
+
* `request`: bad or forged callback (400). `verification`: the IdP's
|
|
5
|
+
* answer failed checks (401). `unavailable`: the IdP is down or
|
|
6
|
+
* misconfigured (502), which is no fault of the user's.
|
|
7
|
+
*/
|
|
8
|
+
kind) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.kind = kind;
|
|
11
|
+
this.name = 'OidcError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RefreshTokenFailure } from '../interfaces/refresh-token-options.interface.js';
|
|
2
|
+
import { AuthenticationError } from './authentication.error.js';
|
|
3
|
+
/**
|
|
4
|
+
* A refresh token was refused. An {@link AuthenticationError}, so a route
|
|
5
|
+
* that lets it escape answers 401 on any transport.
|
|
6
|
+
*/
|
|
7
|
+
export declare class RefreshTokenError extends AuthenticationError {
|
|
8
|
+
readonly reason: RefreshTokenFailure;
|
|
9
|
+
constructor(reason: RefreshTokenFailure);
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AuthenticationError } from './authentication.error.js';
|
|
2
|
+
/**
|
|
3
|
+
* A refresh token was refused. An {@link AuthenticationError}, so a route
|
|
4
|
+
* that lets it escape answers 401 on any transport.
|
|
5
|
+
*/
|
|
6
|
+
export class RefreshTokenError extends AuthenticationError {
|
|
7
|
+
constructor(reason) {
|
|
8
|
+
super(`Refresh token ${reason}`);
|
|
9
|
+
this.reason = reason;
|
|
10
|
+
this.name = 'RefreshTokenError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { MfaState } from '../interfaces/authentication-result.interface.js';
|
|
2
|
+
/**
|
|
3
|
+
* A first factor signed a user in: a cookie session (`SignInService`), or a
|
|
4
|
+
* refresh-token family for a token client (`TokenService.issue()`).
|
|
5
|
+
*/
|
|
6
|
+
export interface AuthenticationSignInEvent {
|
|
7
|
+
type: 'sign-in';
|
|
8
|
+
userId: string;
|
|
9
|
+
/** The new cookie session. */
|
|
10
|
+
sessionId?: string;
|
|
11
|
+
/** The new refresh-token family. */
|
|
12
|
+
tokenFamilyId?: string;
|
|
13
|
+
/** How the user proved who they are, when the caller said: `password`, `magic-link`, `oidc:google`. */
|
|
14
|
+
method?: string;
|
|
15
|
+
/**
|
|
16
|
+
* `pending` while the session still needs its second factor; `verified`
|
|
17
|
+
* for tokens issued with one (`TokenService.issue()`).
|
|
18
|
+
*/
|
|
19
|
+
mfa?: MfaState;
|
|
20
|
+
/** What the session stores next to the user (`session.metadata`). */
|
|
21
|
+
metadata?: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
/** A TOTP or recovery code was accepted, at sign-in or for a token client. */
|
|
24
|
+
export interface AuthenticationMfaVerifiedEvent {
|
|
25
|
+
type: 'mfa-verified';
|
|
26
|
+
userId: string;
|
|
27
|
+
method: 'totp' | 'recovery-code';
|
|
28
|
+
}
|
|
29
|
+
/** A code was refused. `locked` once the user reached `mfa.maxAttempts`. */
|
|
30
|
+
export interface AuthenticationMfaFailedEvent {
|
|
31
|
+
type: 'mfa-failed';
|
|
32
|
+
userId: string;
|
|
33
|
+
method: 'totp' | 'recovery-code';
|
|
34
|
+
/** Failures within `mfa.lockoutWindow`, this one included. */
|
|
35
|
+
failures: number;
|
|
36
|
+
locked: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** An authenticator was confirmed: a first one, or a replacement (`replaced`). */
|
|
39
|
+
export interface AuthenticationMfaEnabledEvent {
|
|
40
|
+
type: 'mfa-enabled';
|
|
41
|
+
userId: string;
|
|
42
|
+
replaced: boolean;
|
|
43
|
+
}
|
|
44
|
+
/** The authenticator and the recovery codes were removed. */
|
|
45
|
+
export interface AuthenticationMfaDisabledEvent {
|
|
46
|
+
type: 'mfa-disabled';
|
|
47
|
+
userId: string;
|
|
48
|
+
}
|
|
49
|
+
/** A new batch of recovery codes replaced the previous one. */
|
|
50
|
+
export interface AuthenticationRecoveryCodesGeneratedEvent {
|
|
51
|
+
type: 'recovery-codes-generated';
|
|
52
|
+
userId: string;
|
|
53
|
+
count: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* A spent refresh token came back, so two parties hold it: the family was
|
|
57
|
+
* revoked. A signal of token theft.
|
|
58
|
+
*/
|
|
59
|
+
export interface AuthenticationRefreshTokenReusedEvent {
|
|
60
|
+
type: 'refresh-token-reused';
|
|
61
|
+
userId: string;
|
|
62
|
+
tokenFamilyId: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A session or a token client was signed out: one session
|
|
66
|
+
* (`SignInService.signOut()`, `SessionService.revoke()`), one refresh-token
|
|
67
|
+
* family (`TokenService.revoke()`), or all of them (`everywhere`,
|
|
68
|
+
* `SignInService.signOutEverywhere()`).
|
|
69
|
+
*/
|
|
70
|
+
export interface AuthenticationSignOutEvent {
|
|
71
|
+
type: 'sign-out';
|
|
72
|
+
userId: string;
|
|
73
|
+
sessionId?: string;
|
|
74
|
+
tokenFamilyId?: string;
|
|
75
|
+
/** Every session and refresh-token family of the user. */
|
|
76
|
+
everywhere?: true;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Someone asked for a password reset link. `userId` is missing when no
|
|
80
|
+
* account has the address: nothing was sent. Many of those from one
|
|
81
|
+
* source is someone probing which addresses are registered.
|
|
82
|
+
*/
|
|
83
|
+
export interface AuthenticationPasswordResetRequestedEvent {
|
|
84
|
+
type: 'password-reset-requested';
|
|
85
|
+
/** Trimmed and lowercased. */
|
|
86
|
+
email: string;
|
|
87
|
+
userId?: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* A reset link set a new password. Every session and refresh-token family
|
|
91
|
+
* of the user was ended, and the address counts as verified.
|
|
92
|
+
*/
|
|
93
|
+
export interface AuthenticationPasswordResetEvent {
|
|
94
|
+
type: 'password-reset';
|
|
95
|
+
userId: string;
|
|
96
|
+
}
|
|
97
|
+
/** A verification link proved the user's address. */
|
|
98
|
+
export interface AuthenticationEmailVerifiedEvent {
|
|
99
|
+
type: 'email-verified';
|
|
100
|
+
userId: string;
|
|
101
|
+
email: string;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* A magic link came back and signed nobody in. `not-this-browser`: the
|
|
105
|
+
* browser holds no transaction cookie for this link (`MagicLinkService`
|
|
106
|
+
* sets one when the link is requested), so the link was opened somewhere
|
|
107
|
+
* else, on another device, or planted by whoever requested it (login CSRF);
|
|
108
|
+
* it stays usable where it was requested, and `consume()` threw a
|
|
109
|
+
* `MagicLinkError`. The others are its `null`: `unknown`: malformed, used,
|
|
110
|
+
* never issued, or presented with a cookie whose secret is not the link's.
|
|
111
|
+
* `expired`: past `magicLink.ttl`. `refused`:
|
|
112
|
+
* `MagicLinkHandler.resolveUser()` returned `null`, or an account whose
|
|
113
|
+
* stored address is not the one the link was sent to.
|
|
114
|
+
*/
|
|
115
|
+
export interface AuthenticationMagicLinkRefusedEvent {
|
|
116
|
+
type: 'magic-link-refused';
|
|
117
|
+
reason: 'not-this-browser' | 'unknown' | 'expired' | 'refused';
|
|
118
|
+
/** The address the link was sent to, once the link was looked up (`expired`, `refused`). */
|
|
119
|
+
email?: string;
|
|
120
|
+
}
|
|
121
|
+
export type AuthenticationEvent = AuthenticationSignInEvent | AuthenticationSignOutEvent | AuthenticationMfaVerifiedEvent | AuthenticationMfaFailedEvent | AuthenticationMfaEnabledEvent | AuthenticationMfaDisabledEvent | AuthenticationRecoveryCodesGeneratedEvent | AuthenticationRefreshTokenReusedEvent | AuthenticationPasswordResetRequestedEvent | AuthenticationPasswordResetEvent | AuthenticationEmailVerifiedEvent | AuthenticationMagicLinkRefusedEvent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type OnApplicationShutdown } from '@nestjs/common';
|
|
2
|
+
import { type Observable } from 'rxjs';
|
|
3
|
+
import type { AuthenticationEvent } from './authentication-events.interface.js';
|
|
4
|
+
/**
|
|
5
|
+
* The audit trail of sign-ins, sign-outs, second-factor changes, password
|
|
6
|
+
* resets, email verifications and refused magic links. Each event is also
|
|
7
|
+
* published on its `node:diagnostics_channel` channel
|
|
8
|
+
* (`nestjs:authentication:<type>`), for tooling that runs outside Nest.
|
|
9
|
+
* Listeners cannot change the outcome: a throwing channel subscriber is
|
|
10
|
+
* reported on the next tick, not in the sign-in that emitted.
|
|
11
|
+
*/
|
|
12
|
+
export declare class AuthenticationEvents implements OnApplicationShutdown {
|
|
13
|
+
private readonly subject;
|
|
14
|
+
/** Every event of this application, in order. */
|
|
15
|
+
readonly events$: Observable<AuthenticationEvent>;
|
|
16
|
+
/** @internal Called by the module's services. */
|
|
17
|
+
emit(event: AuthenticationEvent): void;
|
|
18
|
+
onApplicationShutdown(): void;
|
|
19
|
+
}
|