@tsed/oidc-provider 8.0.1 → 8.0.3

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 (49) hide show
  1. package/package.json +16 -15
  2. package/src/OidcModule.spec.ts +116 -0
  3. package/src/OidcModule.ts +70 -0
  4. package/src/constants/constants.ts +10 -0
  5. package/src/decorators/grantId.spec.ts +17 -0
  6. package/src/decorators/grantId.ts +10 -0
  7. package/src/decorators/interaction.spec.ts +27 -0
  8. package/src/decorators/interaction.ts +18 -0
  9. package/src/decorators/interactions.spec.ts +23 -0
  10. package/src/decorators/interactions.ts +21 -0
  11. package/src/decorators/noCache.ts +7 -0
  12. package/src/decorators/oidcCtx.spec.ts +17 -0
  13. package/src/decorators/oidcCtx.ts +11 -0
  14. package/src/decorators/oidcSession.spec.ts +17 -0
  15. package/src/decorators/oidcSession.ts +14 -0
  16. package/src/decorators/params.spec.ts +17 -0
  17. package/src/decorators/params.ts +10 -0
  18. package/src/decorators/prompt.spec.ts +17 -0
  19. package/src/decorators/prompt.ts +11 -0
  20. package/src/decorators/uid.spec.ts +17 -0
  21. package/src/decorators/uid.ts +10 -0
  22. package/src/domain/InteractionMethods.ts +11 -0
  23. package/src/domain/OidcAccountsMethods.ts +10 -0
  24. package/src/domain/OidcBadInteractionName.ts +3 -0
  25. package/src/domain/OidcInteractionMethods.ts +3 -0
  26. package/src/domain/OidcInteractionOptions.ts +8 -0
  27. package/src/domain/OidcInteractionPromptProps.ts +11 -0
  28. package/src/domain/OidcSettings.ts +72 -0
  29. package/src/domain/interfaces.ts +13 -0
  30. package/src/index.ts +33 -0
  31. package/src/middlewares/OidcInteractionMiddleware.spec.ts +40 -0
  32. package/src/middlewares/OidcInteractionMiddleware.ts +14 -0
  33. package/src/middlewares/OidcNoCacheMiddleware.spec.ts +18 -0
  34. package/src/middlewares/OidcNoCacheMiddleware.ts +10 -0
  35. package/src/middlewares/OidcSecureMiddleware.spec.ts +106 -0
  36. package/src/middlewares/OidcSecureMiddleware.ts +29 -0
  37. package/src/services/OidcAdapters.spec.ts +100 -0
  38. package/src/services/OidcAdapters.ts +92 -0
  39. package/src/services/OidcInteractionContext.spec.ts +304 -0
  40. package/src/services/OidcInteractionContext.ts +206 -0
  41. package/src/services/OidcInteractions.ts +57 -0
  42. package/src/services/OidcJwks.ts +21 -0
  43. package/src/services/OidcPolicy.spec.ts +156 -0
  44. package/src/services/OidcPolicy.ts +92 -0
  45. package/src/services/OidcProvider.spec.ts +116 -0
  46. package/src/services/OidcProvider.ts +198 -0
  47. package/src/utils/debug.spec.ts +12 -0
  48. package/src/utils/debug.ts +25 -0
  49. package/src/utils/events.ts +61 -0
@@ -0,0 +1,304 @@
1
+ import {catchAsyncError, catchError} from "@tsed/core";
2
+ import {runInContext} from "@tsed/di";
3
+ import {PlatformTest} from "@tsed/platform-http/testing";
4
+
5
+ import {OidcInteractionContext} from "./OidcInteractionContext.js";
6
+ import {OidcProvider} from "./OidcProvider.js";
7
+
8
+ async function createOidcInteractionContextFixture(grantId: any = "grantId") {
9
+ const $ctx = PlatformTest.createRequestContext();
10
+
11
+ const session = {
12
+ accountId: "accountId"
13
+ };
14
+
15
+ const interactionDetails: any = {
16
+ uid: "uid",
17
+ grantId,
18
+ session,
19
+ prompt: {
20
+ name: "login"
21
+ },
22
+ params: {
23
+ client_id: "client_id",
24
+ email: "email@email.com"
25
+ },
26
+ save: vi.fn()
27
+ };
28
+
29
+ const oidcProvider = {
30
+ interactionDetails: vi.fn().mockResolvedValue(interactionDetails),
31
+ interactionFinished: vi.fn().mockResolvedValue(undefined),
32
+ interactionResult: vi.fn().mockResolvedValue(undefined),
33
+ setProviderSession: vi.fn().mockResolvedValue(undefined),
34
+ find: vi.fn().mockResolvedValue("grant"),
35
+ Grant: class {
36
+ static find = vi.fn().mockResolvedValue("grant");
37
+ },
38
+ Client: {
39
+ find: vi.fn().mockResolvedValue({
40
+ client_id: "client_id"
41
+ })
42
+ },
43
+ Account: {
44
+ findAccount: vi.fn().mockResolvedValue({
45
+ accountId: "accountId"
46
+ })
47
+ }
48
+ };
49
+ const oidcCtx = await PlatformTest.invoke<OidcInteractionContext>(OidcInteractionContext, [
50
+ {
51
+ token: OidcProvider,
52
+ use: {
53
+ get() {
54
+ return oidcProvider;
55
+ }
56
+ }
57
+ }
58
+ ]);
59
+
60
+ await runInContext($ctx, () => oidcCtx.interactionDetails());
61
+
62
+ return {$ctx, oidcCtx, oidcProvider, session, interactionDetails};
63
+ }
64
+
65
+ describe("OidcInteractionContext", () => {
66
+ beforeEach(() => PlatformTest.create());
67
+ afterEach(() => PlatformTest.reset());
68
+
69
+ describe("uid()", () => {
70
+ it("should return uid", async () => {
71
+ const {$ctx, oidcCtx} = await createOidcInteractionContextFixture();
72
+
73
+ await runInContext($ctx, () => {
74
+ expect(oidcCtx.uid).toEqual("uid");
75
+ });
76
+ });
77
+ });
78
+
79
+ describe("checkInteractionName()", () => {
80
+ it("should throw error", async () => {
81
+ const {$ctx, oidcCtx} = await createOidcInteractionContextFixture();
82
+
83
+ await runInContext($ctx, () => {
84
+ const error: any = catchError(() => oidcCtx.checkInteractionName("test"));
85
+
86
+ expect(error?.message).toEqual("Bad interaction name");
87
+ });
88
+ });
89
+ });
90
+
91
+ describe("checkClientId()", () => {
92
+ it("should throw error", async () => {
93
+ const {$ctx, oidcCtx, oidcProvider} = await createOidcInteractionContextFixture();
94
+ oidcProvider.Client.find.mockResolvedValue(undefined);
95
+
96
+ await runInContext($ctx, async () => {
97
+ const error: any = await catchAsyncError(() => oidcCtx.checkClientId());
98
+
99
+ expect(error?.message).toEqual("Unknown client_id client_id");
100
+ });
101
+ });
102
+ });
103
+
104
+ describe("grantId()", () => {
105
+ it("should return uid", async () => {
106
+ const {$ctx, oidcCtx} = await createOidcInteractionContextFixture();
107
+ await runInContext($ctx, () => {
108
+ expect(oidcCtx.grantId).toEqual("grantId");
109
+ });
110
+ });
111
+ });
112
+
113
+ describe("session()", () => {
114
+ it("should return session", async () => {
115
+ const {$ctx, oidcCtx, interactionDetails} = await createOidcInteractionContextFixture();
116
+ await runInContext($ctx, () => {
117
+ expect(oidcCtx.session).toEqual(interactionDetails.session);
118
+ });
119
+ });
120
+ });
121
+
122
+ describe("prompt()", () => {
123
+ it("should return prompt", async () => {
124
+ const {$ctx, oidcCtx} = await createOidcInteractionContextFixture();
125
+
126
+ await runInContext($ctx, () => {
127
+ expect(oidcCtx.prompt).toEqual({
128
+ name: "login"
129
+ });
130
+ });
131
+ });
132
+ });
133
+
134
+ describe("params()", () => {
135
+ it("should return params", async () => {
136
+ const {$ctx, oidcCtx, interactionDetails} = await createOidcInteractionContextFixture();
137
+ await runInContext($ctx, () => {
138
+ expect(oidcCtx.params).toEqual(interactionDetails.params);
139
+ });
140
+ });
141
+ });
142
+
143
+ describe("interactionFinished()", () => {
144
+ it("should return call interactionFinished", async () => {
145
+ const {$ctx, oidcCtx, oidcProvider} = await createOidcInteractionContextFixture();
146
+
147
+ await runInContext($ctx, async () => {
148
+ await oidcCtx.interactionFinished({login: {accountId: "string"}}, {mergeWithLastSubmission: false});
149
+
150
+ expect(oidcProvider.interactionFinished).toHaveBeenCalledWith(
151
+ $ctx.getReq(),
152
+ $ctx.getRes(),
153
+ {login: {accountId: "string"}},
154
+ {mergeWithLastSubmission: false}
155
+ );
156
+ });
157
+ });
158
+ });
159
+
160
+ describe("interactionResult()", () => {
161
+ it("should return call interactionResult", async () => {
162
+ const {$ctx, oidcCtx, oidcProvider} = await createOidcInteractionContextFixture();
163
+ await runInContext($ctx, async () => {
164
+ await oidcCtx.interactionResult({login: {accountId: "string"}}, {mergeWithLastSubmission: false});
165
+
166
+ expect(oidcProvider.interactionResult).toHaveBeenCalledWith(
167
+ $ctx.getReq(),
168
+ $ctx.getRes(),
169
+ {login: {accountId: "string"}},
170
+ {mergeWithLastSubmission: false}
171
+ );
172
+ });
173
+ });
174
+ it("should return call interactionResult (default)", async () => {
175
+ const {$ctx, oidcCtx, oidcProvider} = await createOidcInteractionContextFixture();
176
+ await runInContext($ctx, async () => {
177
+ await oidcCtx.interactionResult({login: {accountId: "string"}});
178
+
179
+ expect(oidcProvider.interactionResult).toHaveBeenCalledWith(
180
+ $ctx.getReq(),
181
+ $ctx.getRes(),
182
+ {login: {accountId: "string"}},
183
+ {mergeWithLastSubmission: false}
184
+ );
185
+ });
186
+ });
187
+ });
188
+
189
+ describe("render()", () => {
190
+ it("should return call render", async () => {
191
+ const {$ctx, oidcCtx} = await createOidcInteractionContextFixture();
192
+ await runInContext($ctx, async () => {
193
+ vi.spyOn($ctx.response, "render").mockResolvedValue("");
194
+
195
+ await oidcCtx.render("login", {});
196
+
197
+ expect($ctx.response.render).toHaveBeenCalledWith("login", {});
198
+ });
199
+ });
200
+ });
201
+
202
+ describe("save()", () => {
203
+ it("should return call save", async () => {
204
+ const {$ctx, oidcCtx, interactionDetails} = await createOidcInteractionContextFixture();
205
+ await runInContext($ctx, async () => {
206
+ await oidcCtx.save(2000);
207
+
208
+ expect(interactionDetails.save).toHaveBeenCalledWith(2000);
209
+ });
210
+ });
211
+
212
+ it("should return call save (default)", async () => {
213
+ const {$ctx, oidcCtx, interactionDetails} = await createOidcInteractionContextFixture();
214
+ await runInContext($ctx, async () => {
215
+ await oidcCtx.save(100);
216
+
217
+ expect(interactionDetails.save).toHaveBeenCalledWith(100);
218
+ });
219
+ });
220
+ });
221
+
222
+ describe("findClient()", () => {
223
+ it("should return call findClient", async () => {
224
+ const {$ctx, oidcCtx, oidcProvider} = await createOidcInteractionContextFixture();
225
+ await runInContext($ctx, async () => {
226
+ const result = await oidcCtx.findClient("client_id");
227
+
228
+ expect(result).toEqual({
229
+ client_id: "client_id"
230
+ });
231
+ expect(oidcProvider.Client.find).toHaveBeenCalledWith("client_id");
232
+ });
233
+ });
234
+
235
+ it("should return call findClient (default)", async () => {
236
+ const {$ctx, oidcCtx, oidcProvider} = await createOidcInteractionContextFixture();
237
+
238
+ await runInContext($ctx, async () => {
239
+ const result = await oidcCtx.findClient();
240
+
241
+ expect(result).toEqual({
242
+ client_id: "client_id"
243
+ });
244
+ expect(oidcProvider.Client.find).toHaveBeenCalledWith("client_id");
245
+ });
246
+ });
247
+ });
248
+
249
+ describe("findAccount()", () => {
250
+ it("should return call findAccount", async () => {
251
+ const {$ctx, oidcCtx, oidcProvider} = await createOidcInteractionContextFixture();
252
+ await runInContext($ctx, async () => {
253
+ const result = await oidcCtx.findAccount(undefined, "token");
254
+
255
+ expect(oidcProvider.Account.findAccount).toHaveBeenCalledWith(undefined, "accountId", "token");
256
+ expect(result).toEqual({
257
+ accountId: "accountId"
258
+ });
259
+ });
260
+ });
261
+
262
+ it("should return call findAccount (with accountId)", async () => {
263
+ const {$ctx, oidcCtx, oidcProvider} = await createOidcInteractionContextFixture();
264
+ await runInContext($ctx, async () => {
265
+ const result = await oidcCtx.findAccount("accountId", "token");
266
+
267
+ expect(oidcProvider.Account.findAccount).toHaveBeenCalledWith(undefined, "accountId", "token");
268
+ expect(result).toEqual({
269
+ accountId: "accountId"
270
+ });
271
+ });
272
+ });
273
+
274
+ it("should return call findAccount (without session/accountId)", async () => {
275
+ const {$ctx, oidcCtx, interactionDetails} = await createOidcInteractionContextFixture();
276
+
277
+ await runInContext($ctx, async () => {
278
+ interactionDetails.session.accountId = undefined;
279
+
280
+ const result = await runInContext($ctx, () => oidcCtx.findAccount(undefined, "token"));
281
+
282
+ expect(result).toBeUndefined();
283
+ });
284
+ });
285
+ });
286
+
287
+ describe("getGrant()", () => {
288
+ it("should return call grant from grantId", async () => {
289
+ const {$ctx, oidcCtx} = await createOidcInteractionContextFixture();
290
+ await runInContext($ctx, async () => {
291
+ const result = await oidcCtx.getGrant();
292
+ expect(result).toEqual("grant");
293
+ });
294
+ });
295
+
296
+ it("should create grant", async () => {
297
+ const {$ctx, oidcCtx} = await createOidcInteractionContextFixture(null);
298
+ await runInContext($ctx, async () => {
299
+ const result = await oidcCtx.getGrant();
300
+ expect(result).toEqual({});
301
+ });
302
+ });
303
+ });
304
+ });
@@ -0,0 +1,206 @@
1
+ import {Env} from "@tsed/core";
2
+ import {constant, context, inject, Injectable} from "@tsed/di";
3
+ import {Unauthorized} from "@tsed/exceptions";
4
+ import {PlatformContext} from "@tsed/platform-http";
5
+ import omit from "lodash/omit.js";
6
+ import type {Account, default as Provider, InteractionResults, PromptDetail} from "oidc-provider";
7
+
8
+ import {
9
+ INTERACTION_CONTEXT,
10
+ INTERACTION_DETAILS,
11
+ INTERACTION_GRANT_ID,
12
+ INTERACTION_PARAMS,
13
+ INTERACTION_PROMPT,
14
+ INTERACTION_SESSION,
15
+ INTERACTION_UID
16
+ } from "../constants/constants.js";
17
+ import {OidcSession} from "../decorators/oidcSession.js";
18
+ import {OidcClient, OidcInteraction} from "../domain/interfaces.js";
19
+ import {OidcBadInteractionName} from "../domain/OidcBadInteractionName.js";
20
+ import {OidcInteractionPromptProps} from "../domain/OidcInteractionPromptProps.js";
21
+ import {debug} from "../utils/debug.js";
22
+ import {OidcInteractions} from "./OidcInteractions.js";
23
+ import {OidcProvider} from "./OidcProvider.js";
24
+
25
+ @Injectable()
26
+ export class OidcInteractionContext {
27
+ protected env = constant<Env>("env");
28
+ protected oidcProvider = inject(OidcProvider);
29
+ protected oidcInteractions = inject(OidcInteractions);
30
+
31
+ get $ctx() {
32
+ return context<PlatformContext>();
33
+ }
34
+
35
+ get raw(): OidcInteraction {
36
+ return this.$ctx.get(INTERACTION_DETAILS)!;
37
+ }
38
+
39
+ get session(): OidcSession | undefined {
40
+ return this.raw.session as any;
41
+ }
42
+
43
+ get prompt(): PromptDetail {
44
+ return this.raw.prompt;
45
+ }
46
+
47
+ get params(): Record<string, any> {
48
+ return this.raw.params;
49
+ }
50
+
51
+ get uid(): string {
52
+ return this.raw.uid;
53
+ }
54
+
55
+ get grantId(): string {
56
+ return (this.raw as any).grantId;
57
+ }
58
+
59
+ async runInteraction(name?: string) {
60
+ name = name || this.prompt.name;
61
+
62
+ const handler = this.oidcInteractions.getInteractionHandler(name);
63
+
64
+ if (handler) {
65
+ this.raw.prompt = {
66
+ ...this.raw.prompt,
67
+ name,
68
+ reasons: [name]
69
+ };
70
+
71
+ await handler(this.$ctx);
72
+ }
73
+ }
74
+
75
+ async interactionDetails(): Promise<OidcInteraction> {
76
+ const raw = await this.oidcProvider.get().interactionDetails(this.$ctx.getReq(), this.$ctx.getRes());
77
+ const {uid, prompt, params, session, grantId} = raw as any;
78
+
79
+ this.$ctx.set(INTERACTION_CONTEXT, this);
80
+ this.$ctx.set(INTERACTION_DETAILS, raw);
81
+ this.$ctx.set(INTERACTION_UID, uid);
82
+ this.$ctx.set(INTERACTION_PROMPT, prompt);
83
+ this.$ctx.set(INTERACTION_PARAMS, params);
84
+ this.$ctx.set(INTERACTION_GRANT_ID, grantId);
85
+ this.$ctx.set(INTERACTION_SESSION, session);
86
+
87
+ return raw;
88
+ }
89
+
90
+ interactionFinished(
91
+ result: InteractionResults,
92
+ options: {
93
+ mergeWithLastSubmission?: boolean;
94
+ } = {mergeWithLastSubmission: false}
95
+ ) {
96
+ return this.oidcProvider.get().interactionFinished(this.$ctx.getReq(), this.$ctx.getRes(), result, options);
97
+ }
98
+
99
+ interactionResult(
100
+ result: InteractionResults,
101
+ options: {
102
+ mergeWithLastSubmission?: boolean;
103
+ } = {mergeWithLastSubmission: false}
104
+ ) {
105
+ return this.oidcProvider.get().interactionResult(this.$ctx.getReq(), this.$ctx.getRes(), result, options);
106
+ }
107
+
108
+ async interactionPrompt({client, ...options}: Record<string, any>): Promise<OidcInteractionPromptProps> {
109
+ client = client || (await this.findClient());
110
+
111
+ const omitClientProps = constant("oidc.render.omitClientProps", []);
112
+
113
+ return {
114
+ client: omit(client, ["clientSecret", ...omitClientProps]),
115
+ uid: this.uid,
116
+ grantId: this.grantId,
117
+ details: this.prompt.details,
118
+ params: {
119
+ ...this.params,
120
+ ...options.params
121
+ },
122
+ ...options,
123
+ ...this.debug()
124
+ };
125
+ }
126
+
127
+ render(view: string, result: any): Promise<string> {
128
+ return this.$ctx.response.render(view, result);
129
+ }
130
+
131
+ save(ttl: number): Promise<string> {
132
+ return this.raw.save(ttl);
133
+ }
134
+
135
+ findClient(clientId: string = this.params.client_id): Promise<OidcClient | undefined> {
136
+ const key = `$client:${clientId}`;
137
+
138
+ return this.$ctx.cacheAsync(key, () => this.oidcProvider.get().Client.find(clientId));
139
+ }
140
+
141
+ findAccount(sub?: string, token?: any): Promise<Account | undefined> {
142
+ if (!sub && this.session) {
143
+ sub = this.session?.accountId as any;
144
+ }
145
+
146
+ if (!sub) {
147
+ return Promise.resolve(undefined);
148
+ }
149
+
150
+ const key = `$account:${sub}`;
151
+
152
+ return this.$ctx.cacheAsync<Account | undefined>(key, (() => {
153
+ return this.oidcProvider.get().Account.findAccount(undefined as any, sub!, token);
154
+ }) as any);
155
+ }
156
+
157
+ getGrant(): Promise<InstanceType<Provider["Grant"]>> {
158
+ const {Grant} = this.oidcProvider.get() as any;
159
+
160
+ if (this.grantId) {
161
+ // we'll be modifying existing grant in existing session
162
+ // @ts-ignore
163
+ return Grant.find(this.grantId);
164
+ }
165
+
166
+ return Promise.resolve(
167
+ new Grant({
168
+ accountId: this.session?.accountId,
169
+ clientId: this.params.client_id
170
+ })
171
+ );
172
+ }
173
+
174
+ checkInteractionName(name: string) {
175
+ if (this.prompt.name !== name) {
176
+ throw new OidcBadInteractionName("Bad interaction name");
177
+ }
178
+ }
179
+
180
+ async checkClientId(clientId = this.params.client_id) {
181
+ const client = await this.findClient(clientId);
182
+
183
+ if (!client) {
184
+ throw new Unauthorized(`Unknown client_id ${clientId}`);
185
+ }
186
+ }
187
+
188
+ debug(obj?: any): any {
189
+ /* istanbul ignore next */
190
+ if (this.env === Env.PROD) {
191
+ return {session: undefined, dbg: {params: undefined, prompt: undefined}};
192
+ }
193
+
194
+ if (obj) {
195
+ return debug(obj);
196
+ }
197
+
198
+ return {
199
+ session: this.session ? this.debug(this.session) : undefined,
200
+ dbg: {
201
+ params: this.debug(this.params),
202
+ prompt: this.debug(this.prompt)
203
+ }
204
+ };
205
+ }
206
+ }
@@ -0,0 +1,57 @@
1
+ import {Env} from "@tsed/core";
2
+ import {constant, Injectable, injector, Provider, TokenProvider} from "@tsed/di";
3
+ import {PlatformContext, PlatformHandler} from "@tsed/platform-http";
4
+ import {EndpointMetadata} from "@tsed/schema";
5
+
6
+ import {INTERACTION, INTERACTION_OPTIONS, INTERACTIONS} from "../constants/constants.js";
7
+ import {OidcInteractionOptions} from "../domain/OidcInteractionOptions.js";
8
+
9
+ @Injectable()
10
+ export class OidcInteractions {
11
+ protected injector = injector();
12
+ protected env = constant<Env>("env");
13
+ protected interactions: Map<string, Provider> = new Map();
14
+
15
+ $onInit(): void {
16
+ const platformHandler = this.injector.get<PlatformHandler>(PlatformHandler)!;
17
+
18
+ this.getInteractions().forEach((provider: Provider) => {
19
+ const {name} = provider.store.get<OidcInteractionOptions>(INTERACTION_OPTIONS);
20
+ this.interactions.set(name, provider);
21
+
22
+ if (this.injector.get(provider.token)?.$prompt) {
23
+ provider.store.set("$prompt", platformHandler.createCustomHandler(provider, "$prompt"));
24
+ }
25
+ });
26
+ }
27
+
28
+ getInteractions(): Provider[] {
29
+ const interactionsProvider = this.injector.getProviders().find((provider) => provider.subType === INTERACTIONS);
30
+
31
+ /* istanbul ignore next */
32
+ if (!interactionsProvider) {
33
+ return [];
34
+ }
35
+
36
+ return interactionsProvider.children
37
+ .map((token: TokenProvider) => this.injector.getProvider(token)!)
38
+ .filter((provider: Provider) => provider?.subType === INTERACTION);
39
+ }
40
+
41
+ getInteractionProvider(name: string): Provider | undefined {
42
+ return this.interactions.get(name);
43
+ }
44
+
45
+ getInteractionHandler(name: string) {
46
+ const interaction = this.getInteractionProvider(name);
47
+
48
+ if (interaction) {
49
+ const endpoint = EndpointMetadata.get(interaction.useClass, "$prompt");
50
+ return (ctx: PlatformContext) => {
51
+ // Add current endpoint metadata to ctx
52
+ ctx.endpoint = endpoint;
53
+ return interaction.store.get("$prompt")(ctx);
54
+ };
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,21 @@
1
+ import {constant, Injectable} from "@tsed/di";
2
+ import {getJwks, JwksKeyParameters} from "@tsed/jwks";
3
+ import {join} from "path";
4
+
5
+ @Injectable()
6
+ export class OidcJwks {
7
+ public jwksPath: string = constant("oidc.jwksPath", join(process.cwd(), "keys", "jwks.json"));
8
+ public certificates?: JwksKeyParameters[] = constant("oidc.certificates");
9
+ public keys: string;
10
+
11
+ $onInit() {
12
+ return this.getJwks();
13
+ }
14
+
15
+ getJwks() {
16
+ return getJwks({
17
+ path: this.jwksPath,
18
+ certificates: this.certificates
19
+ });
20
+ }
21
+ }