@awesome-lang-auth/node 1.10.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 +21 -0
- package/README.detailed.md +4059 -0
- package/README.md +248 -0
- package/dist/abstract/base-auth-strategy.abstract.d.ts +7 -0
- package/dist/abstract/base-auth-strategy.abstract.d.ts.map +1 -0
- package/dist/abstract/base-auth-strategy.abstract.js +7 -0
- package/dist/abstract/base-auth-strategy.abstract.js.map +1 -0
- package/dist/abstract/base-oauth-strategy.abstract.d.ts +27 -0
- package/dist/abstract/base-oauth-strategy.abstract.d.ts.map +1 -0
- package/dist/abstract/base-oauth-strategy.abstract.js +11 -0
- package/dist/abstract/base-oauth-strategy.abstract.js.map +1 -0
- package/dist/adapters/express.d.ts +45 -0
- package/dist/adapters/express.d.ts.map +1 -0
- package/dist/adapters/express.js +49 -0
- package/dist/adapters/express.js.map +1 -0
- package/dist/adapters/fastify.d.ts +72 -0
- package/dist/adapters/fastify.d.ts.map +1 -0
- package/dist/adapters/fastify.js +63 -0
- package/dist/adapters/fastify.js.map +1 -0
- package/dist/auth-configurator.d.ts +65 -0
- package/dist/auth-configurator.d.ts.map +1 -0
- package/dist/auth-configurator.js +127 -0
- package/dist/auth-configurator.js.map +1 -0
- package/dist/events/auth-event-bus.d.ts +68 -0
- package/dist/events/auth-event-bus.d.ts.map +1 -0
- package/dist/events/auth-event-bus.js +60 -0
- package/dist/events/auth-event-bus.js.map +1 -0
- package/dist/events/auth-event-names.d.ts +34 -0
- package/dist/events/auth-event-names.d.ts.map +1 -0
- package/dist/events/auth-event-names.js +41 -0
- package/dist/events/auth-event-names.js.map +1 -0
- package/dist/http-types.d.ts +135 -0
- package/dist/http-types.d.ts.map +1 -0
- package/dist/http-types.js +18 -0
- package/dist/http-types.js.map +1 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +88 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/api-key-store.interface.d.ts +94 -0
- package/dist/interfaces/api-key-store.interface.d.ts.map +1 -0
- package/dist/interfaces/api-key-store.interface.js +3 -0
- package/dist/interfaces/api-key-store.interface.js.map +1 -0
- package/dist/interfaces/auth-strategy.interface.d.ts +6 -0
- package/dist/interfaces/auth-strategy.interface.d.ts.map +1 -0
- package/dist/interfaces/auth-strategy.interface.js +3 -0
- package/dist/interfaces/auth-strategy.interface.js.map +1 -0
- package/dist/interfaces/linked-accounts-store.interface.d.ts +74 -0
- package/dist/interfaces/linked-accounts-store.interface.d.ts.map +1 -0
- package/dist/interfaces/linked-accounts-store.interface.js +3 -0
- package/dist/interfaces/linked-accounts-store.interface.js.map +1 -0
- package/dist/interfaces/pending-link-store.interface.d.ts +77 -0
- package/dist/interfaces/pending-link-store.interface.d.ts.map +1 -0
- package/dist/interfaces/pending-link-store.interface.js +3 -0
- package/dist/interfaces/pending-link-store.interface.js.map +1 -0
- package/dist/interfaces/roles-permissions-store.interface.d.ts +129 -0
- package/dist/interfaces/roles-permissions-store.interface.d.ts.map +1 -0
- package/dist/interfaces/roles-permissions-store.interface.js +3 -0
- package/dist/interfaces/roles-permissions-store.interface.js.map +1 -0
- package/dist/interfaces/session-store.interface.d.ts +92 -0
- package/dist/interfaces/session-store.interface.d.ts.map +1 -0
- package/dist/interfaces/session-store.interface.js +3 -0
- package/dist/interfaces/session-store.interface.js.map +1 -0
- package/dist/interfaces/settings-store.interface.d.ts +91 -0
- package/dist/interfaces/settings-store.interface.d.ts.map +1 -0
- package/dist/interfaces/settings-store.interface.js +3 -0
- package/dist/interfaces/settings-store.interface.js.map +1 -0
- package/dist/interfaces/sse-distributor.interface.d.ts +25 -0
- package/dist/interfaces/sse-distributor.interface.d.ts.map +1 -0
- package/dist/interfaces/sse-distributor.interface.js +3 -0
- package/dist/interfaces/sse-distributor.interface.js.map +1 -0
- package/dist/interfaces/telemetry-store.interface.d.ts +72 -0
- package/dist/interfaces/telemetry-store.interface.d.ts.map +1 -0
- package/dist/interfaces/telemetry-store.interface.js +3 -0
- package/dist/interfaces/telemetry-store.interface.js.map +1 -0
- package/dist/interfaces/template-store.interface.d.ts +37 -0
- package/dist/interfaces/template-store.interface.d.ts.map +1 -0
- package/dist/interfaces/template-store.interface.js +3 -0
- package/dist/interfaces/template-store.interface.js.map +1 -0
- package/dist/interfaces/tenant-store.interface.d.ts +97 -0
- package/dist/interfaces/tenant-store.interface.d.ts.map +1 -0
- package/dist/interfaces/tenant-store.interface.js +3 -0
- package/dist/interfaces/tenant-store.interface.js.map +1 -0
- package/dist/interfaces/token-store.interface.d.ts +10 -0
- package/dist/interfaces/token-store.interface.d.ts.map +1 -0
- package/dist/interfaces/token-store.interface.js +3 -0
- package/dist/interfaces/token-store.interface.js.map +1 -0
- package/dist/interfaces/user-metadata-store.interface.d.ts +50 -0
- package/dist/interfaces/user-metadata-store.interface.d.ts.map +1 -0
- package/dist/interfaces/user-metadata-store.interface.js +3 -0
- package/dist/interfaces/user-metadata-store.interface.js.map +1 -0
- package/dist/interfaces/user-store.interface.d.ts +113 -0
- package/dist/interfaces/user-store.interface.d.ts.map +1 -0
- package/dist/interfaces/user-store.interface.js +3 -0
- package/dist/interfaces/user-store.interface.js.map +1 -0
- package/dist/interfaces/webhook-store.interface.d.ts +139 -0
- package/dist/interfaces/webhook-store.interface.d.ts.map +1 -0
- package/dist/interfaces/webhook-store.interface.js +3 -0
- package/dist/interfaces/webhook-store.interface.js.map +1 -0
- package/dist/middleware/api-key.middleware.d.ts +35 -0
- package/dist/middleware/api-key.middleware.d.ts.map +1 -0
- package/dist/middleware/api-key.middleware.js +45 -0
- package/dist/middleware/api-key.middleware.js.map +1 -0
- package/dist/middleware/auth.middleware.d.ts +13 -0
- package/dist/middleware/auth.middleware.d.ts.map +1 -0
- package/dist/middleware/auth.middleware.js +55 -0
- package/dist/middleware/auth.middleware.js.map +1 -0
- package/dist/middleware/jwks-auth.middleware.d.ts +18 -0
- package/dist/middleware/jwks-auth.middleware.d.ts.map +1 -0
- package/dist/middleware/jwks-auth.middleware.js +77 -0
- package/dist/middleware/jwks-auth.middleware.js.map +1 -0
- package/dist/models/api-key.model.d.ts +66 -0
- package/dist/models/api-key.model.d.ts.map +1 -0
- package/dist/models/api-key.model.js +3 -0
- package/dist/models/api-key.model.js.map +1 -0
- package/dist/models/auth-config.model.d.ts +387 -0
- package/dist/models/auth-config.model.d.ts.map +1 -0
- package/dist/models/auth-config.model.js +3 -0
- package/dist/models/auth-config.model.js.map +1 -0
- package/dist/models/errors.d.ts +7 -0
- package/dist/models/errors.d.ts.map +1 -0
- package/dist/models/errors.js +14 -0
- package/dist/models/errors.js.map +1 -0
- package/dist/models/session.model.d.ts +28 -0
- package/dist/models/session.model.d.ts.map +1 -0
- package/dist/models/session.model.js +3 -0
- package/dist/models/session.model.js.map +1 -0
- package/dist/models/tenant.model.d.ts +20 -0
- package/dist/models/tenant.model.d.ts.map +1 -0
- package/dist/models/tenant.model.js +3 -0
- package/dist/models/tenant.model.js.map +1 -0
- package/dist/models/token.model.d.ts +21 -0
- package/dist/models/token.model.d.ts.map +1 -0
- package/dist/models/token.model.js +3 -0
- package/dist/models/token.model.js.map +1 -0
- package/dist/models/user.model.d.ts +92 -0
- package/dist/models/user.model.d.ts.map +1 -0
- package/dist/models/user.model.js +3 -0
- package/dist/models/user.model.js.map +1 -0
- package/dist/router/admin.router.d.ts +188 -0
- package/dist/router/admin.router.d.ts.map +1 -0
- package/dist/router/admin.router.js +1507 -0
- package/dist/router/admin.router.js.map +1 -0
- package/dist/router/auth.router.d.ts +199 -0
- package/dist/router/auth.router.d.ts.map +1 -0
- package/dist/router/auth.router.js +1636 -0
- package/dist/router/auth.router.js.map +1 -0
- package/dist/router/openapi.d.ts +98 -0
- package/dist/router/openapi.d.ts.map +1 -0
- package/dist/router/openapi.js +1518 -0
- package/dist/router/openapi.js.map +1 -0
- package/dist/router/router-events.d.ts +38 -0
- package/dist/router/router-events.d.ts.map +1 -0
- package/dist/router/router-events.js +74 -0
- package/dist/router/router-events.js.map +1 -0
- package/dist/router/tools.router.d.ts +104 -0
- package/dist/router/tools.router.d.ts.map +1 -0
- package/dist/router/tools.router.js +227 -0
- package/dist/router/tools.router.js.map +1 -0
- package/dist/router/ui.router.d.ts +49 -0
- package/dist/router/ui.router.d.ts.map +1 -0
- package/dist/router/ui.router.js +272 -0
- package/dist/router/ui.router.js.map +1 -0
- package/dist/services/api-key.service.d.ts +53 -0
- package/dist/services/api-key.service.d.ts.map +1 -0
- package/dist/services/api-key.service.js +66 -0
- package/dist/services/api-key.service.js.map +1 -0
- package/dist/services/jwks.service.d.ts +73 -0
- package/dist/services/jwks.service.d.ts.map +1 -0
- package/dist/services/jwks.service.js +174 -0
- package/dist/services/jwks.service.js.map +1 -0
- package/dist/services/mailer.service.d.ts +30 -0
- package/dist/services/mailer.service.d.ts.map +1 -0
- package/dist/services/mailer.service.js +248 -0
- package/dist/services/mailer.service.js.map +1 -0
- package/dist/services/notification.service.d.ts +110 -0
- package/dist/services/notification.service.d.ts.map +1 -0
- package/dist/services/notification.service.js +79 -0
- package/dist/services/notification.service.js.map +1 -0
- package/dist/services/password.service.d.ts +5 -0
- package/dist/services/password.service.d.ts.map +1 -0
- package/dist/services/password.service.js +17 -0
- package/dist/services/password.service.js.map +1 -0
- package/dist/services/sms.service.d.ts +14 -0
- package/dist/services/sms.service.d.ts.map +1 -0
- package/dist/services/sms.service.js +51 -0
- package/dist/services/sms.service.js.map +1 -0
- package/dist/services/token.service.d.ts +62 -0
- package/dist/services/token.service.d.ts.map +1 -0
- package/dist/services/token.service.js +354 -0
- package/dist/services/token.service.js.map +1 -0
- package/dist/stores/memory-template.store.d.ts +12 -0
- package/dist/stores/memory-template.store.d.ts.map +1 -0
- package/dist/stores/memory-template.store.js +35 -0
- package/dist/stores/memory-template.store.js.map +1 -0
- package/dist/strategies/api-key/api-key.strategy.d.ts +72 -0
- package/dist/strategies/api-key/api-key.strategy.d.ts.map +1 -0
- package/dist/strategies/api-key/api-key.strategy.js +182 -0
- package/dist/strategies/api-key/api-key.strategy.js.map +1 -0
- package/dist/strategies/local/local.strategy.d.ts +19 -0
- package/dist/strategies/local/local.strategy.d.ts.map +1 -0
- package/dist/strategies/local/local.strategy.js +45 -0
- package/dist/strategies/local/local.strategy.js.map +1 -0
- package/dist/strategies/magic-link/magic-link.strategy.d.ts +8 -0
- package/dist/strategies/magic-link/magic-link.strategy.d.ts.map +1 -0
- package/dist/strategies/magic-link/magic-link.strategy.js +53 -0
- package/dist/strategies/magic-link/magic-link.strategy.js.map +1 -0
- package/dist/strategies/oauth/generic-oauth.strategy.d.ts +120 -0
- package/dist/strategies/oauth/generic-oauth.strategy.d.ts.map +1 -0
- package/dist/strategies/oauth/generic-oauth.strategy.js +88 -0
- package/dist/strategies/oauth/generic-oauth.strategy.js.map +1 -0
- package/dist/strategies/oauth/github.strategy.d.ts +31 -0
- package/dist/strategies/oauth/github.strategy.d.ts.map +1 -0
- package/dist/strategies/oauth/github.strategy.js +72 -0
- package/dist/strategies/oauth/github.strategy.js.map +1 -0
- package/dist/strategies/oauth/google.strategy.d.ts +31 -0
- package/dist/strategies/oauth/google.strategy.d.ts.map +1 -0
- package/dist/strategies/oauth/google.strategy.js +61 -0
- package/dist/strategies/oauth/google.strategy.js.map +1 -0
- package/dist/strategies/sms/sms.strategy.d.ts +7 -0
- package/dist/strategies/sms/sms.strategy.d.ts.map +1 -0
- package/dist/strategies/sms/sms.strategy.js +39 -0
- package/dist/strategies/sms/sms.strategy.js.map +1 -0
- package/dist/strategies/two-factor/totp.strategy.d.ts +12 -0
- package/dist/strategies/two-factor/totp.strategy.d.ts.map +1 -0
- package/dist/strategies/two-factor/totp.strategy.js +32 -0
- package/dist/strategies/two-factor/totp.strategy.js.map +1 -0
- package/dist/tools/auth-tools.d.ts +200 -0
- package/dist/tools/auth-tools.d.ts.map +1 -0
- package/dist/tools/auth-tools.js +232 -0
- package/dist/tools/auth-tools.js.map +1 -0
- package/dist/tools/sse-manager.d.ts +118 -0
- package/dist/tools/sse-manager.d.ts.map +1 -0
- package/dist/tools/sse-manager.js +163 -0
- package/dist/tools/sse-manager.js.map +1 -0
- package/dist/tools/sse-notify.decorator.d.ts +74 -0
- package/dist/tools/sse-notify.decorator.d.ts.map +1 -0
- package/dist/tools/sse-notify.decorator.js +78 -0
- package/dist/tools/sse-notify.decorator.js.map +1 -0
- package/dist/tools/webhook-action.d.ts +130 -0
- package/dist/tools/webhook-action.d.ts.map +1 -0
- package/dist/tools/webhook-action.js +144 -0
- package/dist/tools/webhook-action.js.map +1 -0
- package/dist/tools/webhook-sender.d.ts +31 -0
- package/dist/tools/webhook-sender.d.ts.map +1 -0
- package/dist/tools/webhook-sender.js +80 -0
- package/dist/tools/webhook-sender.js.map +1 -0
- package/dist/ui-assets/2fa.html +115 -0
- package/dist/ui-assets/account-conflict.html +108 -0
- package/dist/ui-assets/admin.css +263 -0
- package/dist/ui-assets/admin.js +1927 -0
- package/dist/ui-assets/auth.js +725 -0
- package/dist/ui-assets/base.css +219 -0
- package/dist/ui-assets/forgot-password.html +93 -0
- package/dist/ui-assets/link-verify.html +74 -0
- package/dist/ui-assets/login.html +135 -0
- package/dist/ui-assets/magic-link.html +112 -0
- package/dist/ui-assets/register.html +122 -0
- package/dist/ui-assets/reset-password.html +103 -0
- package/dist/ui-assets/ui-i18n-keys.json +78 -0
- package/dist/ui-assets/verify-email.html +66 -0
- package/package.json +89 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Notification service for awesome-node-auth.
|
|
4
|
+
*
|
|
5
|
+
* Provides a thin, transport-agnostic wrapper around the built-in
|
|
6
|
+
* `MailerService` and `SmsService` so that business-level notifications
|
|
7
|
+
* (e.g. "your subscription will expire in 3 days") can be sent over the same
|
|
8
|
+
* transports that are already configured for authentication flows — without
|
|
9
|
+
* passing the entire `AuthConfig` to `AuthTools`.
|
|
10
|
+
*
|
|
11
|
+
* @since 1.8.0
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.NotificationService = void 0;
|
|
15
|
+
const mailer_service_1 = require("./mailer.service");
|
|
16
|
+
const sms_service_1 = require("./sms.service");
|
|
17
|
+
/**
|
|
18
|
+
* A thin facade that exposes email and SMS sending without requiring the
|
|
19
|
+
* entire `AuthConfig`. Intended for use with `AuthTools.notify()` when
|
|
20
|
+
* email or SMS channels are requested.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { NotificationService } from '@awesome-lang-auth/node';
|
|
25
|
+
*
|
|
26
|
+
* const notifications = new NotificationService({
|
|
27
|
+
* email: { endpoint: process.env.MAILER_ENDPOINT!, apiKey: process.env.MAILER_KEY!, from: 'no-reply@example.com' },
|
|
28
|
+
* sms: { endpoint: process.env.SMS_ENDPOINT!, apiKey: process.env.SMS_KEY!, username: '...', password: '...' },
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* await notifications.sendEmail({
|
|
32
|
+
* to: 'alice@example.com',
|
|
33
|
+
* subject: 'Subscription expiring',
|
|
34
|
+
* html: '<p>Your subscription expires in 3 days.</p>',
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @since 1.8.0
|
|
39
|
+
*/
|
|
40
|
+
class NotificationService {
|
|
41
|
+
constructor(opts = {}) {
|
|
42
|
+
if (opts.email)
|
|
43
|
+
this.mailer = new mailer_service_1.MailerService(opts.email);
|
|
44
|
+
if (opts.sms)
|
|
45
|
+
this.sms = new sms_service_1.SmsService(opts.sms);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Send a custom email notification.
|
|
49
|
+
*
|
|
50
|
+
* Throws if no email transport is configured.
|
|
51
|
+
*
|
|
52
|
+
* @since 1.8.0
|
|
53
|
+
*/
|
|
54
|
+
async sendEmail(opts) {
|
|
55
|
+
if (!this.mailer) {
|
|
56
|
+
throw new Error('[NotificationService] No email transport configured. Pass `email` config to the constructor.');
|
|
57
|
+
}
|
|
58
|
+
await this.mailer.sendCustom(opts.to, opts.subject, opts.html, opts.text);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Send a custom SMS notification.
|
|
62
|
+
*
|
|
63
|
+
* Throws if no SMS transport is configured.
|
|
64
|
+
*
|
|
65
|
+
* @since 1.8.0
|
|
66
|
+
*/
|
|
67
|
+
async sendSms(opts) {
|
|
68
|
+
if (!this.sms) {
|
|
69
|
+
throw new Error('[NotificationService] No SMS transport configured. Pass `sms` config to the constructor.');
|
|
70
|
+
}
|
|
71
|
+
await this.sms.sendSms(opts.to, opts.message);
|
|
72
|
+
}
|
|
73
|
+
/** `true` when an email transport is configured. */
|
|
74
|
+
get hasEmail() { return !!this.mailer; }
|
|
75
|
+
/** `true` when an SMS transport is configured. */
|
|
76
|
+
get hasSms() { return !!this.sms; }
|
|
77
|
+
}
|
|
78
|
+
exports.NotificationService = NotificationService;
|
|
79
|
+
//# sourceMappingURL=notification.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification.service.js","sourceRoot":"","sources":["../../src/services/notification.service.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAEH,qDAAiD;AACjD,+CAA2C;AAsD3C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAa,mBAAmB;IAI9B,YAAY,OAGR,EAAE;QACJ,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,MAAM,GAAG,IAAI,8BAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAI,IAAI,CAAC,GAAG;YAAI,IAAI,CAAC,GAAG,GAAK,IAAI,wBAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxD,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,SAAS,CAAC,IAAsB;QACpC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,8FAA8F,CAAC,CAAC;QAClH,CAAC;QACD,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5E,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CAAC,IAAoB;QAChC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,0FAA0F,CAAC,CAAC;QAC9G,CAAC;QACD,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,oDAAoD;IACpD,IAAI,QAAQ,KAAc,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,kDAAkD;IAClD,IAAI,MAAM,KAAc,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;CAC7C;AA5CD,kDA4CC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.service.d.ts","sourceRoot":"","sources":["../../src/services/password.service.ts"],"names":[],"mappings":"AAEA,qBAAa,eAAe;IACpB,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAE,MAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAIhE,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAGhE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PasswordService = void 0;
|
|
7
|
+
const bcryptjs_1 = __importDefault(require("bcryptjs"));
|
|
8
|
+
class PasswordService {
|
|
9
|
+
async hash(password, saltRounds = 12) {
|
|
10
|
+
return bcryptjs_1.default.hash(password, saltRounds);
|
|
11
|
+
}
|
|
12
|
+
async compare(password, hash) {
|
|
13
|
+
return bcryptjs_1.default.compare(password, hash);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.PasswordService = PasswordService;
|
|
17
|
+
//# sourceMappingURL=password.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.service.js","sourceRoot":"","sources":["../../src/services/password.service.ts"],"names":[],"mappings":";;;;;;AAAA,wDAA8B;AAE9B,MAAa,eAAe;IAC1B,KAAK,CAAC,IAAI,CAAC,QAAgB,EAAE,aAAqB,EAAE;QAClD,OAAO,kBAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB,EAAE,IAAY;QAC1C,OAAO,kBAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACxC,CAAC;CACF;AARD,0CAQC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface SmsConfig {
|
|
2
|
+
endpoint: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
username: string;
|
|
5
|
+
password: string;
|
|
6
|
+
codeExpiresInMinutes?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class SmsService {
|
|
9
|
+
private readonly config;
|
|
10
|
+
constructor(config: SmsConfig);
|
|
11
|
+
sendSms(phone: string, message: string): Promise<void>;
|
|
12
|
+
generateCode(digits?: number): string;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=sms.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sms.service.d.ts","sourceRoot":"","sources":["../../src/services/sms.service.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS;IAE9C,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCtD,YAAY,CAAC,MAAM,GAAE,MAAU,GAAG,MAAM;CAKzC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SmsService = void 0;
|
|
7
|
+
const https_1 = __importDefault(require("https"));
|
|
8
|
+
const http_1 = __importDefault(require("http"));
|
|
9
|
+
const url_1 = require("url");
|
|
10
|
+
class SmsService {
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
}
|
|
14
|
+
sendSms(phone, message) {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const url = new url_1.URL(this.config.endpoint);
|
|
17
|
+
url.searchParams.set('username', this.config.username);
|
|
18
|
+
url.searchParams.set('password', this.config.password);
|
|
19
|
+
url.searchParams.set('phone', phone);
|
|
20
|
+
url.searchParams.set('message', message);
|
|
21
|
+
const options = {
|
|
22
|
+
hostname: url.hostname,
|
|
23
|
+
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
24
|
+
path: `${url.pathname}?${url.searchParams.toString()}`,
|
|
25
|
+
method: 'GET',
|
|
26
|
+
headers: {
|
|
27
|
+
'X-API-Key': this.config.apiKey,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
const transport = url.protocol === 'https:' ? https_1.default : http_1.default;
|
|
31
|
+
const req = transport.request(options, (res) => {
|
|
32
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
33
|
+
resolve();
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
reject(new Error(`SMS send failed with status ${res.statusCode}`));
|
|
37
|
+
}
|
|
38
|
+
res.resume();
|
|
39
|
+
});
|
|
40
|
+
req.on('error', reject);
|
|
41
|
+
req.end();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
generateCode(digits = 6) {
|
|
45
|
+
const max = Math.pow(10, digits);
|
|
46
|
+
const min = Math.pow(10, digits - 1);
|
|
47
|
+
return String(Math.floor(min + Math.random() * (max - min)));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.SmsService = SmsService;
|
|
51
|
+
//# sourceMappingURL=sms.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sms.service.js","sourceRoot":"","sources":["../../src/services/sms.service.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,gDAAwB;AACxB,6BAA0B;AAU1B,MAAa,UAAU;IACrB,YAA6B,MAAiB;QAAjB,WAAM,GAAN,MAAM,CAAW;IAAG,CAAC;IAElD,OAAO,CAAC,KAAa,EAAE,OAAe;QACpC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,GAAG,GAAG,IAAI,SAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC1C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACvD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACvD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACrC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAEzC,MAAM,OAAO,GAAG;gBACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxD,IAAI,EAAE,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE;gBACtD,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;iBAChC;aACF,CAAC;YAEF,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAK,CAAC,CAAC,CAAC,cAAI,CAAC;YAC3D,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBAC7C,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;oBACpE,OAAO,EAAE,CAAC;gBACZ,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,KAAK,CAAC,+BAA+B,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBACrE,CAAC;gBACD,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACxB,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,YAAY,CAAC,SAAiB,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;QACrC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC;CACF;AAxCD,gCAwCC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import { AccessTokenPayload, TokenPair } from '../models/token.model';
|
|
3
|
+
import { AuthConfig } from '../models/auth-config.model';
|
|
4
|
+
import { JwksClient } from './jwks.service';
|
|
5
|
+
/**
|
|
6
|
+
* Claim that marks a token signed with the access-token secret which is **not**
|
|
7
|
+
* an application session token. Session (access) tokens carry no `purpose`.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare const TOKEN_PURPOSE_CLAIM = "purpose";
|
|
11
|
+
/** `purpose` of the 2FA step-up token (`tempToken`) issued after a password. @internal */
|
|
12
|
+
export declare const TEMP_TOKEN_PURPOSE = "2fa";
|
|
13
|
+
/** `purpose` of the admin console token issued by `POST <admin>/login`. @internal */
|
|
14
|
+
export declare const ADMIN_TOKEN_PURPOSE = "admin";
|
|
15
|
+
/** Reset ephemeral-warning flag. Exported for testing only. */
|
|
16
|
+
export declare function _resetEphemeralWarning(): void;
|
|
17
|
+
export declare class TokenService {
|
|
18
|
+
generateTokenPair(payload: AccessTokenPayload, config: AuthConfig): TokenPair;
|
|
19
|
+
/**
|
|
20
|
+
* Generate an RS256-signed token pair for IdP mode.
|
|
21
|
+
*
|
|
22
|
+
* IdP mode activates when `config.idProvider.privateKey` is present **or**
|
|
23
|
+
* `config.idProvider.enabled === true`. A keypair is auto-generated at the
|
|
24
|
+
* first call if no `privateKey` is configured (for dev; emits a warning).
|
|
25
|
+
*/
|
|
26
|
+
generateIdProviderTokenPair(payload: AccessTokenPayload, config: AuthConfig): TokenPair;
|
|
27
|
+
/**
|
|
28
|
+
* Verify a JWT against a remote JWKS endpoint.
|
|
29
|
+
* The `kid` header claim is used to select the correct public key.
|
|
30
|
+
*/
|
|
31
|
+
verifyWithJwks(token: string, jwksClient: JwksClient, expectedIssuer?: string): Promise<AccessTokenPayload>;
|
|
32
|
+
private _verifyRsaToken;
|
|
33
|
+
/**
|
|
34
|
+
* Sign the short-lived 2FA step-up token (`tempToken`) handed out after a
|
|
35
|
+
* correct password when a second factor is required. It carries
|
|
36
|
+
* `purpose: '2fa'`, set after the payload claims so a custom claim cannot
|
|
37
|
+
* remove it: `verifyAccessToken` refuses it, and only `verifyTempToken`
|
|
38
|
+
* (the 2FA completion endpoints) accepts it.
|
|
39
|
+
*/
|
|
40
|
+
generateTempToken(payload: AccessTokenPayload, config: AuthConfig): string;
|
|
41
|
+
/**
|
|
42
|
+
* Verify a 2FA step-up token. Only a token minted by `generateTempToken`
|
|
43
|
+
* passes: an application access token is refused. Throws the same
|
|
44
|
+
* `INVALID_ACCESS_TOKEN` error as `verifyAccessToken`.
|
|
45
|
+
*/
|
|
46
|
+
verifyTempToken(token: string, config: AuthConfig): AccessTokenPayload;
|
|
47
|
+
/**
|
|
48
|
+
* Verify an application session (access) token. A token signed with the
|
|
49
|
+
* same secret for another purpose is refused: the 2FA step-up token, and
|
|
50
|
+
* the admin console token (when the admin `jwtSecret` is the access-token
|
|
51
|
+
* secret, as `buildAllRouters()` sets it by default).
|
|
52
|
+
*/
|
|
53
|
+
verifyAccessToken(token: string, config: AuthConfig): AccessTokenPayload;
|
|
54
|
+
verifyRefreshToken(token: string, config: AuthConfig): AccessTokenPayload;
|
|
55
|
+
private getCookieName;
|
|
56
|
+
setTokenCookies(res: Response, tokens: TokenPair, config: AuthConfig): void;
|
|
57
|
+
initCsrfToken(res: Response, config: AuthConfig): void;
|
|
58
|
+
clearTokenCookies(res: Response, config?: AuthConfig): void;
|
|
59
|
+
generateSecureToken(bytes?: number): string;
|
|
60
|
+
extractTokenFromCookie(req: Request, cookieName: string): string | null;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=token.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.service.d.ts","sourceRoot":"","sources":["../../src/services/token.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAe,MAAM,gBAAgB,CAAC;AAIzD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAC7C,0FAA0F;AAC1F,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AACxC,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,UAAU,CAAC;AA8B3C,+DAA+D;AAC/D,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAED,qBAAa,YAAY;IACvB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS;IAmB7E;;;;;;OAMG;IACH,2BAA2B,CAAC,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS;IA0DvF;;;OAGG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAiCjH,OAAO,CAAC,eAAe;IAQvB;;;;;;OAMG;IACH,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM;IAS1E;;;;OAIG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,kBAAkB;IAWtE;;;;;OAKG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,kBAAkB;IAYxE,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,kBAAkB;IASzE,OAAO,CAAC,aAAa;IAarB,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IA0C3E,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAoBtD,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI;IAsC3D,mBAAmB,CAAC,KAAK,GAAE,MAAW,GAAG,MAAM;IAI/C,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CA6BxE"}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TokenService = exports.ADMIN_TOKEN_PURPOSE = exports.TEMP_TOKEN_PURPOSE = exports.TOKEN_PURPOSE_CLAIM = void 0;
|
|
7
|
+
exports._resetEphemeralWarning = _resetEphemeralWarning;
|
|
8
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
9
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
10
|
+
const errors_1 = require("../models/errors");
|
|
11
|
+
const jwks_service_1 = require("./jwks.service");
|
|
12
|
+
let ephemeralWarningEmitted = false;
|
|
13
|
+
/**
|
|
14
|
+
* Claim that marks a token signed with the access-token secret which is **not**
|
|
15
|
+
* an application session token. Session (access) tokens carry no `purpose`.
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
exports.TOKEN_PURPOSE_CLAIM = 'purpose';
|
|
19
|
+
/** `purpose` of the 2FA step-up token (`tempToken`) issued after a password. @internal */
|
|
20
|
+
exports.TEMP_TOKEN_PURPOSE = '2fa';
|
|
21
|
+
/** `purpose` of the admin console token issued by `POST <admin>/login`. @internal */
|
|
22
|
+
exports.ADMIN_TOKEN_PURPOSE = 'admin';
|
|
23
|
+
/** Lifetime of the 2FA step-up token. */
|
|
24
|
+
const TEMP_TOKEN_EXPIRES_IN = '5m';
|
|
25
|
+
function invalidAccessToken() {
|
|
26
|
+
return new errors_1.AuthError('Invalid or expired access token', 'INVALID_ACCESS_TOKEN', 401);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Lifetime of a signed JWT in milliseconds (`exp - iat`), or `undefined` when
|
|
30
|
+
* the token has no usable `iat`/`exp`. The tokens are signed with the
|
|
31
|
+
* configured `accessTokenExpiresIn` / `refreshTokenExpiresIn`, parsed by
|
|
32
|
+
* jsonwebtoken itself, so this is the configured lifetime in every format
|
|
33
|
+
* jsonwebtoken accepts.
|
|
34
|
+
*/
|
|
35
|
+
function tokenLifetimeMs(token) {
|
|
36
|
+
const decoded = jsonwebtoken_1.default.decode(token);
|
|
37
|
+
if (decoded && typeof decoded === 'object'
|
|
38
|
+
&& typeof decoded.iat === 'number' && typeof decoded.exp === 'number'
|
|
39
|
+
&& decoded.exp > decoded.iat) {
|
|
40
|
+
return (decoded.exp - decoded.iat) * 1000;
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
/** Cookie lifetimes used when a token carries no `iat`/`exp` (the 1.9.0 values). */
|
|
45
|
+
const DEFAULT_ACCESS_COOKIE_MAX_AGE_MS = 15 * 60 * 1000;
|
|
46
|
+
const DEFAULT_REFRESH_COOKIE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
47
|
+
/** Reset ephemeral-warning flag. Exported for testing only. */
|
|
48
|
+
function _resetEphemeralWarning() {
|
|
49
|
+
ephemeralWarningEmitted = false;
|
|
50
|
+
}
|
|
51
|
+
class TokenService {
|
|
52
|
+
generateTokenPair(payload, config) {
|
|
53
|
+
// Exclude jwt-managed fields; spread remaining claims (including any custom ones).
|
|
54
|
+
// `purpose` is reserved for tokens that are not sessions (the 2FA step-up
|
|
55
|
+
// token, the admin console token): drop it, so a custom claim from
|
|
56
|
+
// `buildTokenPayload` can never mark a session token as one of them.
|
|
57
|
+
const { iat, exp, [exports.TOKEN_PURPOSE_CLAIM]: _purpose, ...claims } = payload;
|
|
58
|
+
const accessToken = jsonwebtoken_1.default.sign(claims, config.accessTokenSecret, { expiresIn: config.accessTokenExpiresIn ?? '15m' });
|
|
59
|
+
const refreshToken = jsonwebtoken_1.default.sign(claims, config.refreshTokenSecret, { expiresIn: config.refreshTokenExpiresIn ?? '7d' });
|
|
60
|
+
return { accessToken, refreshToken };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Generate an RS256-signed token pair for IdP mode.
|
|
64
|
+
*
|
|
65
|
+
* IdP mode activates when `config.idProvider.privateKey` is present **or**
|
|
66
|
+
* `config.idProvider.enabled === true`. A keypair is auto-generated at the
|
|
67
|
+
* first call if no `privateKey` is configured (for dev; emits a warning).
|
|
68
|
+
*/
|
|
69
|
+
generateIdProviderTokenPair(payload, config) {
|
|
70
|
+
const idp = config.idProvider;
|
|
71
|
+
const isActive = !!idp?.privateKey || idp?.enabled === true;
|
|
72
|
+
if (!isActive) {
|
|
73
|
+
throw new errors_1.AuthError('IdP mode is not enabled', 'IDP_NOT_ENABLED', 500);
|
|
74
|
+
}
|
|
75
|
+
let privateKeyPem = idp.privateKey;
|
|
76
|
+
let publicKeyPem = idp.publicKey;
|
|
77
|
+
if (!privateKeyPem) {
|
|
78
|
+
if (!ephemeralWarningEmitted) {
|
|
79
|
+
console.warn('[awesome-node-auth] IdP mode: no privateKey configured — ' +
|
|
80
|
+
'auto-generating an ephemeral RSA keypair. ' +
|
|
81
|
+
'All tokens will be invalidated on restart. ' +
|
|
82
|
+
'Set idProvider.privateKey in production.');
|
|
83
|
+
ephemeralWarningEmitted = true;
|
|
84
|
+
}
|
|
85
|
+
// Auto-generate ephemeral keypair (dev only)
|
|
86
|
+
const kp = jwks_service_1.JwksService.generateKeypair();
|
|
87
|
+
privateKeyPem = kp.privateKey;
|
|
88
|
+
publicKeyPem = kp.publicKey;
|
|
89
|
+
// Persist into the config object so subsequent calls reuse the same keypair
|
|
90
|
+
idp.privateKey = privateKeyPem;
|
|
91
|
+
idp.publicKey = publicKeyPem;
|
|
92
|
+
}
|
|
93
|
+
else if (!publicKeyPem) {
|
|
94
|
+
publicKeyPem = jwks_service_1.JwksService.derivePublicKey(privateKeyPem);
|
|
95
|
+
idp.publicKey = publicKeyPem;
|
|
96
|
+
}
|
|
97
|
+
// `iat`, `exp` and `kid` are managed by jsonwebtoken (header claim, not payload)
|
|
98
|
+
const { iat, exp, kid: _kid, ...claims } = payload;
|
|
99
|
+
const idpClaims = {
|
|
100
|
+
...claims,
|
|
101
|
+
...(idp.issuer ? { iss: idp.issuer } : {}),
|
|
102
|
+
};
|
|
103
|
+
const keyId = 'provisioner-key-1';
|
|
104
|
+
const expiresIn = (idp.tokenExpiry ?? '30d');
|
|
105
|
+
const accessToken = jsonwebtoken_1.default.sign(idpClaims, privateKeyPem, {
|
|
106
|
+
algorithm: 'RS256',
|
|
107
|
+
expiresIn,
|
|
108
|
+
keyid: keyId,
|
|
109
|
+
});
|
|
110
|
+
// Refresh token also RS256-signed, with a longer expiry.
|
|
111
|
+
// Priority: idProvider.refreshTokenExpiry → config.refreshTokenExpiresIn → '90d'
|
|
112
|
+
const refreshToken = jsonwebtoken_1.default.sign(idpClaims, privateKeyPem, {
|
|
113
|
+
algorithm: 'RS256',
|
|
114
|
+
expiresIn: (idp.refreshTokenExpiry ?? config.refreshTokenExpiresIn ?? '90d'),
|
|
115
|
+
keyid: keyId,
|
|
116
|
+
});
|
|
117
|
+
return { accessToken, refreshToken };
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Verify a JWT against a remote JWKS endpoint.
|
|
121
|
+
* The `kid` header claim is used to select the correct public key.
|
|
122
|
+
*/
|
|
123
|
+
async verifyWithJwks(token, jwksClient, expectedIssuer) {
|
|
124
|
+
try {
|
|
125
|
+
// Decode without verifying to extract `kid`
|
|
126
|
+
const decoded = jsonwebtoken_1.default.decode(token, { complete: true });
|
|
127
|
+
if (!decoded || typeof decoded === 'string') {
|
|
128
|
+
throw new errors_1.AuthError('Invalid token format', 'INVALID_TOKEN', 401);
|
|
129
|
+
}
|
|
130
|
+
const kid = decoded.header.kid;
|
|
131
|
+
if (!kid) {
|
|
132
|
+
throw new errors_1.AuthError('Token missing kid header', 'INVALID_TOKEN', 401);
|
|
133
|
+
}
|
|
134
|
+
const jwk = await jwksClient.getKey(kid);
|
|
135
|
+
if (!jwk) {
|
|
136
|
+
// Key not found — try once more after cache invalidation (supports key rotation)
|
|
137
|
+
jwksClient.invalidateCache();
|
|
138
|
+
const retried = await jwksClient.getKey(kid);
|
|
139
|
+
if (!retried) {
|
|
140
|
+
throw new errors_1.AuthError('Unknown signing key', 'INVALID_TOKEN', 401);
|
|
141
|
+
}
|
|
142
|
+
const publicKey = jwks_service_1.JwksService.jwkToPublicKey(retried);
|
|
143
|
+
return this._verifyRsaToken(token, publicKey, expectedIssuer);
|
|
144
|
+
}
|
|
145
|
+
const publicKey = jwks_service_1.JwksService.jwkToPublicKey(jwk);
|
|
146
|
+
return this._verifyRsaToken(token, publicKey, expectedIssuer);
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
if (err instanceof errors_1.AuthError)
|
|
150
|
+
throw err;
|
|
151
|
+
throw new errors_1.AuthError('Invalid or expired token', 'INVALID_TOKEN', 401);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
_verifyRsaToken(token, publicKeyPem, expectedIssuer) {
|
|
155
|
+
const payload = jsonwebtoken_1.default.verify(token, publicKeyPem, { algorithms: ['RS256'] });
|
|
156
|
+
if (expectedIssuer && payload.iss !== expectedIssuer) {
|
|
157
|
+
throw new errors_1.AuthError('Token issuer mismatch', 'INVALID_TOKEN', 401);
|
|
158
|
+
}
|
|
159
|
+
return payload;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Sign the short-lived 2FA step-up token (`tempToken`) handed out after a
|
|
163
|
+
* correct password when a second factor is required. It carries
|
|
164
|
+
* `purpose: '2fa'`, set after the payload claims so a custom claim cannot
|
|
165
|
+
* remove it: `verifyAccessToken` refuses it, and only `verifyTempToken`
|
|
166
|
+
* (the 2FA completion endpoints) accepts it.
|
|
167
|
+
*/
|
|
168
|
+
generateTempToken(payload, config) {
|
|
169
|
+
const { iat, exp, ...claims } = payload;
|
|
170
|
+
return jsonwebtoken_1.default.sign({ ...claims, [exports.TOKEN_PURPOSE_CLAIM]: exports.TEMP_TOKEN_PURPOSE }, config.accessTokenSecret, { expiresIn: TEMP_TOKEN_EXPIRES_IN });
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Verify a 2FA step-up token. Only a token minted by `generateTempToken`
|
|
174
|
+
* passes: an application access token is refused. Throws the same
|
|
175
|
+
* `INVALID_ACCESS_TOKEN` error as `verifyAccessToken`.
|
|
176
|
+
*/
|
|
177
|
+
verifyTempToken(token, config) {
|
|
178
|
+
let payload;
|
|
179
|
+
try {
|
|
180
|
+
payload = jsonwebtoken_1.default.verify(token, config.accessTokenSecret);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
throw invalidAccessToken();
|
|
184
|
+
}
|
|
185
|
+
if (payload?.[exports.TOKEN_PURPOSE_CLAIM] !== exports.TEMP_TOKEN_PURPOSE)
|
|
186
|
+
throw invalidAccessToken();
|
|
187
|
+
return payload;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Verify an application session (access) token. A token signed with the
|
|
191
|
+
* same secret for another purpose is refused: the 2FA step-up token, and
|
|
192
|
+
* the admin console token (when the admin `jwtSecret` is the access-token
|
|
193
|
+
* secret, as `buildAllRouters()` sets it by default).
|
|
194
|
+
*/
|
|
195
|
+
verifyAccessToken(token, config) {
|
|
196
|
+
let payload;
|
|
197
|
+
try {
|
|
198
|
+
payload = jsonwebtoken_1.default.verify(token, config.accessTokenSecret);
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
throw invalidAccessToken();
|
|
202
|
+
}
|
|
203
|
+
const purpose = payload?.[exports.TOKEN_PURPOSE_CLAIM];
|
|
204
|
+
if (purpose === exports.TEMP_TOKEN_PURPOSE || purpose === exports.ADMIN_TOKEN_PURPOSE)
|
|
205
|
+
throw invalidAccessToken();
|
|
206
|
+
return payload;
|
|
207
|
+
}
|
|
208
|
+
verifyRefreshToken(token, config) {
|
|
209
|
+
try {
|
|
210
|
+
const payload = jsonwebtoken_1.default.verify(token, config.refreshTokenSecret);
|
|
211
|
+
return payload;
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
throw new errors_1.AuthError('Invalid or expired refresh token', 'INVALID_REFRESH_TOKEN', 401);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
getCookieName(name, config) {
|
|
218
|
+
if (!config.cookieOptions?.secure)
|
|
219
|
+
return name;
|
|
220
|
+
// __Host- needs Secure, Path=/, and NO Domain.
|
|
221
|
+
// We use it if path is '/' (default) and domain is not set.
|
|
222
|
+
const isPathRoot = !config.cookieOptions?.path || config.cookieOptions.path === '/';
|
|
223
|
+
if (isPathRoot && !config.cookieOptions?.domain) {
|
|
224
|
+
return `__Host-${name}`;
|
|
225
|
+
}
|
|
226
|
+
return `__Secure-${name}`;
|
|
227
|
+
}
|
|
228
|
+
setTokenCookies(res, tokens, config) {
|
|
229
|
+
const commonOpts = {
|
|
230
|
+
httpOnly: true,
|
|
231
|
+
secure: config.cookieOptions?.secure ?? false,
|
|
232
|
+
sameSite: (config.cookieOptions?.sameSite ?? 'lax'),
|
|
233
|
+
path: config.cookieOptions?.path ?? '/',
|
|
234
|
+
};
|
|
235
|
+
const setCookie = (name, value, extraOpts = {}) => {
|
|
236
|
+
const finalName = this.getCookieName(name, config);
|
|
237
|
+
const opts = { ...commonOpts, ...extraOpts };
|
|
238
|
+
if (finalName.startsWith('__Host-')) {
|
|
239
|
+
delete opts.domain;
|
|
240
|
+
opts.path = '/'; // __Host- requires path=/
|
|
241
|
+
opts.secure = true; // __Host- requires Secure
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
opts.domain = config.cookieOptions?.domain;
|
|
245
|
+
}
|
|
246
|
+
res.cookie(finalName, value, opts);
|
|
247
|
+
};
|
|
248
|
+
// Each cookie lives as long as the token it carries, i.e. the configured
|
|
249
|
+
// accessTokenExpiresIn / refreshTokenExpiresIn.
|
|
250
|
+
setCookie('accessToken', tokens.accessToken, {
|
|
251
|
+
maxAge: tokenLifetimeMs(tokens.accessToken) ?? DEFAULT_ACCESS_COOKIE_MAX_AGE_MS,
|
|
252
|
+
});
|
|
253
|
+
const refreshPath = config.cookieOptions?.refreshTokenPath
|
|
254
|
+
?? (config.apiPrefix ? `${config.apiPrefix}/refresh` : '/auth/refresh');
|
|
255
|
+
setCookie('refreshToken', tokens.refreshToken, {
|
|
256
|
+
maxAge: tokenLifetimeMs(tokens.refreshToken) ?? DEFAULT_REFRESH_COOKIE_MAX_AGE_MS,
|
|
257
|
+
path: refreshPath
|
|
258
|
+
});
|
|
259
|
+
if (config.csrf?.enabled) {
|
|
260
|
+
setCookie('csrf-token', this.generateSecureToken(16), {
|
|
261
|
+
httpOnly: false,
|
|
262
|
+
maxAge: 15 * 60 * 1000
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
initCsrfToken(res, config) {
|
|
267
|
+
if (!config.csrf?.enabled)
|
|
268
|
+
return;
|
|
269
|
+
const name = this.getCookieName('csrf-token', config);
|
|
270
|
+
const opts = {
|
|
271
|
+
httpOnly: false,
|
|
272
|
+
secure: config.cookieOptions?.secure ?? false,
|
|
273
|
+
sameSite: (config.cookieOptions?.sameSite ?? 'lax'),
|
|
274
|
+
path: config.cookieOptions?.path ?? '/',
|
|
275
|
+
maxAge: 15 * 60 * 1000,
|
|
276
|
+
};
|
|
277
|
+
if (name.startsWith('__Host-')) {
|
|
278
|
+
delete opts.domain;
|
|
279
|
+
opts.path = '/'; // __Host- requires path=/
|
|
280
|
+
opts.secure = true; // __Host- requires Secure
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
opts.domain = config.cookieOptions?.domain;
|
|
284
|
+
}
|
|
285
|
+
res.cookie(name, this.generateSecureToken(16), opts);
|
|
286
|
+
}
|
|
287
|
+
clearTokenCookies(res, config) {
|
|
288
|
+
const commonOpts = {
|
|
289
|
+
secure: config?.cookieOptions?.secure ?? false,
|
|
290
|
+
sameSite: (config?.cookieOptions?.sameSite ?? 'lax'),
|
|
291
|
+
path: config?.cookieOptions?.path ?? '/',
|
|
292
|
+
};
|
|
293
|
+
const clearCookie = (name, extraOpts = {}) => {
|
|
294
|
+
// For maximum robustness, we try to clear the primary name AND prefixed variants.
|
|
295
|
+
// Cookies are only cleared if BOTH name, path, and domain match exactly.
|
|
296
|
+
const primaryName = this.getCookieName(name, config || {});
|
|
297
|
+
const possibleNames = new Set([primaryName, `__Host-${name}`, `__Secure-${name}`, name]);
|
|
298
|
+
for (const finalName of possibleNames) {
|
|
299
|
+
const opts = { ...commonOpts, ...extraOpts };
|
|
300
|
+
if (finalName.startsWith('__Host-')) {
|
|
301
|
+
delete opts.domain;
|
|
302
|
+
opts.path = '/'; // __Host- requires path=/
|
|
303
|
+
opts.secure = true;
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
opts.domain = config?.cookieOptions?.domain;
|
|
307
|
+
}
|
|
308
|
+
res.clearCookie(finalName, opts);
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
clearCookie('accessToken');
|
|
312
|
+
// Mirror the path logic from setTokenCookies so the cookie is found and deleted.
|
|
313
|
+
const refreshPath = config?.cookieOptions?.refreshTokenPath
|
|
314
|
+
?? (config?.apiPrefix ? `${config?.apiPrefix}/refresh` : '/auth/refresh');
|
|
315
|
+
clearCookie('refreshToken', { path: refreshPath });
|
|
316
|
+
if (config?.csrf?.enabled) {
|
|
317
|
+
clearCookie('csrf-token');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
generateSecureToken(bytes = 32) {
|
|
321
|
+
return crypto_1.default.randomBytes(bytes).toString('hex');
|
|
322
|
+
}
|
|
323
|
+
extractTokenFromCookie(req, cookieName) {
|
|
324
|
+
// List of possible prefixed names in order of preference
|
|
325
|
+
const possibleNames = [
|
|
326
|
+
`__Host-${cookieName}`,
|
|
327
|
+
`__Secure-${cookieName}`,
|
|
328
|
+
cookieName
|
|
329
|
+
];
|
|
330
|
+
for (const name of possibleNames) {
|
|
331
|
+
// First try cookie-parser parsed cookies
|
|
332
|
+
if (req.cookies && req.cookies[name]) {
|
|
333
|
+
return req.cookies[name];
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
// Fallback: parse raw Cookie header
|
|
337
|
+
const cookieHeader = req.headers?.cookie;
|
|
338
|
+
if (!cookieHeader)
|
|
339
|
+
return null;
|
|
340
|
+
const cookies = cookieHeader.split(';').reduce((acc, part) => {
|
|
341
|
+
const [key, ...val] = part.trim().split('=');
|
|
342
|
+
if (key)
|
|
343
|
+
acc[key.trim()] = decodeURIComponent(val.join('='));
|
|
344
|
+
return acc;
|
|
345
|
+
}, {});
|
|
346
|
+
for (const name of possibleNames) {
|
|
347
|
+
if (cookies[name])
|
|
348
|
+
return cookies[name];
|
|
349
|
+
}
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
exports.TokenService = TokenService;
|
|
354
|
+
//# sourceMappingURL=token.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.service.js","sourceRoot":"","sources":["../../src/services/token.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ITemplateStore, MailTemplate, UiTranslation } from '../interfaces/template-store.interface';
|
|
2
|
+
export declare class MemoryTemplateStore implements ITemplateStore {
|
|
3
|
+
private mailTemplates;
|
|
4
|
+
private uiTranslations;
|
|
5
|
+
getMailTemplate(id: string): Promise<MailTemplate | null>;
|
|
6
|
+
listMailTemplates(): Promise<MailTemplate[]>;
|
|
7
|
+
updateMailTemplate(id: string, template: Partial<MailTemplate>): Promise<void>;
|
|
8
|
+
getUiTranslations(page: string): Promise<UiTranslation | null>;
|
|
9
|
+
listUiTranslations(): Promise<UiTranslation[]>;
|
|
10
|
+
updateUiTranslations(page: string, translations: Record<string, Record<string, string>>): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=memory-template.store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-template.store.d.ts","sourceRoot":"","sources":["../../src/stores/memory-template.store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAErG,qBAAa,mBAAoB,YAAW,cAAc;IACtD,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,cAAc,CAAyC;IAEzD,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAIzD,iBAAiB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAI5C,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9E,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAI9D,kBAAkB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAI9C,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAGhH"}
|