@flink-app/oidc-plugin 2.0.0-alpha.117 → 2.0.0-alpha.118
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/CHANGELOG.md +47 -0
- package/README.md +296 -17
- package/dist/OidcPlugin.d.ts.map +1 -1
- package/dist/OidcPlugin.js +35 -2
- package/dist/OidcPluginContext.d.ts +17 -0
- package/dist/OidcPluginContext.d.ts.map +1 -1
- package/dist/OidcPluginOptions.d.ts +123 -3
- package/dist/OidcPluginOptions.d.ts.map +1 -1
- package/dist/handlers/CallbackOidc.d.ts.map +1 -1
- package/dist/handlers/CallbackOidc.js +97 -20
- package/dist/handlers/InitiateOidc.d.ts.map +1 -1
- package/dist/handlers/InitiateOidc.js +12 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/providers/ProviderRegistry.d.ts +27 -4
- package/dist/providers/ProviderRegistry.d.ts.map +1 -1
- package/dist/providers/ProviderRegistry.js +77 -21
- package/dist/utils/error-utils.d.ts +1 -0
- package/dist/utils/error-utils.d.ts.map +1 -1
- package/dist/utils/error-utils.js +1 -0
- package/dist/utils/redirect-uri-utils.d.ts +38 -0
- package/dist/utils/redirect-uri-utils.d.ts.map +1 -0
- package/dist/utils/redirect-uri-utils.js +92 -0
- package/examples/basic-oidc.ts +4 -0
- package/examples/multi-provider.ts +4 -0
- package/package.json +6 -6
- package/spec/handlers/CallbackOidc.spec.ts +330 -0
- package/spec/handlers/InitiateOidc.spec.ts +95 -1
- package/spec/helpers/test-helpers.ts +68 -0
- package/spec/plugin/OidcPlugin.spec.ts +165 -0
- package/spec/providers/ProviderRegistry.spec.ts +142 -0
- package/spec/utils/redirect-uri-utils.spec.ts +98 -0
- package/src/OidcPlugin.ts +38 -1
- package/src/OidcPluginContext.ts +18 -0
- package/src/OidcPluginOptions.ts +132 -3
- package/src/handlers/CallbackOidc.ts +109 -20
- package/src/handlers/InitiateOidc.ts +14 -3
- package/src/index.ts +10 -1
- package/src/providers/ProviderRegistry.ts +95 -22
- package/src/utils/error-utils.ts +1 -0
- package/src/utils/redirect-uri-utils.ts +116 -0
|
@@ -2,6 +2,8 @@ import OidcProfile from "./schemas/OidcProfile";
|
|
|
2
2
|
import OidcTokenSet from "./schemas/OidcTokenSet";
|
|
3
3
|
import { OidcProviderConfig } from "./OidcProviderConfig";
|
|
4
4
|
import { TokenDeliveryMode } from "./utils/response-utils";
|
|
5
|
+
import { AllowedRedirectUris } from "./utils/redirect-uri-utils";
|
|
6
|
+
import { FlinkResponse } from "@flink-app/flink";
|
|
5
7
|
/**
|
|
6
8
|
* OIDC error information passed to onAuthError callback
|
|
7
9
|
*/
|
|
@@ -20,10 +22,10 @@ export interface OidcError {
|
|
|
20
22
|
details?: any;
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
+
* Default completion: the plugin delivers the JWT token generated by the application
|
|
26
|
+
* via jwt-auth-plugin, according to `tokenDelivery` (or as JSON for `?response_type=json`).
|
|
25
27
|
*/
|
|
26
|
-
export interface
|
|
28
|
+
export interface AuthSuccessTokenResponse {
|
|
27
29
|
/**
|
|
28
30
|
* User object from your application
|
|
29
31
|
* Should include _id field for connection storage
|
|
@@ -42,6 +44,54 @@ export interface AuthSuccessCallbackResponse {
|
|
|
42
44
|
*/
|
|
43
45
|
redirectUrl?: string;
|
|
44
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Verbatim redirect completion: the plugin redirects to `redirectUrl` exactly as given,
|
|
49
|
+
* without attaching any token. Use when the application has already handed the session
|
|
50
|
+
* over some other way — a one-time code it put in the URL, a server-side session keyed
|
|
51
|
+
* by something in the URL, and so on.
|
|
52
|
+
*
|
|
53
|
+
* The URL is still subject to the `allowedRedirectUris` check.
|
|
54
|
+
*/
|
|
55
|
+
export interface AuthSuccessRedirectResponse {
|
|
56
|
+
/**
|
|
57
|
+
* User object from your application
|
|
58
|
+
* Should include _id field for connection storage
|
|
59
|
+
*/
|
|
60
|
+
user: any;
|
|
61
|
+
/**
|
|
62
|
+
* URL to redirect to, used exactly as given (no token is spliced in)
|
|
63
|
+
*/
|
|
64
|
+
redirectUrl: string;
|
|
65
|
+
/**
|
|
66
|
+
* Must not be set — a token means the default token completion instead
|
|
67
|
+
*/
|
|
68
|
+
token?: undefined;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Custom completion: the application owns the entire HTTP response — anything a Flink
|
|
72
|
+
* handler may return, e.g. a redirect plus a `Set-Cookie` header, or a login envelope
|
|
73
|
+
* its clients already parse.
|
|
74
|
+
*/
|
|
75
|
+
export interface AuthSuccessCustomResponse {
|
|
76
|
+
/**
|
|
77
|
+
* User object from your application
|
|
78
|
+
* Should include _id field for connection storage
|
|
79
|
+
*/
|
|
80
|
+
user: any;
|
|
81
|
+
/**
|
|
82
|
+
* The response to send, returned as-is by the callback handler
|
|
83
|
+
*/
|
|
84
|
+
response: FlinkResponse;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Response from onAuthSuccess callback
|
|
88
|
+
*
|
|
89
|
+
* Three shapes are supported:
|
|
90
|
+
* 1. `{ user, token, redirectUrl? }` — the plugin delivers the token (default)
|
|
91
|
+
* 2. `{ user, redirectUrl }` — the plugin redirects verbatim, no token attached
|
|
92
|
+
* 3. `{ user, response }` — the application builds the whole response
|
|
93
|
+
*/
|
|
94
|
+
export type AuthSuccessCallbackResponse = AuthSuccessTokenResponse | AuthSuccessRedirectResponse | AuthSuccessCustomResponse;
|
|
45
95
|
/**
|
|
46
96
|
* Response from onAuthError callback
|
|
47
97
|
*/
|
|
@@ -51,6 +101,12 @@ export interface AuthErrorCallbackResponse {
|
|
|
51
101
|
* e.g., "/login?error=authentication_failed"
|
|
52
102
|
*/
|
|
53
103
|
redirectUrl?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Optional complete response to send instead, returned as-is by the callback handler.
|
|
106
|
+
* Takes precedence over `redirectUrl`. Use for error completions the plugin cannot
|
|
107
|
+
* express, e.g. clearing a session cookie alongside the redirect.
|
|
108
|
+
*/
|
|
109
|
+
response?: FlinkResponse;
|
|
54
110
|
}
|
|
55
111
|
/**
|
|
56
112
|
* Configuration options for OIDC Plugin with JWT integration
|
|
@@ -85,6 +141,40 @@ export interface OidcPluginOptions<TCtx = any> {
|
|
|
85
141
|
* }
|
|
86
142
|
*/
|
|
87
143
|
providers?: Record<string, OidcProviderConfig>;
|
|
144
|
+
/**
|
|
145
|
+
* Which `?redirectUri=` values the initiate endpoint accepts.
|
|
146
|
+
*
|
|
147
|
+
* The `redirectUri` decides where the JWT is delivered once the flow completes, and
|
|
148
|
+
* anyone can craft an initiate link — so without an allow-list a crafted link turns a
|
|
149
|
+
* legitimate login into token exfiltration. Set this on every deployment.
|
|
150
|
+
*
|
|
151
|
+
* Entries are matched as:
|
|
152
|
+
* - an exact URI (`https://app.example.com/login`), or
|
|
153
|
+
* - a bare origin (`https://app.example.com`, `myapp://cb`), which covers every path,
|
|
154
|
+
* query and fragment below that origin.
|
|
155
|
+
*
|
|
156
|
+
* A predicate can be used for anything else.
|
|
157
|
+
*
|
|
158
|
+
* Always accepted regardless of the list:
|
|
159
|
+
* - relative paths (`/dashboard`) — they can only land on this app's own origin
|
|
160
|
+
* - the provider's own `callbackUrl` (the fallback when no `redirectUri` is passed)
|
|
161
|
+
*
|
|
162
|
+
* The same check is applied to a `redirectUrl` returned by `onAuthSuccess` /
|
|
163
|
+
* `onAuthError` when it differs from the one stored on the session, so echoing an
|
|
164
|
+
* attacker-supplied value back cannot bypass the list.
|
|
165
|
+
*
|
|
166
|
+
* Default: undefined — every redirectUri is accepted (logged as a warning at startup).
|
|
167
|
+
*
|
|
168
|
+
* Example:
|
|
169
|
+
* ```typescript
|
|
170
|
+
* allowedRedirectUris: [
|
|
171
|
+
* "https://app.example.com", // any path on this origin
|
|
172
|
+
* "https://admin.example.com/auth-callback",
|
|
173
|
+
* "myapp://oidc-callback" // native app scheme
|
|
174
|
+
* ]
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
allowedRedirectUris?: AllowedRedirectUris;
|
|
88
178
|
/**
|
|
89
179
|
* Whether to store OIDC tokens for future API access
|
|
90
180
|
* If false, tokens are discarded after authentication (auth-only mode)
|
|
@@ -107,6 +197,15 @@ export interface OidcPluginOptions<TCtx = any> {
|
|
|
107
197
|
* 3. Generate JWT token using ctx.plugins.jwtAuth.createToken(payload, roles)
|
|
108
198
|
* 4. Return user object, JWT token, and optional redirect URL
|
|
109
199
|
*
|
|
200
|
+
* Applications that complete the login themselves can return one of two other shapes
|
|
201
|
+
* instead of a `token`:
|
|
202
|
+
* - `{ user, redirectUrl }` — the plugin redirects there verbatim, attaching nothing
|
|
203
|
+
* (e.g. the URL carries a short-lived one-time code the client exchanges for a session)
|
|
204
|
+
* - `{ user, response }` — the application returns the whole HTTP response
|
|
205
|
+
* (e.g. a redirect plus a `Set-Cookie` header)
|
|
206
|
+
*
|
|
207
|
+
* See {@link AuthSuccessCallbackResponse}.
|
|
208
|
+
*
|
|
110
209
|
* @param params - OIDC profile, claims, provider name, and tokens (if storeTokens enabled)
|
|
111
210
|
* @param ctx - Flink context with access to repos and plugins (including jwtAuth)
|
|
112
211
|
* @returns User object, JWT token, and optional redirect URL
|
|
@@ -260,6 +359,27 @@ export interface OidcPluginOptions<TCtx = any> {
|
|
|
260
359
|
* ```
|
|
261
360
|
*/
|
|
262
361
|
providerLoader?: (providerName: string, ctx: TCtx) => Promise<OidcProviderConfig | null>;
|
|
362
|
+
/**
|
|
363
|
+
* Seconds a resolved provider (static or from `providerLoader`) is reused before its
|
|
364
|
+
* config is loaded and OIDC discovery is run again.
|
|
365
|
+
*
|
|
366
|
+
* Default: 0 — cache for the life of the process (unchanged behaviour).
|
|
367
|
+
*
|
|
368
|
+
* Set this when provider configs live in a database and can change at runtime:
|
|
369
|
+
* without a TTL, editing an issuer, client id, client secret, scope or discovery URL
|
|
370
|
+
* only takes effect after a restart of every instance.
|
|
371
|
+
*
|
|
372
|
+
* Reloading happens lazily on the next request for that provider. If the reload
|
|
373
|
+
* fails (IdP unreachable, database hiccup), the previously cached instance keeps
|
|
374
|
+
* being used and the next attempt happens after another TTL — a discovery hiccup
|
|
375
|
+
* does not break logins that would otherwise work.
|
|
376
|
+
*
|
|
377
|
+
* For an immediate update on the instance handling the change, call
|
|
378
|
+
* `ctx.plugins.oidc.invalidateProvider(name)`; other instances converge within the TTL.
|
|
379
|
+
*
|
|
380
|
+
* Example: `providerCacheTtlSec: 300` (5 minutes)
|
|
381
|
+
*/
|
|
382
|
+
providerCacheTtlSec?: number;
|
|
263
383
|
/**
|
|
264
384
|
* Custom collection name for OIDC sessions
|
|
265
385
|
* Default: 'oidc_sessions'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OidcPluginOptions.d.ts","sourceRoot":"","sources":["../src/OidcPluginOptions.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,uBAAuB,CAAC;AAChD,OAAO,YAAY,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"OidcPluginOptions.d.ts","sourceRoot":"","sources":["../src/OidcPluginOptions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CallbackOidc.d.ts","sourceRoot":"","sources":["../../src/handlers/CallbackOidc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAc,UAAU,EAAwC,MAAM,kBAAkB,CAAC;AAC5G,OAAO,eAAe,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"CallbackOidc.d.ts","sourceRoot":"","sources":["../../src/handlers/CallbackOidc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAc,UAAU,EAAwC,MAAM,kBAAkB,CAAC;AAC5G,OAAO,eAAe,MAAM,4BAA4B,CAAC;AAQzD;;GAEG;AACH,UAAU,UAAU;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,UAGnB,CAAC;AAEF;;;;;;GAMG;AACH,QAAA,MAAM,YAAY,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,eAAe,CAqWnE,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -20,6 +20,7 @@ const state_utils_1 = require("../utils/state-utils");
|
|
|
20
20
|
const response_utils_1 = require("../utils/response-utils");
|
|
21
21
|
const encryption_utils_1 = require("../utils/encryption-utils");
|
|
22
22
|
const error_utils_1 = require("../utils/error-utils");
|
|
23
|
+
const redirect_uri_utils_1 = require("../utils/redirect-uri-utils");
|
|
23
24
|
const log_1 = require("../log");
|
|
24
25
|
/**
|
|
25
26
|
* Route configuration
|
|
@@ -42,6 +43,21 @@ const CallbackOidc = async ({ ctx, req }) => {
|
|
|
42
43
|
// Track session outside try/catch so redirectUri and metadata are available in error handling
|
|
43
44
|
let sessionRedirectUri;
|
|
44
45
|
let sessionMetadata = {};
|
|
46
|
+
/**
|
|
47
|
+
* Apply the `allowedRedirectUris` allow-list to a redirect target built by the host
|
|
48
|
+
* (the `redirectUrl` returned by onAuthSuccess / onAuthError), so a host that echoes
|
|
49
|
+
* back an attacker-supplied value cannot bypass the list by accident.
|
|
50
|
+
*
|
|
51
|
+
* The redirectUri stored on the session was already validated at initiate time, as is
|
|
52
|
+
* the provider's own callbackUrl — both are always accepted here.
|
|
53
|
+
*/
|
|
54
|
+
const isRedirectAllowed = (url, callbackUrl) => {
|
|
55
|
+
const { options } = ctx.plugins.oidc;
|
|
56
|
+
return (0, redirect_uri_utils_1.isRedirectUriAllowed)(url, provider, options.allowedRedirectUris, [
|
|
57
|
+
callbackUrl || options.providers?.[provider]?.callbackUrl,
|
|
58
|
+
sessionRedirectUri,
|
|
59
|
+
]);
|
|
60
|
+
};
|
|
45
61
|
try {
|
|
46
62
|
// Validate provider and response_type
|
|
47
63
|
(0, error_utils_1.validateProvider)(provider);
|
|
@@ -69,15 +85,24 @@ const CallbackOidc = async ({ ctx, req }) => {
|
|
|
69
85
|
redirectUri: sessionRedirectUri,
|
|
70
86
|
metadata: sessionMetadata,
|
|
71
87
|
});
|
|
88
|
+
if (errorResult.response) {
|
|
89
|
+
log_1.oidcLog.debug("Callback: responding with host-built error response");
|
|
90
|
+
return errorResult.response;
|
|
91
|
+
}
|
|
72
92
|
if (errorResult.redirectUrl) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
93
|
+
if (!isRedirectAllowed(errorResult.redirectUrl)) {
|
|
94
|
+
flink_1.log.error(`OIDC callback: onAuthError returned a redirectUrl that is not allowed, ignoring it: ${errorResult.redirectUrl}`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
return {
|
|
98
|
+
status: 302,
|
|
99
|
+
headers: { Location: errorResult.redirectUrl },
|
|
100
|
+
data: {},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
78
103
|
}
|
|
79
104
|
}
|
|
80
|
-
return (0, flink_1.badRequest)(error.message);
|
|
105
|
+
return (0, flink_1.badRequest)(error.message, error.code);
|
|
81
106
|
}
|
|
82
107
|
// Validate required parameters
|
|
83
108
|
if (!code || !state) {
|
|
@@ -152,19 +177,34 @@ const CallbackOidc = async ({ ctx, req }) => {
|
|
|
152
177
|
redirectUri: session.redirectUri,
|
|
153
178
|
metadata: sessionMetadata,
|
|
154
179
|
});
|
|
180
|
+
if (errorResult.response) {
|
|
181
|
+
log_1.oidcLog.debug("Callback: responding with host-built error response");
|
|
182
|
+
return errorResult.response;
|
|
183
|
+
}
|
|
155
184
|
if (errorResult.redirectUrl) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
185
|
+
if (!isRedirectAllowed(errorResult.redirectUrl)) {
|
|
186
|
+
flink_1.log.error(`OIDC callback: onAuthError returned a redirectUrl that is not allowed, ignoring it: ${errorResult.redirectUrl}`);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
return {
|
|
190
|
+
status: 302,
|
|
191
|
+
headers: { Location: errorResult.redirectUrl },
|
|
192
|
+
data: {},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
161
195
|
}
|
|
162
196
|
}
|
|
163
197
|
return (0, flink_1.internalServerError)("Authentication failed. Please try again.");
|
|
164
198
|
}
|
|
165
|
-
// Extract
|
|
166
|
-
|
|
167
|
-
|
|
199
|
+
// Extract the completion the host asked for. Three shapes are supported:
|
|
200
|
+
// 1. `token` — the plugin delivers it (fragment/query/JSON)
|
|
201
|
+
// 2. `redirectUrl` without a token — redirect there verbatim, attaching nothing
|
|
202
|
+
// 3. `response` — the host owns the whole HTTP response (Set-Cookie, custom envelope, ...)
|
|
203
|
+
const { user } = authResult;
|
|
204
|
+
const token = "token" in authResult ? authResult.token : undefined;
|
|
205
|
+
const redirectUrl = "redirectUrl" in authResult ? authResult.redirectUrl : undefined;
|
|
206
|
+
const hostResponse = "response" in authResult ? authResult.response : undefined;
|
|
207
|
+
if (!token && !redirectUrl && !hostResponse) {
|
|
168
208
|
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.JWT_GENERATION_FAILED, "No authentication token returned from callback", { hasUser: !!user });
|
|
169
209
|
}
|
|
170
210
|
// Store OIDC connection if token storage is enabled
|
|
@@ -214,7 +254,35 @@ const CallbackOidc = async ({ ctx, req }) => {
|
|
|
214
254
|
}
|
|
215
255
|
}
|
|
216
256
|
}
|
|
257
|
+
// Shape 3: the host built the whole response — send it as-is
|
|
258
|
+
if (hostResponse) {
|
|
259
|
+
log_1.oidcLog.debug(`Callback: auth complete, responding with host-built response (status=${hostResponse.status ?? 200})`);
|
|
260
|
+
return hostResponse;
|
|
261
|
+
}
|
|
262
|
+
// Shape 2: verbatim redirect, nothing attached
|
|
263
|
+
if (!token) {
|
|
264
|
+
if (response_type === "json") {
|
|
265
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.INVALID_RESPONSE_TYPE, "The application completed the login without a token, so JSON mode is not available for this callback", { provider });
|
|
266
|
+
}
|
|
267
|
+
if (!isRedirectAllowed(redirectUrl, oidcProvider.config?.callbackUrl)) {
|
|
268
|
+
flink_1.log.error(`OIDC callback: onAuthSuccess returned a redirectUrl that is not allowed: ${redirectUrl}`);
|
|
269
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.INVALID_REDIRECT_URI, "The redirect URL is not allowed", { redirectUrl, provider });
|
|
270
|
+
}
|
|
271
|
+
log_1.oidcLog.debug(`Callback: auth complete, redirecting verbatim to "${redirectUrl}" (no token attached)`);
|
|
272
|
+
return {
|
|
273
|
+
status: 302,
|
|
274
|
+
headers: { Location: redirectUrl },
|
|
275
|
+
data: {},
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
// Shape 1: the plugin delivers the token
|
|
217
279
|
const finalRedirectUrl = redirectUrl || session.redirectUri;
|
|
280
|
+
// Only the redirect response can leak the token to a foreign origin — the JSON
|
|
281
|
+
// response never uses finalRedirectUrl, so it is not subject to the allow-list.
|
|
282
|
+
if (response_type !== "json" && !isRedirectAllowed(finalRedirectUrl, oidcProvider.config?.callbackUrl)) {
|
|
283
|
+
flink_1.log.error(`OIDC callback: onAuthSuccess returned a redirectUrl that is not allowed: ${finalRedirectUrl}`);
|
|
284
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.INVALID_REDIRECT_URI, "The redirect URL is not allowed", { redirectUrl: finalRedirectUrl, provider });
|
|
285
|
+
}
|
|
218
286
|
log_1.oidcLog.debug(`Callback: auth complete, responding via ${response_type === "json" ? "JSON" : `redirect to "${finalRedirectUrl}"`}`);
|
|
219
287
|
// Resolve token delivery mode: literal, function, or default "fragment".
|
|
220
288
|
// The plugin stays a dumb transport — the host app makes the policy decision.
|
|
@@ -243,19 +311,28 @@ const CallbackOidc = async ({ ctx, req }) => {
|
|
|
243
311
|
redirectUri: sessionRedirectUri,
|
|
244
312
|
metadata: sessionMetadata,
|
|
245
313
|
});
|
|
314
|
+
if (errorResult.response) {
|
|
315
|
+
log_1.oidcLog.debug("Callback: responding with host-built error response");
|
|
316
|
+
return errorResult.response;
|
|
317
|
+
}
|
|
246
318
|
if (errorResult.redirectUrl) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
319
|
+
if (!isRedirectAllowed(errorResult.redirectUrl)) {
|
|
320
|
+
flink_1.log.error(`OIDC callback: onAuthError returned a redirectUrl that is not allowed, ignoring it: ${errorResult.redirectUrl}`);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
return {
|
|
324
|
+
status: 302,
|
|
325
|
+
headers: { Location: errorResult.redirectUrl },
|
|
326
|
+
data: {},
|
|
327
|
+
};
|
|
328
|
+
}
|
|
252
329
|
}
|
|
253
330
|
}
|
|
254
331
|
catch (callbackError) {
|
|
255
332
|
flink_1.log.error("onAuthError callback failed:", callbackError);
|
|
256
333
|
}
|
|
257
334
|
}
|
|
258
|
-
return (0, flink_1.badRequest)(error.message);
|
|
335
|
+
return (0, flink_1.badRequest)(error.message, error.code);
|
|
259
336
|
}
|
|
260
337
|
// Handle provider errors
|
|
261
338
|
const mappedError = (0, error_utils_1.handleProviderError)(error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InitiateOidc.d.ts","sourceRoot":"","sources":["../../src/handlers/InitiateOidc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAc,UAAU,EAAmC,MAAM,kBAAkB,CAAC;AACvG,OAAO,eAAe,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"InitiateOidc.d.ts","sourceRoot":"","sources":["../../src/handlers/InitiateOidc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAc,UAAU,EAAmC,MAAM,kBAAkB,CAAC;AACvG,OAAO,eAAe,MAAM,4BAA4B,CAAC;AAOzD;;GAEG;AACH,UAAU,UAAU;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,UAGnB,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,YAAY,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,eAAe,CA4FnE,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -16,6 +16,7 @@ exports.Route = void 0;
|
|
|
16
16
|
const flink_1 = require("@flink-app/flink");
|
|
17
17
|
const state_utils_1 = require("../utils/state-utils");
|
|
18
18
|
const error_utils_1 = require("../utils/error-utils");
|
|
19
|
+
const redirect_uri_utils_1 = require("../utils/redirect-uri-utils");
|
|
19
20
|
const openid_client_1 = require("openid-client");
|
|
20
21
|
const log_1 = require("../log");
|
|
21
22
|
/**
|
|
@@ -50,7 +51,15 @@ const InitiateOidc = async ({ ctx, req }) => {
|
|
|
50
51
|
const { options } = ctx.plugins.oidc;
|
|
51
52
|
// Determine redirect URI (use provided or default to callback URL)
|
|
52
53
|
const staticProviderConfig = options.providers?.[provider];
|
|
53
|
-
const
|
|
54
|
+
const callbackUrl = oidcProvider?.config?.callbackUrl || staticProviderConfig?.callbackUrl;
|
|
55
|
+
// The redirectUri decides where the JWT ends up, and the query param is
|
|
56
|
+
// attacker-controllable — validate it against the configured allow-list
|
|
57
|
+
// before anything is persisted.
|
|
58
|
+
if (redirectUri && !(0, redirect_uri_utils_1.isRedirectUriAllowed)(redirectUri, provider, options.allowedRedirectUris, [callbackUrl])) {
|
|
59
|
+
log_1.oidcLog.debug(`Initiate: rejected redirectUri="${redirectUri}" (not in allowedRedirectUris)`);
|
|
60
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.INVALID_REDIRECT_URI, "The provided redirectUri is not allowed", { redirectUri, provider });
|
|
61
|
+
}
|
|
62
|
+
const finalRedirectUri = redirectUri || callbackUrl || `${req.protocol}://${req.get("host")}/oidc/${provider}/callback`;
|
|
54
63
|
// Collect meta.* query params as opaque metadata (prefix stripped)
|
|
55
64
|
const metadata = {};
|
|
56
65
|
for (const [key, value] of Object.entries(req.query)) {
|
|
@@ -58,7 +67,7 @@ const InitiateOidc = async ({ ctx, req }) => {
|
|
|
58
67
|
metadata[key.slice(5)] = value;
|
|
59
68
|
}
|
|
60
69
|
}
|
|
61
|
-
log_1.oidcLog.debug(`Initiate: resolved redirectUri="${finalRedirectUri}" (source: ${redirectUri ? "query param" :
|
|
70
|
+
log_1.oidcLog.debug(`Initiate: resolved redirectUri="${finalRedirectUri}" (source: ${redirectUri ? "query param" : callbackUrl ? "provider config" : "auto-detected"})`);
|
|
62
71
|
// Generate cryptographically secure parameters
|
|
63
72
|
const state = (0, state_utils_1.generateState)();
|
|
64
73
|
const sessionId = (0, state_utils_1.generateSessionId)();
|
|
@@ -95,7 +104,7 @@ const InitiateOidc = async ({ ctx, req }) => {
|
|
|
95
104
|
catch (error) {
|
|
96
105
|
// Handle validation errors
|
|
97
106
|
if (error.code && Object.values(error_utils_1.OidcErrorCodes).includes(error.code)) {
|
|
98
|
-
return (0, flink_1.badRequest)(error.message);
|
|
107
|
+
return (0, flink_1.badRequest)(error.message, error.code);
|
|
99
108
|
}
|
|
100
109
|
// Handle unexpected errors
|
|
101
110
|
return (0, flink_1.internalServerError)(error.message || "Failed to initiate OIDC flow");
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* and optional token storage for API access.
|
|
9
9
|
*/
|
|
10
10
|
export { oidcPlugin } from "./OidcPlugin";
|
|
11
|
-
export { OidcPluginOptions, OidcError, AuthSuccessCallbackResponse, AuthErrorCallbackResponse } from "./OidcPluginOptions";
|
|
11
|
+
export { OidcPluginOptions, OidcError, AuthSuccessCallbackResponse, AuthSuccessTokenResponse, AuthSuccessRedirectResponse, AuthSuccessCustomResponse, AuthErrorCallbackResponse, } from "./OidcPluginOptions";
|
|
12
12
|
export { OidcProviderConfig } from "./OidcProviderConfig";
|
|
13
13
|
export { OidcPluginContext } from "./OidcPluginContext";
|
|
14
14
|
export { default as OidcProfile } from "./schemas/OidcProfile";
|
|
@@ -23,5 +23,6 @@ export { generateState, generateSessionId, generateNonce, validateState } from "
|
|
|
23
23
|
export { encryptToken, decryptToken, validateEncryptionSecret } from "./utils/encryption-utils";
|
|
24
24
|
export { mapClaimsToProfile, extractCustomClaims } from "./utils/claims-mapper";
|
|
25
25
|
export { formatTokenResponse, TokenDeliveryMode } from "./utils/response-utils";
|
|
26
|
+
export { isRedirectUriAllowed, isRelativeRedirect, AllowedRedirectUris } from "./utils/redirect-uri-utils";
|
|
26
27
|
export { createOidcError, validateProvider, handleProviderError, OidcErrorCodes } from "./utils/error-utils";
|
|
27
28
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,OAAO,EACH,iBAAiB,EACjB,SAAS,EACT,2BAA2B,EAC3B,wBAAwB,EACxB,2BAA2B,EAC3B,yBAAyB,EACzB,yBAAyB,GAC5B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGvE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGhE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACrG,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAChG,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAC3G,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* and optional token storage for API access.
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.OidcErrorCodes = exports.handleProviderError = exports.validateProvider = exports.createOidcError = exports.formatTokenResponse = exports.extractCustomClaims = exports.mapClaimsToProfile = exports.validateEncryptionSecret = exports.decryptToken = exports.encryptToken = exports.validateState = exports.generateNonce = exports.generateSessionId = exports.generateState = exports.ProviderRegistry = exports.OidcProvider = exports.oidcPlugin = void 0;
|
|
12
|
+
exports.OidcErrorCodes = exports.handleProviderError = exports.validateProvider = exports.createOidcError = exports.isRelativeRedirect = exports.isRedirectUriAllowed = exports.formatTokenResponse = exports.extractCustomClaims = exports.mapClaimsToProfile = exports.validateEncryptionSecret = exports.decryptToken = exports.encryptToken = exports.validateState = exports.generateNonce = exports.generateSessionId = exports.generateState = exports.ProviderRegistry = exports.OidcProvider = exports.oidcPlugin = void 0;
|
|
13
13
|
// Main plugin factory
|
|
14
14
|
var OidcPlugin_1 = require("./OidcPlugin");
|
|
15
15
|
Object.defineProperty(exports, "oidcPlugin", { enumerable: true, get: function () { return OidcPlugin_1.oidcPlugin; } });
|
|
@@ -33,6 +33,9 @@ Object.defineProperty(exports, "mapClaimsToProfile", { enumerable: true, get: fu
|
|
|
33
33
|
Object.defineProperty(exports, "extractCustomClaims", { enumerable: true, get: function () { return claims_mapper_1.extractCustomClaims; } });
|
|
34
34
|
var response_utils_1 = require("./utils/response-utils");
|
|
35
35
|
Object.defineProperty(exports, "formatTokenResponse", { enumerable: true, get: function () { return response_utils_1.formatTokenResponse; } });
|
|
36
|
+
var redirect_uri_utils_1 = require("./utils/redirect-uri-utils");
|
|
37
|
+
Object.defineProperty(exports, "isRedirectUriAllowed", { enumerable: true, get: function () { return redirect_uri_utils_1.isRedirectUriAllowed; } });
|
|
38
|
+
Object.defineProperty(exports, "isRelativeRedirect", { enumerable: true, get: function () { return redirect_uri_utils_1.isRelativeRedirect; } });
|
|
36
39
|
var error_utils_1 = require("./utils/error-utils");
|
|
37
40
|
Object.defineProperty(exports, "createOidcError", { enumerable: true, get: function () { return error_utils_1.createOidcError; } });
|
|
38
41
|
Object.defineProperty(exports, "validateProvider", { enumerable: true, get: function () { return error_utils_1.validateProvider; } });
|
|
@@ -6,7 +6,7 @@ import { OidcProviderConfig } from "../OidcProviderConfig";
|
|
|
6
6
|
* Handles:
|
|
7
7
|
* - Static provider configuration
|
|
8
8
|
* - Dynamic provider loading from database
|
|
9
|
-
* - Provider instance caching
|
|
9
|
+
* - Provider instance caching (optionally with a TTL)
|
|
10
10
|
* - Lazy initialization
|
|
11
11
|
*/
|
|
12
12
|
export declare class ProviderRegistry {
|
|
@@ -14,22 +14,43 @@ export declare class ProviderRegistry {
|
|
|
14
14
|
private providerInstances;
|
|
15
15
|
private providerLoader?;
|
|
16
16
|
private ctx;
|
|
17
|
-
|
|
17
|
+
private providerCacheTtlSec;
|
|
18
|
+
constructor(staticProviders: Record<string, OidcProviderConfig>, providerLoader?: (providerName: string, ctx: any) => Promise<OidcProviderConfig | null>, ctx?: any, providerCacheTtlSec?: number);
|
|
18
19
|
/**
|
|
19
20
|
* Get provider instance by name
|
|
20
21
|
*
|
|
21
22
|
* Looks up provider in the following order:
|
|
22
|
-
* 1. Cached instance
|
|
23
|
+
* 1. Cached instance (unless it is older than `providerCacheTtlSec`)
|
|
23
24
|
* 2. Static configuration
|
|
24
25
|
* 3. Dynamic loader (if configured)
|
|
25
26
|
*
|
|
26
|
-
* Providers are lazy-initialized on first use and cached.
|
|
27
|
+
* Providers are lazy-initialized on first use and cached. With a cache TTL
|
|
28
|
+
* configured, an expired entry is reloaded on the next request — the config is
|
|
29
|
+
* resolved again (re-running `providerLoader`) and discovery is re-run.
|
|
30
|
+
*
|
|
31
|
+
* If reloading an expired entry fails, the previous instance keeps being used: a
|
|
32
|
+
* transient discovery or database hiccup should not break logins that would
|
|
33
|
+
* otherwise work. The next reload attempt happens after another TTL.
|
|
27
34
|
*
|
|
28
35
|
* @param providerName - Provider identifier
|
|
29
36
|
* @returns Initialized OIDC provider instance
|
|
30
37
|
* @throws Error if provider not found or initialization fails
|
|
31
38
|
*/
|
|
32
39
|
getProvider(providerName: string): Promise<OidcProvider>;
|
|
40
|
+
/**
|
|
41
|
+
* Resolve provider config from static configuration or the dynamic loader
|
|
42
|
+
*/
|
|
43
|
+
private resolveConfig;
|
|
44
|
+
/**
|
|
45
|
+
* Whether a cache entry has outlived the configured TTL.
|
|
46
|
+
* A TTL of 0 (the default) means entries are cached for the life of the process.
|
|
47
|
+
*/
|
|
48
|
+
private isExpired;
|
|
49
|
+
/**
|
|
50
|
+
* Keep serving a previously cached instance when a reload fails.
|
|
51
|
+
* Rethrows when there is nothing cached to fall back on.
|
|
52
|
+
*/
|
|
53
|
+
private keepCachedOnFailure;
|
|
33
54
|
/**
|
|
34
55
|
* Check if provider exists in static configuration or can be loaded dynamically
|
|
35
56
|
*
|
|
@@ -43,6 +64,8 @@ export declare class ProviderRegistry {
|
|
|
43
64
|
* Forces re-initialization of providers on next access.
|
|
44
65
|
* Useful when provider configurations change.
|
|
45
66
|
*
|
|
67
|
+
* Exposed to applications as `ctx.plugins.oidc.invalidateProvider()`.
|
|
68
|
+
*
|
|
46
69
|
* @param providerName - Optional provider to clear (clears all if not specified)
|
|
47
70
|
*/
|
|
48
71
|
clearCache(providerName?: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderRegistry.d.ts","sourceRoot":"","sources":["../../src/providers/ProviderRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"ProviderRegistry.d.ts","sourceRoot":"","sources":["../../src/providers/ProviderRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAa3D;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IACzB,OAAO,CAAC,eAAe,CAAqC;IAC5D,OAAO,CAAC,iBAAiB,CAA0C;IACnE,OAAO,CAAC,cAAc,CAAC,CAAyE;IAChG,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,mBAAmB,CAAS;gBAGhC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACnD,cAAc,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,EACvF,GAAG,CAAC,EAAE,GAAG,EACT,mBAAmB,GAAE,MAAU;IAQnC;;;;;;;;;;;;;;;;;;;OAmBG;IACG,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAsD9D;;OAEG;YACW,aAAa;IAc3B;;;OAGG;IACH,OAAO,CAAC,SAAS;IAQjB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAa3B;;;;;OAKG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI1C;;;;;;;;;OASG;IACH,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI;IAQvC;;;;OAIG;IACH,gBAAgB,IAAI,MAAM,EAAE;CAG/B"}
|