@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.
Files changed (262) hide show
  1. package/LICENSE +21 -0
  2. package/README.detailed.md +4059 -0
  3. package/README.md +248 -0
  4. package/dist/abstract/base-auth-strategy.abstract.d.ts +7 -0
  5. package/dist/abstract/base-auth-strategy.abstract.d.ts.map +1 -0
  6. package/dist/abstract/base-auth-strategy.abstract.js +7 -0
  7. package/dist/abstract/base-auth-strategy.abstract.js.map +1 -0
  8. package/dist/abstract/base-oauth-strategy.abstract.d.ts +27 -0
  9. package/dist/abstract/base-oauth-strategy.abstract.d.ts.map +1 -0
  10. package/dist/abstract/base-oauth-strategy.abstract.js +11 -0
  11. package/dist/abstract/base-oauth-strategy.abstract.js.map +1 -0
  12. package/dist/adapters/express.d.ts +45 -0
  13. package/dist/adapters/express.d.ts.map +1 -0
  14. package/dist/adapters/express.js +49 -0
  15. package/dist/adapters/express.js.map +1 -0
  16. package/dist/adapters/fastify.d.ts +72 -0
  17. package/dist/adapters/fastify.d.ts.map +1 -0
  18. package/dist/adapters/fastify.js +63 -0
  19. package/dist/adapters/fastify.js.map +1 -0
  20. package/dist/auth-configurator.d.ts +65 -0
  21. package/dist/auth-configurator.d.ts.map +1 -0
  22. package/dist/auth-configurator.js +127 -0
  23. package/dist/auth-configurator.js.map +1 -0
  24. package/dist/events/auth-event-bus.d.ts +68 -0
  25. package/dist/events/auth-event-bus.d.ts.map +1 -0
  26. package/dist/events/auth-event-bus.js +60 -0
  27. package/dist/events/auth-event-bus.js.map +1 -0
  28. package/dist/events/auth-event-names.d.ts +34 -0
  29. package/dist/events/auth-event-names.d.ts.map +1 -0
  30. package/dist/events/auth-event-names.js +41 -0
  31. package/dist/events/auth-event-names.js.map +1 -0
  32. package/dist/http-types.d.ts +135 -0
  33. package/dist/http-types.d.ts.map +1 -0
  34. package/dist/http-types.js +18 -0
  35. package/dist/http-types.js.map +1 -0
  36. package/dist/index.d.ts +80 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +88 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/interfaces/api-key-store.interface.d.ts +94 -0
  41. package/dist/interfaces/api-key-store.interface.d.ts.map +1 -0
  42. package/dist/interfaces/api-key-store.interface.js +3 -0
  43. package/dist/interfaces/api-key-store.interface.js.map +1 -0
  44. package/dist/interfaces/auth-strategy.interface.d.ts +6 -0
  45. package/dist/interfaces/auth-strategy.interface.d.ts.map +1 -0
  46. package/dist/interfaces/auth-strategy.interface.js +3 -0
  47. package/dist/interfaces/auth-strategy.interface.js.map +1 -0
  48. package/dist/interfaces/linked-accounts-store.interface.d.ts +74 -0
  49. package/dist/interfaces/linked-accounts-store.interface.d.ts.map +1 -0
  50. package/dist/interfaces/linked-accounts-store.interface.js +3 -0
  51. package/dist/interfaces/linked-accounts-store.interface.js.map +1 -0
  52. package/dist/interfaces/pending-link-store.interface.d.ts +77 -0
  53. package/dist/interfaces/pending-link-store.interface.d.ts.map +1 -0
  54. package/dist/interfaces/pending-link-store.interface.js +3 -0
  55. package/dist/interfaces/pending-link-store.interface.js.map +1 -0
  56. package/dist/interfaces/roles-permissions-store.interface.d.ts +129 -0
  57. package/dist/interfaces/roles-permissions-store.interface.d.ts.map +1 -0
  58. package/dist/interfaces/roles-permissions-store.interface.js +3 -0
  59. package/dist/interfaces/roles-permissions-store.interface.js.map +1 -0
  60. package/dist/interfaces/session-store.interface.d.ts +92 -0
  61. package/dist/interfaces/session-store.interface.d.ts.map +1 -0
  62. package/dist/interfaces/session-store.interface.js +3 -0
  63. package/dist/interfaces/session-store.interface.js.map +1 -0
  64. package/dist/interfaces/settings-store.interface.d.ts +91 -0
  65. package/dist/interfaces/settings-store.interface.d.ts.map +1 -0
  66. package/dist/interfaces/settings-store.interface.js +3 -0
  67. package/dist/interfaces/settings-store.interface.js.map +1 -0
  68. package/dist/interfaces/sse-distributor.interface.d.ts +25 -0
  69. package/dist/interfaces/sse-distributor.interface.d.ts.map +1 -0
  70. package/dist/interfaces/sse-distributor.interface.js +3 -0
  71. package/dist/interfaces/sse-distributor.interface.js.map +1 -0
  72. package/dist/interfaces/telemetry-store.interface.d.ts +72 -0
  73. package/dist/interfaces/telemetry-store.interface.d.ts.map +1 -0
  74. package/dist/interfaces/telemetry-store.interface.js +3 -0
  75. package/dist/interfaces/telemetry-store.interface.js.map +1 -0
  76. package/dist/interfaces/template-store.interface.d.ts +37 -0
  77. package/dist/interfaces/template-store.interface.d.ts.map +1 -0
  78. package/dist/interfaces/template-store.interface.js +3 -0
  79. package/dist/interfaces/template-store.interface.js.map +1 -0
  80. package/dist/interfaces/tenant-store.interface.d.ts +97 -0
  81. package/dist/interfaces/tenant-store.interface.d.ts.map +1 -0
  82. package/dist/interfaces/tenant-store.interface.js +3 -0
  83. package/dist/interfaces/tenant-store.interface.js.map +1 -0
  84. package/dist/interfaces/token-store.interface.d.ts +10 -0
  85. package/dist/interfaces/token-store.interface.d.ts.map +1 -0
  86. package/dist/interfaces/token-store.interface.js +3 -0
  87. package/dist/interfaces/token-store.interface.js.map +1 -0
  88. package/dist/interfaces/user-metadata-store.interface.d.ts +50 -0
  89. package/dist/interfaces/user-metadata-store.interface.d.ts.map +1 -0
  90. package/dist/interfaces/user-metadata-store.interface.js +3 -0
  91. package/dist/interfaces/user-metadata-store.interface.js.map +1 -0
  92. package/dist/interfaces/user-store.interface.d.ts +113 -0
  93. package/dist/interfaces/user-store.interface.d.ts.map +1 -0
  94. package/dist/interfaces/user-store.interface.js +3 -0
  95. package/dist/interfaces/user-store.interface.js.map +1 -0
  96. package/dist/interfaces/webhook-store.interface.d.ts +139 -0
  97. package/dist/interfaces/webhook-store.interface.d.ts.map +1 -0
  98. package/dist/interfaces/webhook-store.interface.js +3 -0
  99. package/dist/interfaces/webhook-store.interface.js.map +1 -0
  100. package/dist/middleware/api-key.middleware.d.ts +35 -0
  101. package/dist/middleware/api-key.middleware.d.ts.map +1 -0
  102. package/dist/middleware/api-key.middleware.js +45 -0
  103. package/dist/middleware/api-key.middleware.js.map +1 -0
  104. package/dist/middleware/auth.middleware.d.ts +13 -0
  105. package/dist/middleware/auth.middleware.d.ts.map +1 -0
  106. package/dist/middleware/auth.middleware.js +55 -0
  107. package/dist/middleware/auth.middleware.js.map +1 -0
  108. package/dist/middleware/jwks-auth.middleware.d.ts +18 -0
  109. package/dist/middleware/jwks-auth.middleware.d.ts.map +1 -0
  110. package/dist/middleware/jwks-auth.middleware.js +77 -0
  111. package/dist/middleware/jwks-auth.middleware.js.map +1 -0
  112. package/dist/models/api-key.model.d.ts +66 -0
  113. package/dist/models/api-key.model.d.ts.map +1 -0
  114. package/dist/models/api-key.model.js +3 -0
  115. package/dist/models/api-key.model.js.map +1 -0
  116. package/dist/models/auth-config.model.d.ts +387 -0
  117. package/dist/models/auth-config.model.d.ts.map +1 -0
  118. package/dist/models/auth-config.model.js +3 -0
  119. package/dist/models/auth-config.model.js.map +1 -0
  120. package/dist/models/errors.d.ts +7 -0
  121. package/dist/models/errors.d.ts.map +1 -0
  122. package/dist/models/errors.js +14 -0
  123. package/dist/models/errors.js.map +1 -0
  124. package/dist/models/session.model.d.ts +28 -0
  125. package/dist/models/session.model.d.ts.map +1 -0
  126. package/dist/models/session.model.js +3 -0
  127. package/dist/models/session.model.js.map +1 -0
  128. package/dist/models/tenant.model.d.ts +20 -0
  129. package/dist/models/tenant.model.d.ts.map +1 -0
  130. package/dist/models/tenant.model.js +3 -0
  131. package/dist/models/tenant.model.js.map +1 -0
  132. package/dist/models/token.model.d.ts +21 -0
  133. package/dist/models/token.model.d.ts.map +1 -0
  134. package/dist/models/token.model.js +3 -0
  135. package/dist/models/token.model.js.map +1 -0
  136. package/dist/models/user.model.d.ts +92 -0
  137. package/dist/models/user.model.d.ts.map +1 -0
  138. package/dist/models/user.model.js +3 -0
  139. package/dist/models/user.model.js.map +1 -0
  140. package/dist/router/admin.router.d.ts +188 -0
  141. package/dist/router/admin.router.d.ts.map +1 -0
  142. package/dist/router/admin.router.js +1507 -0
  143. package/dist/router/admin.router.js.map +1 -0
  144. package/dist/router/auth.router.d.ts +199 -0
  145. package/dist/router/auth.router.d.ts.map +1 -0
  146. package/dist/router/auth.router.js +1636 -0
  147. package/dist/router/auth.router.js.map +1 -0
  148. package/dist/router/openapi.d.ts +98 -0
  149. package/dist/router/openapi.d.ts.map +1 -0
  150. package/dist/router/openapi.js +1518 -0
  151. package/dist/router/openapi.js.map +1 -0
  152. package/dist/router/router-events.d.ts +38 -0
  153. package/dist/router/router-events.d.ts.map +1 -0
  154. package/dist/router/router-events.js +74 -0
  155. package/dist/router/router-events.js.map +1 -0
  156. package/dist/router/tools.router.d.ts +104 -0
  157. package/dist/router/tools.router.d.ts.map +1 -0
  158. package/dist/router/tools.router.js +227 -0
  159. package/dist/router/tools.router.js.map +1 -0
  160. package/dist/router/ui.router.d.ts +49 -0
  161. package/dist/router/ui.router.d.ts.map +1 -0
  162. package/dist/router/ui.router.js +272 -0
  163. package/dist/router/ui.router.js.map +1 -0
  164. package/dist/services/api-key.service.d.ts +53 -0
  165. package/dist/services/api-key.service.d.ts.map +1 -0
  166. package/dist/services/api-key.service.js +66 -0
  167. package/dist/services/api-key.service.js.map +1 -0
  168. package/dist/services/jwks.service.d.ts +73 -0
  169. package/dist/services/jwks.service.d.ts.map +1 -0
  170. package/dist/services/jwks.service.js +174 -0
  171. package/dist/services/jwks.service.js.map +1 -0
  172. package/dist/services/mailer.service.d.ts +30 -0
  173. package/dist/services/mailer.service.d.ts.map +1 -0
  174. package/dist/services/mailer.service.js +248 -0
  175. package/dist/services/mailer.service.js.map +1 -0
  176. package/dist/services/notification.service.d.ts +110 -0
  177. package/dist/services/notification.service.d.ts.map +1 -0
  178. package/dist/services/notification.service.js +79 -0
  179. package/dist/services/notification.service.js.map +1 -0
  180. package/dist/services/password.service.d.ts +5 -0
  181. package/dist/services/password.service.d.ts.map +1 -0
  182. package/dist/services/password.service.js +17 -0
  183. package/dist/services/password.service.js.map +1 -0
  184. package/dist/services/sms.service.d.ts +14 -0
  185. package/dist/services/sms.service.d.ts.map +1 -0
  186. package/dist/services/sms.service.js +51 -0
  187. package/dist/services/sms.service.js.map +1 -0
  188. package/dist/services/token.service.d.ts +62 -0
  189. package/dist/services/token.service.d.ts.map +1 -0
  190. package/dist/services/token.service.js +354 -0
  191. package/dist/services/token.service.js.map +1 -0
  192. package/dist/stores/memory-template.store.d.ts +12 -0
  193. package/dist/stores/memory-template.store.d.ts.map +1 -0
  194. package/dist/stores/memory-template.store.js +35 -0
  195. package/dist/stores/memory-template.store.js.map +1 -0
  196. package/dist/strategies/api-key/api-key.strategy.d.ts +72 -0
  197. package/dist/strategies/api-key/api-key.strategy.d.ts.map +1 -0
  198. package/dist/strategies/api-key/api-key.strategy.js +182 -0
  199. package/dist/strategies/api-key/api-key.strategy.js.map +1 -0
  200. package/dist/strategies/local/local.strategy.d.ts +19 -0
  201. package/dist/strategies/local/local.strategy.d.ts.map +1 -0
  202. package/dist/strategies/local/local.strategy.js +45 -0
  203. package/dist/strategies/local/local.strategy.js.map +1 -0
  204. package/dist/strategies/magic-link/magic-link.strategy.d.ts +8 -0
  205. package/dist/strategies/magic-link/magic-link.strategy.d.ts.map +1 -0
  206. package/dist/strategies/magic-link/magic-link.strategy.js +53 -0
  207. package/dist/strategies/magic-link/magic-link.strategy.js.map +1 -0
  208. package/dist/strategies/oauth/generic-oauth.strategy.d.ts +120 -0
  209. package/dist/strategies/oauth/generic-oauth.strategy.d.ts.map +1 -0
  210. package/dist/strategies/oauth/generic-oauth.strategy.js +88 -0
  211. package/dist/strategies/oauth/generic-oauth.strategy.js.map +1 -0
  212. package/dist/strategies/oauth/github.strategy.d.ts +31 -0
  213. package/dist/strategies/oauth/github.strategy.d.ts.map +1 -0
  214. package/dist/strategies/oauth/github.strategy.js +72 -0
  215. package/dist/strategies/oauth/github.strategy.js.map +1 -0
  216. package/dist/strategies/oauth/google.strategy.d.ts +31 -0
  217. package/dist/strategies/oauth/google.strategy.d.ts.map +1 -0
  218. package/dist/strategies/oauth/google.strategy.js +61 -0
  219. package/dist/strategies/oauth/google.strategy.js.map +1 -0
  220. package/dist/strategies/sms/sms.strategy.d.ts +7 -0
  221. package/dist/strategies/sms/sms.strategy.d.ts.map +1 -0
  222. package/dist/strategies/sms/sms.strategy.js +39 -0
  223. package/dist/strategies/sms/sms.strategy.js.map +1 -0
  224. package/dist/strategies/two-factor/totp.strategy.d.ts +12 -0
  225. package/dist/strategies/two-factor/totp.strategy.d.ts.map +1 -0
  226. package/dist/strategies/two-factor/totp.strategy.js +32 -0
  227. package/dist/strategies/two-factor/totp.strategy.js.map +1 -0
  228. package/dist/tools/auth-tools.d.ts +200 -0
  229. package/dist/tools/auth-tools.d.ts.map +1 -0
  230. package/dist/tools/auth-tools.js +232 -0
  231. package/dist/tools/auth-tools.js.map +1 -0
  232. package/dist/tools/sse-manager.d.ts +118 -0
  233. package/dist/tools/sse-manager.d.ts.map +1 -0
  234. package/dist/tools/sse-manager.js +163 -0
  235. package/dist/tools/sse-manager.js.map +1 -0
  236. package/dist/tools/sse-notify.decorator.d.ts +74 -0
  237. package/dist/tools/sse-notify.decorator.d.ts.map +1 -0
  238. package/dist/tools/sse-notify.decorator.js +78 -0
  239. package/dist/tools/sse-notify.decorator.js.map +1 -0
  240. package/dist/tools/webhook-action.d.ts +130 -0
  241. package/dist/tools/webhook-action.d.ts.map +1 -0
  242. package/dist/tools/webhook-action.js +144 -0
  243. package/dist/tools/webhook-action.js.map +1 -0
  244. package/dist/tools/webhook-sender.d.ts +31 -0
  245. package/dist/tools/webhook-sender.d.ts.map +1 -0
  246. package/dist/tools/webhook-sender.js +80 -0
  247. package/dist/tools/webhook-sender.js.map +1 -0
  248. package/dist/ui-assets/2fa.html +115 -0
  249. package/dist/ui-assets/account-conflict.html +108 -0
  250. package/dist/ui-assets/admin.css +263 -0
  251. package/dist/ui-assets/admin.js +1927 -0
  252. package/dist/ui-assets/auth.js +725 -0
  253. package/dist/ui-assets/base.css +219 -0
  254. package/dist/ui-assets/forgot-password.html +93 -0
  255. package/dist/ui-assets/link-verify.html +74 -0
  256. package/dist/ui-assets/login.html +135 -0
  257. package/dist/ui-assets/magic-link.html +112 -0
  258. package/dist/ui-assets/register.html +122 -0
  259. package/dist/ui-assets/reset-password.html +103 -0
  260. package/dist/ui-assets/ui-i18n-keys.json +78 -0
  261. package/dist/ui-assets/verify-email.html +66 -0
  262. package/package.json +89 -0
@@ -0,0 +1,49 @@
1
+ import { Router } from 'express';
2
+ import { AuthConfig } from '../models/auth-config.model';
3
+ import { ISettingsStore } from '../interfaces/settings-store.interface';
4
+ import { ITemplateStore } from '../interfaces/template-store.interface';
5
+ import { RouterOptions } from './auth.router';
6
+ export interface UiRouterOptions {
7
+ /**
8
+ * Optional path to a directory containing custom UI assets.
9
+ * If not provided, the internal Vanilla JS UI will be served.
10
+ */
11
+ uiAssetsDir?: string;
12
+ /**
13
+ * Optional directory where uploaded assets (like logos) are stored.
14
+ * If provided, files in this directory will be served under `/ assets / logo / `.
15
+ */
16
+ uploadDir?: string;
17
+ /**
18
+ * Optional settings store to fetch real-time UI customization (colors, site name).
19
+ * If not provided, defaults from `authConfig.ui` or hardcoded values are used.
20
+ */
21
+ settingsStore?: ISettingsStore;
22
+ /**
23
+ * Core authentication configuration.
24
+ * Used to determine which features (OAuth, Register, etc.) are enabled.
25
+ */
26
+ authConfig: AuthConfig;
27
+ /**
28
+ * Optional router options (where strategies and onRegister are defined).
29
+ */
30
+ routerOptions?: RouterOptions;
31
+ /**
32
+ * The base path where the main auth router is mounted.
33
+ * Used by the UI to know where to send API requests.
34
+ * @default '/auth'
35
+ */
36
+ apiPrefix?: string;
37
+ /**
38
+ * Optional template store for UI translations.
39
+ */
40
+ templateStore?: ITemplateStore;
41
+ }
42
+ /**
43
+ * Builds a router that serves the static UI assets and provides a
44
+ * `/ config` endpoint for dynamic UI behavior and theming.
45
+ *
46
+ * @param options Configuration for the UI router.
47
+ */
48
+ export declare function buildUiRouter(options: UiRouterOptions): Router;
49
+ //# sourceMappingURL=ui.router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.router.d.ts","sourceRoot":"","sources":["../../src/router/ui.router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA4D,MAAM,SAAS,CAAC;AAG3F,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAoB,MAAM,eAAe,CAAC;AAQhE,MAAM,WAAW,eAAe;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,cAAc,CAAC;IAE/B;;;OAGG;IACH,UAAU,EAAE,UAAU,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAE9B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,aAAa,CAAC,EAAE,cAAc,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAyR9D"}
@@ -0,0 +1,272 @@
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.buildUiRouter = buildUiRouter;
7
+ const express_1 = require("express");
8
+ const path_1 = __importDefault(require("path"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const auth_router_1 = require("./auth.router");
11
+ /**
12
+ * Builds a router that serves the static UI assets and provides a
13
+ * `/ config` endpoint for dynamic UI behavior and theming.
14
+ *
15
+ * @param options Configuration for the UI router.
16
+ */
17
+ function buildUiRouter(options) {
18
+ const router = (0, express_1.Router)();
19
+ const { uploadDir, settingsStore, templateStore, authConfig, routerOptions } = options;
20
+ const apiPrefix = (0, auth_router_1.resolveApiPrefix)(authConfig, routerOptions);
21
+ // In some environments (like ESM bundling), __dirname may not be available.
22
+ let _dirname = '';
23
+ try {
24
+ _dirname = __dirname;
25
+ }
26
+ catch (e) {
27
+ // Fallback for ESM if needed - though in CJS context this is rarely hit
28
+ _dirname = process.cwd();
29
+ }
30
+ const candidates = [
31
+ path_1.default.resolve(_dirname, '../ui-assets'), // dist
32
+ path_1.default.resolve(_dirname, '../../ui-assets'), // alternate dist
33
+ path_1.default.resolve(_dirname, '../ui/assets'), // src
34
+ path_1.default.resolve(_dirname, '../../src/ui/assets'), // alternate src
35
+ path_1.default.resolve(process.cwd(), 'node_modules/@awesome-lang-auth/node/dist/ui-assets'), // dependency
36
+ path_1.default.resolve(process.cwd(), 'node_modules/@awesome-lang-auth/node/src/ui/assets'), // dependency src
37
+ path_1.default.resolve(process.cwd(), 'node_modules/awesome-node-auth/dist/ui-assets'), // dependency, pre-1.10.1 name
38
+ path_1.default.resolve(process.cwd(), 'node_modules/awesome-node-auth/src/ui/assets'), // dependency src
39
+ ];
40
+ let uiAssetsDir = options.uiAssetsDir;
41
+ if (!uiAssetsDir) {
42
+ for (const candidate of candidates) {
43
+ if (fs_1.default.existsSync(candidate)) {
44
+ uiAssetsDir = candidate;
45
+ break;
46
+ }
47
+ }
48
+ }
49
+ if (!uiAssetsDir) {
50
+ uiAssetsDir = candidates[0];
51
+ }
52
+ async function getUiConfig(req) {
53
+ try {
54
+ const reqBaseUrl = req.baseUrl;
55
+ const resolvedApiPrefix = reqBaseUrl.replace(/\/ui$/, '') || apiPrefix;
56
+ const settings = settingsStore ? await settingsStore.getSettings() : {};
57
+ // Resolve language
58
+ const queryLang = req.query.lang;
59
+ const lang = queryLang || authConfig.email?.mailer?.defaultLang || 'en';
60
+ let translations = {};
61
+ if (templateStore) {
62
+ const page = req.path.replace(/^\//, '') || 'login';
63
+ const res = await templateStore.getUiTranslations(page);
64
+ if (res) {
65
+ translations = res.translations[lang] || res.translations['en'] || {};
66
+ }
67
+ }
68
+ const features = {
69
+ register: !!routerOptions?.onRegister,
70
+ magicLink: !!authConfig.email?.sendMagicLink || !!authConfig.email?.mailer,
71
+ sms: !!authConfig.sms,
72
+ google: !!authConfig.oauth?.google,
73
+ github: !!authConfig.oauth?.github,
74
+ forgotPassword: !!authConfig.email?.sendPasswordReset || !!authConfig.email?.mailer,
75
+ verifyEmail: (!!authConfig.email?.sendVerificationEmail || !!authConfig.email?.mailer) && (authConfig.emailVerificationMode !== 'none' || authConfig.requireEmailVerification),
76
+ twoFactor: !!authConfig.twoFactor,
77
+ };
78
+ const ui = {
79
+ primaryColor: settings.ui?.primaryColor || authConfig.ui?.primaryColor || '#4a90d9',
80
+ secondaryColor: settings.ui?.secondaryColor || authConfig.ui?.secondaryColor || '#6c757d',
81
+ logoUrl: settings.ui?.logoUrl || authConfig.ui?.customLogo || authConfig.ui?.logoUrl,
82
+ siteName: settings.ui?.siteName || authConfig.ui?.siteName || 'Awesome Node Auth',
83
+ customCss: authConfig.ui?.customCss,
84
+ bgColor: settings.ui?.bgColor || authConfig.ui?.bgColor,
85
+ bgImage: settings.ui?.bgImage || authConfig.ui?.bgImage,
86
+ cardBg: settings.ui?.cardBg || authConfig.ui?.cardBg,
87
+ };
88
+ return {
89
+ apiPrefix: resolvedApiPrefix,
90
+ features,
91
+ ui,
92
+ translations,
93
+ lang,
94
+ };
95
+ }
96
+ catch (err) {
97
+ const fallbackApiPrefix = req.baseUrl.replace(/\/ui$/, '') || apiPrefix;
98
+ return {
99
+ apiPrefix: fallbackApiPrefix,
100
+ features: { register: false, google: false, github: false },
101
+ ui: {
102
+ primaryColor: '#4a90d9',
103
+ secondaryColor: '#6c757d',
104
+ siteName: 'Awesome Node Auth',
105
+ logoUrl: undefined,
106
+ customCss: undefined,
107
+ bgColor: undefined,
108
+ bgImage: undefined,
109
+ cardBg: undefined
110
+ },
111
+ translations: {},
112
+ lang: 'en'
113
+ };
114
+ }
115
+ }
116
+ // 1. Configuration endpoint for the UI (still available for dynamic fetching)
117
+ router.get('/config', async (req, res) => {
118
+ const config = await getUiConfig(req);
119
+ // Include headless flag so auth.js can auto-configure itself
120
+ config.headless = !!(authConfig.ui?.headless);
121
+ res.json(config);
122
+ });
123
+ // In headless mode the HTML pages are not served (the hosting SPA provides
124
+ // its own login UI). We still serve /config and static assets (auth.js, CSS)
125
+ // so SPAs can load auth.js via <script> and use the fetch interceptor.
126
+ if (authConfig.ui?.headless) {
127
+ // Serve static assets (JS, CSS) — needed for the <script> tag integration
128
+ router.use('/', (0, express_1.static)(uiAssetsDir, {
129
+ maxAge: 0,
130
+ index: false,
131
+ }));
132
+ return router;
133
+ }
134
+ // 2. Serve custom uploaded assets (e.g. logo, background images)
135
+ if (uploadDir) {
136
+ // Legacy path for backwards compatibility with existing logo URLs
137
+ router.use('/assets/logo', (0, express_1.static)(uploadDir));
138
+ // New unified path for all uploaded UI assets
139
+ router.use('/assets/uploads', (0, express_1.static)(uploadDir));
140
+ }
141
+ // Helper to perform Server-Side Rendering (SSR) of Config and CSS
142
+ async function serveSsrHtml(req, res, htmlPath) {
143
+ console.log('[AwesomeNodeAuth] process SSR for', htmlPath);
144
+ try {
145
+ let htmlContent = await fs_1.default.promises.readFile(htmlPath, 'utf8');
146
+ console.log('[AwesomeNodeAuth] read file length:', htmlContent.length);
147
+ const config = await getUiConfig(req);
148
+ // Construct style snippet to prevent FOUC (Flash of Unstyled Content)
149
+ let styleTags = '<style>:root {';
150
+ if (config.ui?.primaryColor) {
151
+ styleTags += `--primary-color: ${config.ui.primaryColor};`;
152
+ styleTags += `--input-focus: ${config.ui.primaryColor};`;
153
+ }
154
+ if (config.ui?.secondaryColor)
155
+ styleTags += `--secondary-color: ${config.ui.secondaryColor};`;
156
+ if (config.ui?.bgColor)
157
+ styleTags += `--bg-color: ${config.ui.bgColor};`;
158
+ if (config.ui?.cardBg)
159
+ styleTags += `--card-bg: ${config.ui.cardBg};`;
160
+ if (config.ui?.bgImage) {
161
+ const safeUrl = config.ui.bgImage.replace(/['"\\]/g, m => encodeURIComponent(m));
162
+ styleTags += `--bg-image: url("${safeUrl}");`;
163
+ }
164
+ styleTags += '}</style>';
165
+ // Handle custom CSS and Site Name
166
+ if (config.ui?.customCss)
167
+ styleTags += `<style>${config.ui.customCss}</style>`;
168
+ if (config.ui?.siteName) {
169
+ const safeSiteName = config.ui.siteName
170
+ .replace(/&/g, '&amp;')
171
+ .replace(/</g, '&lt;')
172
+ .replace(/>/g, '&gt;')
173
+ .replace(/"/g, '&quot;')
174
+ .replace(/'/g, '&#39;');
175
+ htmlContent = htmlContent.replace(/<title>.*?<\/title>/s, `<title>${safeSiteName}</title>`);
176
+ htmlContent = htmlContent.replace(/(<h1[^>]*class="site-name"[^>]*>).*?(<\/h1>)/s, `$1${safeSiteName}$2`);
177
+ }
178
+ if (config.ui?.logoUrl) {
179
+ htmlContent = htmlContent.replace(/<img src=".*?" alt="Logo" class="logo hidden">/, `<img src="${config.ui.logoUrl}" alt="Logo" class="logo">`);
180
+ }
181
+ // Readiness Splash Screen Injection
182
+ const splashCss = `
183
+ <style>
184
+ body { background-color: var(--bg-color, #f8fafc); margin: 0; }
185
+ #global-splash {
186
+ position: fixed;
187
+ top: 0; left: 0; width: 100vw; height: 100vh;
188
+ background-color: var(--bg-color, #f8fafc);
189
+ z-index: 999999;
190
+ display: flex;
191
+ justify-content: center;
192
+ align-items: center;
193
+ transition: opacity 0.3s ease-out;
194
+ }
195
+ .splash-spinner {
196
+ width: 40px; height: 40px;
197
+ border: 4px solid var(--secondary-color, #cbd5e1);
198
+ border-top: 4px solid var(--primary-color, #4a90d9);
199
+ border-radius: 50%;
200
+ animation: splash-spin 1s linear infinite;
201
+ }
202
+ @keyframes splash-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
203
+ </style>`;
204
+ const splashHtml = `
205
+ <div id="global-splash">
206
+ <div class="splash-spinner"></div>
207
+ </div>`;
208
+ const splashJs = `
209
+ <script>
210
+ window.onload = function() {
211
+ const splash = document.getElementById('global-splash');
212
+ if (splash) {
213
+ splash.style.opacity = '0';
214
+ setTimeout(() => splash.remove(), 300);
215
+ }
216
+ };
217
+ </script>`;
218
+ // Construct script injection for fast synchronous auth.js booting
219
+ const scriptTag = `<script>window.__AUTH_CONFIG__ = ${JSON.stringify(config)};</script>`;
220
+ // Inject just before </head>
221
+ htmlContent = htmlContent.replace('</head>', `${styleTags}\n${splashCss}\n${scriptTag}\n</head>`);
222
+ // Inject splash html right after <body>
223
+ htmlContent = htmlContent.replace('<body>', `<body>\n${splashHtml}`);
224
+ // Inject splash js parser right before </body>
225
+ htmlContent = htmlContent.replace('</body>', `${splashJs}\n</body>`);
226
+ res.setHeader('Content-Type', 'text/html; charset=utf-8');
227
+ res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
228
+ res.send(htmlContent);
229
+ }
230
+ catch (err) {
231
+ console.error('[AwesomeNodeAuth UI Router] SSR Error:', err);
232
+ // Fallback to static sending if reading/parsing fails
233
+ res.sendFile(htmlPath);
234
+ }
235
+ }
236
+ // 3. Vanilla UI Route Mapping & SPA fallback
237
+ // Matches all extensionless paths and renders the corresponding HTML file with SSR config
238
+ router.use(async (req, res, next) => {
239
+ if (req.method !== 'GET') {
240
+ return next();
241
+ }
242
+ if (path_1.default.extname(req.path)) {
243
+ // Let expressStatic handle real files (css, js, images)
244
+ return next();
245
+ }
246
+ // Map clean routes to internal HTML files if they exist
247
+ const page = req.path.replace(/^\//, '') || 'login';
248
+ const htmlFile = `${page}.html`;
249
+ const htmlPath = path_1.default.join(uiAssetsDir, htmlFile);
250
+ if (fs_1.default.existsSync(htmlPath)) {
251
+ await serveSsrHtml(req, res, htmlPath);
252
+ return;
253
+ }
254
+ // Default fallback to login or index
255
+ const fallbackFiles = ['login.html', 'index.html', 'index.csr.html'];
256
+ for (const file of fallbackFiles) {
257
+ const fallbackPath = path_1.default.join(uiAssetsDir, file);
258
+ if (fs_1.default.existsSync(fallbackPath)) {
259
+ await serveSsrHtml(req, res, fallbackPath);
260
+ return;
261
+ }
262
+ }
263
+ next(); // Let it fall through if nothing works
264
+ });
265
+ // 4. Serve UI assets (css, js, static files)
266
+ router.use('/', (0, express_1.static)(uiAssetsDir, {
267
+ maxAge: 0,
268
+ index: false
269
+ }));
270
+ return router;
271
+ }
272
+ //# sourceMappingURL=ui.router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.router.js","sourceRoot":"","sources":["../../src/router/ui.router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { ApiKey } from '../models/api-key.model';
2
+ import { IApiKeyStore } from '../interfaces/api-key-store.interface';
3
+ /** Options for generating a new API key. */
4
+ export interface CreateApiKeyOptions {
5
+ /** Human-readable name / label for the key. */
6
+ name: string;
7
+ /** Optional service identity (user ID, tenant ID, service name, …). */
8
+ serviceId?: string;
9
+ /** Scope strings controlling access (e.g. `['tools:read', 'webhooks:receive']`). */
10
+ scopes?: string[];
11
+ /** IP allowlist (CIDR notation or individual addresses). */
12
+ allowedIps?: string[];
13
+ /** Expiry date. Omit for a non-expiring key. */
14
+ expiresAt?: Date;
15
+ /** bcrypt salt rounds (default: 10 — intentionally lower than user-password hashing). */
16
+ saltRounds?: number;
17
+ }
18
+ /** The result of key creation — contains the raw key (show once, then discard). */
19
+ export interface CreatedApiKey {
20
+ /** The full key to present to the caller — store this securely, it cannot be recovered. */
21
+ rawKey: string;
22
+ /** The persisted key record (does not include the raw key). */
23
+ record: ApiKey;
24
+ }
25
+ /**
26
+ * Service for creating and validating API Keys / Service Tokens.
27
+ *
28
+ * Raw keys are formatted as `ak_<48 hex chars>` (196 bits of entropy).
29
+ * The first 8 characters after `ak_` are used as a prefix index; the full
30
+ * value is stored only in its bcrypt hash form.
31
+ */
32
+ export declare class ApiKeyService {
33
+ private readonly saltRounds;
34
+ constructor(saltRounds?: number);
35
+ /**
36
+ * Generate a new API key, hash it, persist it via the store, and return
37
+ * the plaintext key **once**.
38
+ */
39
+ createKey(store: IApiKeyStore, options: CreateApiKeyOptions): Promise<CreatedApiKey>;
40
+ /**
41
+ * Verify a raw API key against its stored bcrypt hash.
42
+ * Returns `true` when the key matches the hash.
43
+ */
44
+ verifyKey(rawKey: string, hash: string): Promise<boolean>;
45
+ /**
46
+ * Extract the 8-character prefix used as a lookup index.
47
+ * Input: `ak_<48 hex chars>` → prefix: `ak_<first 8 chars>`
48
+ */
49
+ extractPrefix(rawKey: string): string;
50
+ /** Generate a cryptographically secure raw key string. */
51
+ private generateRawKey;
52
+ }
53
+ //# sourceMappingURL=api-key.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-key.service.d.ts","sourceRoot":"","sources":["../../src/services/api-key.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAErE,4CAA4C;AAC5C,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,gDAAgD;IAChD,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,2FAA2F;IAC3F,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,UAAU,SAAK;IAI3B;;;OAGG;IACG,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC;IAwB1F;;;OAGG;IACG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI/D;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAKrC,0DAA0D;IAC1D,OAAO,CAAC,cAAc;CAGvB"}
@@ -0,0 +1,66 @@
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.ApiKeyService = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ const bcryptjs_1 = __importDefault(require("bcryptjs"));
9
+ /**
10
+ * Service for creating and validating API Keys / Service Tokens.
11
+ *
12
+ * Raw keys are formatted as `ak_<48 hex chars>` (196 bits of entropy).
13
+ * The first 8 characters after `ak_` are used as a prefix index; the full
14
+ * value is stored only in its bcrypt hash form.
15
+ */
16
+ class ApiKeyService {
17
+ constructor(saltRounds = 10) {
18
+ this.saltRounds = saltRounds;
19
+ }
20
+ /**
21
+ * Generate a new API key, hash it, persist it via the store, and return
22
+ * the plaintext key **once**.
23
+ */
24
+ async createKey(store, options) {
25
+ const raw = this.generateRawKey();
26
+ const prefix = this.extractPrefix(raw);
27
+ const rounds = options.saltRounds ?? this.saltRounds;
28
+ const hash = await bcryptjs_1.default.hash(raw, rounds);
29
+ const record = {
30
+ id: crypto_1.default.randomUUID(),
31
+ name: options.name,
32
+ keyHash: hash,
33
+ keyPrefix: prefix,
34
+ serviceId: options.serviceId ?? null,
35
+ scopes: options.scopes ?? [],
36
+ allowedIps: options.allowedIps ?? null,
37
+ isActive: true,
38
+ expiresAt: options.expiresAt ?? null,
39
+ createdAt: new Date(),
40
+ lastUsedAt: null,
41
+ };
42
+ await store.save(record);
43
+ return { rawKey: raw, record };
44
+ }
45
+ /**
46
+ * Verify a raw API key against its stored bcrypt hash.
47
+ * Returns `true` when the key matches the hash.
48
+ */
49
+ async verifyKey(rawKey, hash) {
50
+ return bcryptjs_1.default.compare(rawKey, hash);
51
+ }
52
+ /**
53
+ * Extract the 8-character prefix used as a lookup index.
54
+ * Input: `ak_<48 hex chars>` → prefix: `ak_<first 8 chars>`
55
+ */
56
+ extractPrefix(rawKey) {
57
+ // Keep the `ak_` sentinel plus the first 8 hex characters
58
+ return rawKey.substring(0, 11); // 'ak_' (3) + 8 chars = 11
59
+ }
60
+ /** Generate a cryptographically secure raw key string. */
61
+ generateRawKey() {
62
+ return `ak_${crypto_1.default.randomBytes(24).toString('hex')}`; // 24 bytes = 48 hex = ~196 bits
63
+ }
64
+ }
65
+ exports.ApiKeyService = ApiKeyService;
66
+ //# sourceMappingURL=api-key.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-key.service.js","sourceRoot":"","sources":["../../src/services/api-key.service.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA4B;AAC5B,wDAA8B;AA4B9B;;;;;;GAMG;AACH,MAAa,aAAa;IAGxB,YAAY,UAAU,GAAG,EAAE;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS,CAAC,KAAmB,EAAE,OAA4B;QAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC;QACrD,MAAM,IAAI,GAAG,MAAM,kBAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAE5C,MAAM,MAAM,GAAW;YACrB,EAAE,EAAE,gBAAM,CAAC,UAAU,EAAE;YACvB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,MAAM;YACjB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;YACpC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;YAC5B,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI;YACtC,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;YACpC,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,UAAU,EAAE,IAAI;SACjB,CAAC;QAEF,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzB,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IACjC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS,CAAC,MAAc,EAAE,IAAY;QAC1C,OAAO,kBAAM,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,MAAc;QAC1B,0DAA0D;QAC1D,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,2BAA2B;IAC7D,CAAC;IAED,0DAA0D;IAClD,cAAc;QACpB,OAAO,MAAM,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,gCAAgC;IACzF,CAAC;CACF;AAxDD,sCAwDC"}
@@ -0,0 +1,73 @@
1
+ export interface JWK {
2
+ kty: string;
3
+ use: string;
4
+ alg: string;
5
+ kid: string;
6
+ n: string;
7
+ e: string;
8
+ }
9
+ export interface JwksDocument {
10
+ keys: JWK[];
11
+ }
12
+ export interface JwksClientOptions {
13
+ /** Cache TTL in milliseconds. @default 3_600_000 */
14
+ cacheTtl?: number;
15
+ /** Fetch timeout in milliseconds. @default 5000 */
16
+ fetchTimeout?: number;
17
+ }
18
+ /**
19
+ * A simple cached JWKS client for Resource Server use.
20
+ * Fetches and caches the public keys from a remote JWKS URL.
21
+ */
22
+ export declare class JwksClient {
23
+ readonly jwksUrl: string;
24
+ private cachedDocument;
25
+ private cacheExpiry;
26
+ private readonly cacheTtl;
27
+ private readonly fetchTimeout;
28
+ private fetchPromise;
29
+ constructor(jwksUrl: string, options?: JwksClientOptions);
30
+ /**
31
+ * Get the JWKS document, fetching from remote if the cache is stale.
32
+ * Uses stale-while-revalidate: returns the cached doc immediately if available,
33
+ * then refreshes in the background when TTL expires.
34
+ */
35
+ getJwks(): Promise<JwksDocument>;
36
+ /** Find a JWK by its key ID (`kid`). Returns null if not found. */
37
+ getKey(kid: string): Promise<JWK | null>;
38
+ /** Force-invalidate the cache so the next call fetches fresh keys. */
39
+ invalidateCache(): void;
40
+ private _fetch;
41
+ }
42
+ export declare class JwksService {
43
+ /**
44
+ * Generate an RSA-2048 keypair.
45
+ * Returns PEM-encoded `privateKey` and `publicKey` strings.
46
+ */
47
+ static generateKeypair(): {
48
+ privateKey: string;
49
+ publicKey: string;
50
+ };
51
+ /**
52
+ * Derive the public key PEM from a private key PEM.
53
+ */
54
+ static derivePublicKey(privateKeyPem: string): string;
55
+ /**
56
+ * Convert a PEM-encoded RSA public key to JWK format.
57
+ */
58
+ static publicKeyToJwk(publicKeyPem: string, kid: string): JWK;
59
+ /**
60
+ * Build a full JWKS document from a PEM-encoded RSA public key.
61
+ */
62
+ static buildJwksDocument(publicKeyPem: string, kid?: string): JwksDocument;
63
+ /**
64
+ * Create a cached JWKS client for a remote URL (Resource Server use).
65
+ */
66
+ static createRemoteClient(jwksUrl: string, options?: JwksClientOptions): JwksClient;
67
+ /**
68
+ * Convert a JWK (`n`, `e` fields) to an RSA public key PEM string
69
+ * usable by `jwt.verify()`.
70
+ */
71
+ static jwkToPublicKey(jwk: JWK): string;
72
+ }
73
+ //# sourceMappingURL=jwks.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwks.service.d.ts","sourceRoot":"","sources":["../../src/services/jwks.service.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,GAAG,EAAE,CAAC;CACb;AAED,MAAM,WAAW,iBAAiB;IAChC,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,UAAU;aAQH,OAAO,EAAE,MAAM;IAPjC,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,YAAY,CAAsC;gBAGxC,OAAO,EAAE,MAAM,EAC/B,OAAO,GAAE,iBAAsB;IAMjC;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC;IA6CtC,mEAAmE;IAC7D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAK9C,sEAAsE;IACtE,eAAe,IAAI,IAAI;IAMvB,OAAO,CAAC,MAAM;CAkCf;AAED,qBAAa,WAAW;IACtB;;;OAGG;IACH,MAAM,CAAC,eAAe,IAAI;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IASnE;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM;IAKrD;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,GAAG;IAa7D;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,SAAsB,GAAG,YAAY;IAIvF;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,UAAU;IAInF;;;OAGG;IACH,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM;CAIxC"}