@dereekb/firebase-server 13.27.1 → 13.29.0
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/index.cjs.js +32 -1
- package/index.esm.js +32 -2
- package/mailgun/package.json +9 -9
- package/mcp/index.cjs.js +14 -6
- package/mcp/index.esm.js +15 -7
- package/mcp/package.json +11 -11
- package/mcp/src/lib/service/mcp.visibility.d.ts +6 -4
- package/model/package.json +9 -9
- package/oidc/index.cjs.js +365 -107
- package/oidc/index.esm.js +365 -110
- package/oidc/package.json +10 -10
- package/oidc/src/lib/index.d.ts +1 -0
- package/oidc/src/lib/middleware/oauth-cors.module.d.ts +41 -8
- package/oidc/src/lib/oidc.config.d.ts +61 -1
- package/oidc/src/lib/oidc.module.d.ts +1 -1
- package/oidc/src/lib/profile.d.ts +29 -0
- package/oidc/src/lib/scope.d.ts +8 -3
- package/package.json +10 -10
- package/src/lib/nest/model/api.details.d.ts +25 -1
- package/src/lib/nest/model/crud.assert.function.d.ts +9 -1
- package/test/index.cjs.js +10 -3
- package/test/index.esm.js +11 -4
- package/test/package.json +11 -11
- package/test/src/lib/oidc/oidc.test.flow.d.ts +1 -1
- package/twilio/package.json +8 -8
- package/zoho/package.json +9 -9
package/oidc/index.cjs.js
CHANGED
|
@@ -344,6 +344,14 @@ function _define_property$g(obj, key, value) {
|
|
|
344
344
|
*
|
|
345
345
|
* Defaults to `false`.
|
|
346
346
|
*/ _define_property$g(this, "trustProxyInNonProduction", void 0);
|
|
347
|
+
/**
|
|
348
|
+
* Unified CORS configuration for the cross-origin browser OIDC endpoints
|
|
349
|
+
* (discovery GET, token POST). When unset, the Express CORS layer preserves the
|
|
350
|
+
* pre-existing behavior: `Access-Control-Allow-Origin: <appUrl>` on every
|
|
351
|
+
* response, which pre-empts oidc-provider's own CORS handling.
|
|
352
|
+
*
|
|
353
|
+
* @see OidcCorsConfig
|
|
354
|
+
*/ _define_property$g(this, "cors", void 0);
|
|
347
355
|
}
|
|
348
356
|
_create_class$e(OidcModuleConfig, null, [
|
|
349
357
|
{
|
|
@@ -2423,6 +2431,9 @@ function _ts_generator$7(thisArg, body) {
|
|
|
2423
2431
|
if (params.dbx_max_session_ttl != null) {
|
|
2424
2432
|
properties.dbx_max_session_ttl = params.dbx_max_session_ttl;
|
|
2425
2433
|
}
|
|
2434
|
+
if (params.dbx_provider_profiles != null) {
|
|
2435
|
+
properties.dbx_provider_profiles = params.dbx_provider_profiles;
|
|
2436
|
+
}
|
|
2426
2437
|
// Merge any pre-validated metadata (e.g., inline jwks for private_key_jwt in tests)
|
|
2427
2438
|
if (validatedMetadata === null || validatedMetadata === void 0 ? void 0 : validatedMetadata.jwks) {
|
|
2428
2439
|
properties.jwks = validatedMetadata.jwks;
|
|
@@ -2480,7 +2491,7 @@ function _ts_generator$7(thisArg, body) {
|
|
|
2480
2491
|
* @throws {Error} When the client is not found.
|
|
2481
2492
|
*/ function updateClient(clientId, params) {
|
|
2482
2493
|
return _async_to_generator$7(function() {
|
|
2483
|
-
var provider, ProviderClient, existing, updatedMetadata, _params_logo_uri, _params_client_uri, _params_dbx_max_session_ttl, client;
|
|
2494
|
+
var provider, ProviderClient, existing, updatedMetadata, _params_logo_uri, _params_client_uri, _params_dbx_max_session_ttl, _params_dbx_provider_profiles, client;
|
|
2484
2495
|
return _ts_generator$7(this, function(_state) {
|
|
2485
2496
|
switch(_state.label){
|
|
2486
2497
|
case 0:
|
|
@@ -2512,6 +2523,12 @@ function _ts_generator$7(thisArg, body) {
|
|
|
2512
2523
|
if (params.dbx_max_session_ttl !== undefined) {
|
|
2513
2524
|
updatedMetadata.dbx_max_session_ttl = (_params_dbx_max_session_ttl = params.dbx_max_session_ttl) !== null && _params_dbx_max_session_ttl !== void 0 ? _params_dbx_max_session_ttl : undefined;
|
|
2514
2525
|
}
|
|
2526
|
+
// Only overwrite the profile assignment when the field is explicitly provided. An omitted value
|
|
2527
|
+
// (including one stripped for a non-admin caller) preserves the existing assignment; `null`/`[]`
|
|
2528
|
+
// clears it. This is what makes the non-admin strip a no-op rather than a wipe.
|
|
2529
|
+
if (params.dbx_provider_profiles !== undefined) {
|
|
2530
|
+
updatedMetadata.dbx_provider_profiles = (_params_dbx_provider_profiles = params.dbx_provider_profiles) !== null && _params_dbx_provider_profiles !== void 0 ? _params_dbx_provider_profiles : undefined;
|
|
2531
|
+
}
|
|
2515
2532
|
// Mirrors oidc-provider's lib/helpers/add_client.js: re-validates and persists.
|
|
2516
2533
|
return [
|
|
2517
2534
|
4,
|
|
@@ -3225,13 +3242,13 @@ var GRANTABLE_MODELS = new Set(GRANTABLE_MODEL_NAMES);
|
|
|
3225
3242
|
return FirestoreAdapter;
|
|
3226
3243
|
}
|
|
3227
3244
|
|
|
3228
|
-
function _array_like_to_array$
|
|
3245
|
+
function _array_like_to_array$6(arr, len) {
|
|
3229
3246
|
if (len == null || len > arr.length) len = arr.length;
|
|
3230
3247
|
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
3231
3248
|
return arr2;
|
|
3232
3249
|
}
|
|
3233
|
-
function _array_without_holes$
|
|
3234
|
-
if (Array.isArray(arr)) return _array_like_to_array$
|
|
3250
|
+
function _array_without_holes$6(arr) {
|
|
3251
|
+
if (Array.isArray(arr)) return _array_like_to_array$6(arr);
|
|
3235
3252
|
}
|
|
3236
3253
|
function _class_call_check$a(instance, Constructor) {
|
|
3237
3254
|
if (!(instance instanceof Constructor)) {
|
|
@@ -3264,22 +3281,22 @@ function _define_property$a(obj, key, value) {
|
|
|
3264
3281
|
}
|
|
3265
3282
|
return obj;
|
|
3266
3283
|
}
|
|
3267
|
-
function _iterable_to_array$
|
|
3284
|
+
function _iterable_to_array$6(iter) {
|
|
3268
3285
|
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
3269
3286
|
}
|
|
3270
|
-
function _non_iterable_spread$
|
|
3287
|
+
function _non_iterable_spread$6() {
|
|
3271
3288
|
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
3272
3289
|
}
|
|
3273
|
-
function _to_consumable_array$
|
|
3274
|
-
return _array_without_holes$
|
|
3290
|
+
function _to_consumable_array$6(arr) {
|
|
3291
|
+
return _array_without_holes$6(arr) || _iterable_to_array$6(arr) || _unsupported_iterable_to_array$6(arr) || _non_iterable_spread$6();
|
|
3275
3292
|
}
|
|
3276
|
-
function _unsupported_iterable_to_array$
|
|
3293
|
+
function _unsupported_iterable_to_array$6(o, minLen) {
|
|
3277
3294
|
if (!o) return;
|
|
3278
|
-
if (typeof o === "string") return _array_like_to_array$
|
|
3295
|
+
if (typeof o === "string") return _array_like_to_array$6(o, minLen);
|
|
3279
3296
|
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
3280
3297
|
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
3281
3298
|
if (n === "Map" || n === "Set") return Array.from(n);
|
|
3282
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$
|
|
3299
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$6(o, minLen);
|
|
3283
3300
|
}
|
|
3284
3301
|
// MARK: Encrypted Fields
|
|
3285
3302
|
/**
|
|
@@ -3307,7 +3324,7 @@ function _unsupported_iterable_to_array$5(o, minLen) {
|
|
|
3307
3324
|
this.provider = nestjs.createAesStringEncryptionProvider(config.jwksKeyConverterConfig.encryptionSecret);
|
|
3308
3325
|
this.adapterPayloadEncryptor = util.selectiveFieldEncryptor({
|
|
3309
3326
|
provider: this.provider,
|
|
3310
|
-
fields: _to_consumable_array$
|
|
3327
|
+
fields: _to_consumable_array$6(OIDC_ENCRYPTED_PAYLOAD_FIELDS)
|
|
3311
3328
|
});
|
|
3312
3329
|
}
|
|
3313
3330
|
_create_class$8(OidcEncryptionService, [
|
|
@@ -3343,13 +3360,13 @@ exports.OidcEncryptionService = __decorate([
|
|
|
3343
3360
|
__param(0, common.Inject(OidcModuleConfig))
|
|
3344
3361
|
], exports.OidcEncryptionService);
|
|
3345
3362
|
|
|
3346
|
-
function _array_like_to_array$
|
|
3363
|
+
function _array_like_to_array$5(arr, len) {
|
|
3347
3364
|
if (len == null || len > arr.length) len = arr.length;
|
|
3348
3365
|
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
3349
3366
|
return arr2;
|
|
3350
3367
|
}
|
|
3351
|
-
function _array_without_holes$
|
|
3352
|
-
if (Array.isArray(arr)) return _array_like_to_array$
|
|
3368
|
+
function _array_without_holes$5(arr) {
|
|
3369
|
+
if (Array.isArray(arr)) return _array_like_to_array$5(arr);
|
|
3353
3370
|
}
|
|
3354
3371
|
function _class_call_check$9(instance, Constructor) {
|
|
3355
3372
|
if (!(instance instanceof Constructor)) {
|
|
@@ -3382,22 +3399,22 @@ function _define_property$9(obj, key, value) {
|
|
|
3382
3399
|
}
|
|
3383
3400
|
return obj;
|
|
3384
3401
|
}
|
|
3385
|
-
function _iterable_to_array$
|
|
3402
|
+
function _iterable_to_array$5(iter) {
|
|
3386
3403
|
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
3387
3404
|
}
|
|
3388
|
-
function _non_iterable_spread$
|
|
3405
|
+
function _non_iterable_spread$5() {
|
|
3389
3406
|
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
3390
3407
|
}
|
|
3391
|
-
function _to_consumable_array$
|
|
3392
|
-
return _array_without_holes$
|
|
3408
|
+
function _to_consumable_array$5(arr) {
|
|
3409
|
+
return _array_without_holes$5(arr) || _iterable_to_array$5(arr) || _unsupported_iterable_to_array$5(arr) || _non_iterable_spread$5();
|
|
3393
3410
|
}
|
|
3394
|
-
function _unsupported_iterable_to_array$
|
|
3411
|
+
function _unsupported_iterable_to_array$5(o, minLen) {
|
|
3395
3412
|
if (!o) return;
|
|
3396
|
-
if (typeof o === "string") return _array_like_to_array$
|
|
3413
|
+
if (typeof o === "string") return _array_like_to_array$5(o, minLen);
|
|
3397
3414
|
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
3398
3415
|
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
3399
3416
|
if (n === "Map" || n === "Set") return Array.from(n);
|
|
3400
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$
|
|
3417
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$5(o, minLen);
|
|
3401
3418
|
}
|
|
3402
3419
|
// MARK: Routes
|
|
3403
3420
|
/**
|
|
@@ -3474,7 +3491,7 @@ var DEFAULT_OIDC_CODE_CHALLENGE_METHODS = [
|
|
|
3474
3491
|
this.providerConfig = accountService.providerConfig;
|
|
3475
3492
|
this.scopesSupported = Object.keys(this.providerConfig.claims);
|
|
3476
3493
|
this.claimsSupported = Array.from(new Set(Object.values(this.providerConfig.claims).flat()));
|
|
3477
|
-
this.tokenEndpointAuthMethodsSupported = (_this_config_tokenEndpointAuthMethods = this.config.tokenEndpointAuthMethods) !== null && _this_config_tokenEndpointAuthMethods !== void 0 ? _this_config_tokenEndpointAuthMethods : _to_consumable_array$
|
|
3494
|
+
this.tokenEndpointAuthMethodsSupported = (_this_config_tokenEndpointAuthMethods = this.config.tokenEndpointAuthMethods) !== null && _this_config_tokenEndpointAuthMethods !== void 0 ? _this_config_tokenEndpointAuthMethods : _to_consumable_array$5(DEFAULT_OIDC_TOKEN_ENDPOINT_AUTH_METHODS);
|
|
3478
3495
|
var appUrl = envService.appUrl;
|
|
3479
3496
|
this.appLoginUrl = util.websiteUrlFromPaths(appUrl, [
|
|
3480
3497
|
this.config.appOAuthInteractionPath,
|
|
@@ -3507,16 +3524,16 @@ var DEFAULT_OIDC_CODE_CHALLENGE_METHODS = [
|
|
|
3507
3524
|
jwks_uri: jwksUri !== null && jwksUri !== void 0 ? jwksUri : "".concat(issuer).concat(routes.jwks),
|
|
3508
3525
|
registration_endpoint: this.oidcRegistrationRouteEnabled ? "".concat(issuer).concat(routes.registration) : undefined,
|
|
3509
3526
|
scopes_supported: this.scopesSupported,
|
|
3510
|
-
response_types_supported: _to_consumable_array$
|
|
3527
|
+
response_types_supported: _to_consumable_array$5(providerConfig.responseTypes),
|
|
3511
3528
|
response_modes_supported: [
|
|
3512
3529
|
'query'
|
|
3513
3530
|
],
|
|
3514
|
-
grant_types_supported: _to_consumable_array$
|
|
3515
|
-
subject_types_supported: _to_consumable_array$
|
|
3516
|
-
id_token_signing_alg_values_supported: _to_consumable_array$
|
|
3517
|
-
token_endpoint_auth_methods_supported: _to_consumable_array$
|
|
3531
|
+
grant_types_supported: _to_consumable_array$5(providerConfig.grantTypes),
|
|
3532
|
+
subject_types_supported: _to_consumable_array$5(DEFAULT_OIDC_SUBJECT_TYPES),
|
|
3533
|
+
id_token_signing_alg_values_supported: _to_consumable_array$5(DEFAULT_OIDC_ID_TOKEN_SIGNING_ALG_VALUES),
|
|
3534
|
+
token_endpoint_auth_methods_supported: _to_consumable_array$5(this.tokenEndpointAuthMethodsSupported),
|
|
3518
3535
|
claims_supported: this.claimsSupported,
|
|
3519
|
-
code_challenge_methods_supported: _to_consumable_array$
|
|
3536
|
+
code_challenge_methods_supported: _to_consumable_array$5(DEFAULT_OIDC_CODE_CHALLENGE_METHODS)
|
|
3520
3537
|
};
|
|
3521
3538
|
}
|
|
3522
3539
|
}
|
|
@@ -3530,13 +3547,32 @@ exports.OidcProviderConfigService = __decorate([
|
|
|
3530
3547
|
__param(2, common.Inject(firebaseServer.FirebaseServerEnvService))
|
|
3531
3548
|
], exports.OidcProviderConfigService);
|
|
3532
3549
|
|
|
3533
|
-
|
|
3550
|
+
/**
|
|
3551
|
+
* Custom oidc-provider client metadata field holding the {@link OidcProviderProfile} keys assigned
|
|
3552
|
+
* to a client. Registered via `extraClientMetadata` and persisted on the client's `OidcEntry` payload.
|
|
3553
|
+
*/ var DBX_FIREBASE_SERVER_OIDC_PROVIDER_PROFILES_CLIENT_METADATA = 'dbx_provider_profiles';
|
|
3554
|
+
/**
|
|
3555
|
+
* Resolves the unlocked + required scope sets for a client from the provider-profile registry and
|
|
3556
|
+
* the profile keys assigned to that client.
|
|
3557
|
+
*
|
|
3558
|
+
* @param providerProfiles - The provider-profile registry (from {@link OidcProviderConfig.providerProfiles}).
|
|
3559
|
+
* @param clientProfileKeys - The profile keys assigned to the client (its `dbx_provider_profiles`).
|
|
3560
|
+
* @returns The unlocked and required scope sets for the client.
|
|
3561
|
+
*/ function oidcClientProviderProfileScopes(providerProfiles, clientProfileKeys) {
|
|
3562
|
+
var clientProfiles = firebase.oidcProviderProfilesForKeys(providerProfiles !== null && providerProfiles !== void 0 ? providerProfiles : [], clientProfileKeys);
|
|
3563
|
+
return {
|
|
3564
|
+
unlocked: firebase.scopesForOidcProviderProfiles(clientProfiles),
|
|
3565
|
+
required: firebase.requiredScopesForOidcProviderProfiles(clientProfiles)
|
|
3566
|
+
};
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3569
|
+
function _array_like_to_array$4(arr, len) {
|
|
3534
3570
|
if (len == null || len > arr.length) len = arr.length;
|
|
3535
3571
|
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
3536
3572
|
return arr2;
|
|
3537
3573
|
}
|
|
3538
|
-
function _array_without_holes$
|
|
3539
|
-
if (Array.isArray(arr)) return _array_like_to_array$
|
|
3574
|
+
function _array_without_holes$4(arr) {
|
|
3575
|
+
if (Array.isArray(arr)) return _array_like_to_array$4(arr);
|
|
3540
3576
|
}
|
|
3541
3577
|
function asyncGeneratorStep$5(gen, resolve, reject, _next, _throw, key, arg) {
|
|
3542
3578
|
try {
|
|
@@ -3598,10 +3634,10 @@ function _define_property$8(obj, key, value) {
|
|
|
3598
3634
|
}
|
|
3599
3635
|
return obj;
|
|
3600
3636
|
}
|
|
3601
|
-
function _iterable_to_array$
|
|
3637
|
+
function _iterable_to_array$4(iter) {
|
|
3602
3638
|
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
3603
3639
|
}
|
|
3604
|
-
function _non_iterable_spread$
|
|
3640
|
+
function _non_iterable_spread$4() {
|
|
3605
3641
|
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
3606
3642
|
}
|
|
3607
3643
|
function _object_spread$3(target) {
|
|
@@ -3674,16 +3710,16 @@ function _object_without_properties_loose(source, excluded) {
|
|
|
3674
3710
|
}
|
|
3675
3711
|
return target;
|
|
3676
3712
|
}
|
|
3677
|
-
function _to_consumable_array$
|
|
3678
|
-
return _array_without_holes$
|
|
3713
|
+
function _to_consumable_array$4(arr) {
|
|
3714
|
+
return _array_without_holes$4(arr) || _iterable_to_array$4(arr) || _unsupported_iterable_to_array$4(arr) || _non_iterable_spread$4();
|
|
3679
3715
|
}
|
|
3680
|
-
function _unsupported_iterable_to_array$
|
|
3716
|
+
function _unsupported_iterable_to_array$4(o, minLen) {
|
|
3681
3717
|
if (!o) return;
|
|
3682
|
-
if (typeof o === "string") return _array_like_to_array$
|
|
3718
|
+
if (typeof o === "string") return _array_like_to_array$4(o, minLen);
|
|
3683
3719
|
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
3684
3720
|
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
3685
3721
|
if (n === "Map" || n === "Set") return Array.from(n);
|
|
3686
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$
|
|
3722
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$4(o, minLen);
|
|
3687
3723
|
}
|
|
3688
3724
|
function _ts_generator$5(thisArg, body) {
|
|
3689
3725
|
var f, y, t, _ = {
|
|
@@ -4034,7 +4070,8 @@ function _ts_generator$5(thisArg, body) {
|
|
|
4034
4070
|
logo_uri: existing.logo_uri,
|
|
4035
4071
|
client_uri: existing.client_uri,
|
|
4036
4072
|
created_at: existing.created_at,
|
|
4037
|
-
dbx_max_session_ttl: existing.dbx_max_session_ttl
|
|
4073
|
+
dbx_max_session_ttl: existing.dbx_max_session_ttl,
|
|
4074
|
+
dbx_provider_profiles: existing.dbx_provider_profiles
|
|
4038
4075
|
};
|
|
4039
4076
|
}
|
|
4040
4077
|
return [
|
|
@@ -4060,6 +4097,7 @@ function _ts_generator$5(thisArg, body) {
|
|
|
4060
4097
|
value: function buildProviderConfiguration(cookieKeys) {
|
|
4061
4098
|
var _this = this;
|
|
4062
4099
|
var _config_maxRequestedLoginDuration, _config_minRequestedLoginDuration;
|
|
4100
|
+
var _config_cors;
|
|
4063
4101
|
var config = this.config;
|
|
4064
4102
|
var providerConfig = this.providerConfigService.providerConfig;
|
|
4065
4103
|
var serverMaxSeconds = (_config_maxRequestedLoginDuration = config.maxRequestedLoginDuration) !== null && _config_maxRequestedLoginDuration !== void 0 ? _config_maxRequestedLoginDuration : DEFAULT_MAX_REQUESTED_LOGIN_DURATION_SECONDS;
|
|
@@ -4077,7 +4115,7 @@ function _ts_generator$5(thisArg, body) {
|
|
|
4077
4115
|
return _object_spread_props(_object_spread$3({
|
|
4078
4116
|
routes: _object_spread$3({}, this.providerConfigService.routes),
|
|
4079
4117
|
claims: _object_spread$3({}, providerConfig.claims),
|
|
4080
|
-
responseTypes: _to_consumable_array$
|
|
4118
|
+
responseTypes: _to_consumable_array$4(providerConfig.responseTypes),
|
|
4081
4119
|
pkce: {
|
|
4082
4120
|
required: function required() {
|
|
4083
4121
|
return true;
|
|
@@ -4140,7 +4178,8 @@ function _ts_generator$5(thisArg, body) {
|
|
|
4140
4178
|
],
|
|
4141
4179
|
extraClientMetadata: {
|
|
4142
4180
|
properties: [
|
|
4143
|
-
DBX_FIREBASE_SERVER_OIDC_MAX_SESSION_TTL_CLIENT_METADATA
|
|
4181
|
+
DBX_FIREBASE_SERVER_OIDC_MAX_SESSION_TTL_CLIENT_METADATA,
|
|
4182
|
+
DBX_FIREBASE_SERVER_OIDC_PROVIDER_PROFILES_CLIENT_METADATA
|
|
4144
4183
|
],
|
|
4145
4184
|
validator: function validator(_ctx, key, value) {
|
|
4146
4185
|
if (key === DBX_FIREBASE_SERVER_OIDC_MAX_SESSION_TTL_CLIENT_METADATA && value !== undefined && value !== null) {
|
|
@@ -4150,6 +4189,22 @@ function _ts_generator$5(thisArg, body) {
|
|
|
4150
4189
|
if (value > serverMaxSeconds) {
|
|
4151
4190
|
throw new oidcProvider.errors.InvalidClientMetadata("".concat(DBX_FIREBASE_SERVER_OIDC_MAX_SESSION_TTL_CLIENT_METADATA, " cannot exceed the server max of ").concat(serverMaxSeconds, " seconds."));
|
|
4152
4191
|
}
|
|
4192
|
+
} else if (key === DBX_FIREBASE_SERVER_OIDC_PROVIDER_PROFILES_CLIENT_METADATA && value !== undefined && value !== null) {
|
|
4193
|
+
var _providerConfig_providerProfiles;
|
|
4194
|
+
if (!Array.isArray(value) || value.some(function(entry) {
|
|
4195
|
+
return typeof entry !== 'string';
|
|
4196
|
+
})) {
|
|
4197
|
+
throw new oidcProvider.errors.InvalidClientMetadata("".concat(DBX_FIREBASE_SERVER_OIDC_PROVIDER_PROFILES_CLIENT_METADATA, " must be an array of provider profile keys."));
|
|
4198
|
+
}
|
|
4199
|
+
var knownProfileKeys = new Set(((_providerConfig_providerProfiles = providerConfig.providerProfiles) !== null && _providerConfig_providerProfiles !== void 0 ? _providerConfig_providerProfiles : []).map(function(profile) {
|
|
4200
|
+
return profile.key;
|
|
4201
|
+
}));
|
|
4202
|
+
var unknownKey = value.find(function(entry) {
|
|
4203
|
+
return !knownProfileKeys.has(entry);
|
|
4204
|
+
});
|
|
4205
|
+
if (unknownKey !== undefined) {
|
|
4206
|
+
throw new oidcProvider.errors.InvalidClientMetadata("".concat(DBX_FIREBASE_SERVER_OIDC_PROVIDER_PROFILES_CLIENT_METADATA, " contains an unknown provider profile key: ").concat(unknownKey, "."));
|
|
4207
|
+
}
|
|
4153
4208
|
}
|
|
4154
4209
|
}
|
|
4155
4210
|
},
|
|
@@ -4177,7 +4232,7 @@ function _ts_generator$5(thisArg, body) {
|
|
|
4177
4232
|
interactions: {
|
|
4178
4233
|
url: function url(_ctx, interaction) {
|
|
4179
4234
|
return _async_to_generator$5(function() {
|
|
4180
|
-
var baseUrl, client_id, paramsToEncode, client, scopes, interactionLoginDetails, paramsString;
|
|
4235
|
+
var baseUrl, client_id, paramsToEncode, client, _client_dbx_provider_profiles, scopes, requestedScopeSet, required, requiredScopes, interactionLoginDetails, paramsString;
|
|
4181
4236
|
return _ts_generator$5(this, function(_state) {
|
|
4182
4237
|
switch(_state.label){
|
|
4183
4238
|
case 0:
|
|
@@ -4205,13 +4260,23 @@ function _ts_generator$5(thisArg, body) {
|
|
|
4205
4260
|
client = _state.sent();
|
|
4206
4261
|
if (client) {
|
|
4207
4262
|
scopes = interaction.params.scope;
|
|
4208
|
-
|
|
4263
|
+
// Surface the scopes the client's provider profiles force-require so the consent UI can
|
|
4264
|
+
// render them as required. Intersect with the actually-requested scopes so only visible
|
|
4265
|
+
// scope rows are flagged.
|
|
4266
|
+
requestedScopeSet = new Set(scopes.split(' ').filter(Boolean));
|
|
4267
|
+
required = oidcClientProviderProfileScopes(providerConfig.providerProfiles, (_client_dbx_provider_profiles = client.dbx_provider_profiles) !== null && _client_dbx_provider_profiles !== void 0 ? _client_dbx_provider_profiles : undefined).required;
|
|
4268
|
+
requiredScopes = Array.from(required).filter(function(scope) {
|
|
4269
|
+
return requestedScopeSet.has(scope);
|
|
4270
|
+
});
|
|
4271
|
+
interactionLoginDetails = _object_spread$3({
|
|
4209
4272
|
client_id: client_id,
|
|
4210
4273
|
client_name: client.client_name,
|
|
4211
4274
|
client_uri: client.client_uri,
|
|
4212
4275
|
logo_uri: client.logo_uri,
|
|
4213
4276
|
scopes: scopes
|
|
4214
|
-
}
|
|
4277
|
+
}, requiredScopes.length > 0 ? {
|
|
4278
|
+
requiredScopes: requiredScopes.join(' ')
|
|
4279
|
+
} : {});
|
|
4215
4280
|
paramsToEncode = _object_spread$3({}, paramsToEncode, interactionLoginDetails);
|
|
4216
4281
|
}
|
|
4217
4282
|
_state.label = 3;
|
|
@@ -4233,6 +4298,19 @@ function _ts_generator$5(thisArg, body) {
|
|
|
4233
4298
|
}
|
|
4234
4299
|
}, config.renderError ? {
|
|
4235
4300
|
renderError: config.renderError
|
|
4301
|
+
} : {}, ((_config_cors = config.cors) === null || _config_cors === void 0 ? void 0 : _config_cors.clientBased) ? {
|
|
4302
|
+
clientBasedCORS: function clientBasedCORS(_ctx, origin, client) {
|
|
4303
|
+
var _client_redirectUris;
|
|
4304
|
+
return ((_client_redirectUris = client.redirectUris) !== null && _client_redirectUris !== void 0 ? _client_redirectUris : []).some(function(uri) {
|
|
4305
|
+
var matches = false;
|
|
4306
|
+
try {
|
|
4307
|
+
matches = new URL(uri).origin === origin;
|
|
4308
|
+
} catch (unused) {
|
|
4309
|
+
// malformed persisted redirect_uri — treat as non-matching
|
|
4310
|
+
}
|
|
4311
|
+
return matches;
|
|
4312
|
+
});
|
|
4313
|
+
}
|
|
4236
4314
|
} : {}), {
|
|
4237
4315
|
// Setting `rotateRefreshToken` disables oidc-provider's built-in default, so we both honor the
|
|
4238
4316
|
// dbx-components `nonRotatingScopes` extension (service tokens never rotate, keeping a stable
|
|
@@ -4862,9 +4940,69 @@ exports.OidcAuthBearerTokenMiddleware = __decorate([
|
|
|
4862
4940
|
__param(1, common.Inject(OidcAuthMiddlewareConfig))
|
|
4863
4941
|
], exports.OidcAuthBearerTokenMiddleware);
|
|
4864
4942
|
|
|
4943
|
+
function _array_like_to_array$3(arr, len) {
|
|
4944
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
4945
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
4946
|
+
return arr2;
|
|
4947
|
+
}
|
|
4948
|
+
function _array_without_holes$3(arr) {
|
|
4949
|
+
if (Array.isArray(arr)) return _array_like_to_array$3(arr);
|
|
4950
|
+
}
|
|
4951
|
+
function _iterable_to_array$3(iter) {
|
|
4952
|
+
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
4953
|
+
}
|
|
4954
|
+
function _non_iterable_spread$3() {
|
|
4955
|
+
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
4956
|
+
}
|
|
4957
|
+
function _to_consumable_array$3(arr) {
|
|
4958
|
+
return _array_without_holes$3(arr) || _iterable_to_array$3(arr) || _unsupported_iterable_to_array$3(arr) || _non_iterable_spread$3();
|
|
4959
|
+
}
|
|
4960
|
+
function _unsupported_iterable_to_array$3(o, minLen) {
|
|
4961
|
+
if (!o) return;
|
|
4962
|
+
if (typeof o === "string") return _array_like_to_array$3(o, minLen);
|
|
4963
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
4964
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
4965
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
4966
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$3(o, minLen);
|
|
4967
|
+
}
|
|
4968
|
+
/**
|
|
4969
|
+
* Builds the `cors`-package origin delegate implementing the composed OIDC CORS policy.
|
|
4970
|
+
*
|
|
4971
|
+
* - An allowlisted origin (`appUrl` or any {@link OidcCorsConfig.allowOrigins} entry) is
|
|
4972
|
+
* reflected exactly, which pre-empts oidc-provider's own CORS handling.
|
|
4973
|
+
* - Otherwise, when {@link OidcCorsConfig.clientBased} is enabled, the header is OMITTED so
|
|
4974
|
+
* oidc-provider runs its `clientBasedCORS` check on client routes (`/token`) and its builtin
|
|
4975
|
+
* reflect on client-less routes (discovery/JWKS).
|
|
4976
|
+
* - Otherwise (client-based off), `appUrl` is returned unconditionally so oidc-provider stays
|
|
4977
|
+
* pre-empted and there is never a reflect-any.
|
|
4978
|
+
*
|
|
4979
|
+
* Exported for unit testing without a running Nest application.
|
|
4980
|
+
*
|
|
4981
|
+
* @param appUrl - The authoritative frontend origin (always allowed).
|
|
4982
|
+
* @param cors - The unified CORS configuration.
|
|
4983
|
+
* @returns A `cors`-package origin delegate.
|
|
4984
|
+
*/ function oidcCorsOriginDelegate(appUrl, cors) {
|
|
4985
|
+
var _cors_allowOrigins;
|
|
4986
|
+
var clientBased = cors.clientBased === true;
|
|
4987
|
+
var allowlist = new Set([
|
|
4988
|
+
appUrl
|
|
4989
|
+
].concat(_to_consumable_array$3((_cors_allowOrigins = cors.allowOrigins) !== null && _cors_allowOrigins !== void 0 ? _cors_allowOrigins : [])));
|
|
4990
|
+
return function(requestOrigin, callback) {
|
|
4991
|
+
var resolved;
|
|
4992
|
+
if (requestOrigin && allowlist.has(requestOrigin)) {
|
|
4993
|
+
resolved = requestOrigin; // reflect the exact allowlisted origin; pre-empts oidc-provider
|
|
4994
|
+
} else if (clientBased) {
|
|
4995
|
+
resolved = false; // OMIT ACAO → oidc-provider runs clientBasedCORS (token) / builtin reflect (discovery)
|
|
4996
|
+
} else {
|
|
4997
|
+
resolved = appUrl; // legacy fallback: ACAO=appUrl always; no reflect-any
|
|
4998
|
+
}
|
|
4999
|
+
callback(null, resolved);
|
|
5000
|
+
};
|
|
5001
|
+
}
|
|
4865
5002
|
// MARK: Express-Level Helper
|
|
4866
5003
|
/**
|
|
4867
|
-
* Enables CORS on the NestJS app for OIDC cross-origin requests originating from the frontend
|
|
5004
|
+
* Enables CORS on the NestJS app for OIDC cross-origin requests originating from the frontend
|
|
5005
|
+
* and any additional relying-party origins.
|
|
4868
5006
|
*
|
|
4869
5007
|
* When the OIDC issuer lives on a different origin than the frontend app (e.g. the frontend is
|
|
4870
5008
|
* `https://app.example.com` and the OIDC server is at `https://api.example.com`), the frontend's
|
|
@@ -4872,16 +5010,22 @@ exports.OidcAuthBearerTokenMiddleware = __decorate([
|
|
|
4872
5010
|
* and `/interaction/{uid}/consent`. Because the POST body is `application/json`, the browser
|
|
4873
5011
|
* sends a CORS preflight. Without an `Access-Control-Allow-Origin` reply the preflight fails,
|
|
4874
5012
|
* the POST never reaches the server, and the OAuth flow stalls before `finishInteractionByUid`
|
|
4875
|
-
* can run.
|
|
5013
|
+
* can run. Browser-based OIDC relying parties (public PKCE clients) likewise need CORS on the
|
|
5014
|
+
* discovery GET and the token POST.
|
|
5015
|
+
*
|
|
5016
|
+
* `appUrl` (from `FirebaseServerEnvService.appUrl`) is always allowed. Additional behavior is
|
|
5017
|
+
* driven by the optional {@link OidcModuleConfig.cors} configuration:
|
|
5018
|
+
* - {@link OidcCorsConfig.allowOrigins} adds an explicit allowlist of relying-party origins.
|
|
5019
|
+
* - {@link OidcCorsConfig.clientBased} defers non-allowlisted origins to oidc-provider's
|
|
5020
|
+
* `clientBasedCORS`, which trusts each requesting client's registered `redirect_uris`.
|
|
4876
5021
|
*
|
|
4877
|
-
*
|
|
4878
|
-
*
|
|
4879
|
-
*
|
|
4880
|
-
* actually same-origin and CORS is a no-op.
|
|
5022
|
+
* When `cors` is unset, this preserves the legacy single-origin behavior exactly:
|
|
5023
|
+
* `Access-Control-Allow-Origin: <appUrl>` on every response, which pre-empts oidc-provider's
|
|
5024
|
+
* own CORS handling.
|
|
4881
5025
|
*
|
|
4882
5026
|
* Credentials are intentionally NOT enabled (`Access-Control-Allow-Credentials` stays off). The
|
|
4883
|
-
* `/interaction/{uid}/*` POSTs
|
|
4884
|
-
* we keep the CORS surface minimal.
|
|
5027
|
+
* `/interaction/{uid}/*` POSTs and the token exchange carry their bearer material in the request
|
|
5028
|
+
* body, not in cookies, so we keep the CORS surface minimal.
|
|
4885
5029
|
*
|
|
4886
5030
|
* @param nestApp - The NestJS application to configure.
|
|
4887
5031
|
*
|
|
@@ -4897,18 +5041,40 @@ exports.OidcAuthBearerTokenMiddleware = __decorate([
|
|
|
4897
5041
|
* ```
|
|
4898
5042
|
*/ function applyOidcCorsMiddleware(nestApp) {
|
|
4899
5043
|
var envService = nestApp.get(firebaseServer.FirebaseServerEnvService);
|
|
4900
|
-
var
|
|
4901
|
-
if (!
|
|
5044
|
+
var appUrl = envService.appUrl;
|
|
5045
|
+
if (!appUrl) {
|
|
4902
5046
|
return;
|
|
4903
5047
|
}
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
})
|
|
5048
|
+
// OidcModuleConfig may be absent (module not registered / out of the resolution scope).
|
|
5049
|
+
var cors;
|
|
5050
|
+
try {
|
|
5051
|
+
var _nestApp_get;
|
|
5052
|
+
cors = (_nestApp_get = nestApp.get(OidcModuleConfig, {
|
|
5053
|
+
strict: false
|
|
5054
|
+
})) === null || _nestApp_get === void 0 ? void 0 : _nestApp_get.cors;
|
|
5055
|
+
} catch (unused) {
|
|
5056
|
+
cors = undefined;
|
|
5057
|
+
}
|
|
5058
|
+
if (cors) {
|
|
5059
|
+
nestApp.enableCors({
|
|
5060
|
+
origin: oidcCorsOriginDelegate(appUrl, cors),
|
|
5061
|
+
methods: [
|
|
5062
|
+
'GET',
|
|
5063
|
+
'POST',
|
|
5064
|
+
'OPTIONS'
|
|
5065
|
+
]
|
|
5066
|
+
});
|
|
5067
|
+
} else {
|
|
5068
|
+
// No cors config → byte-identical to the legacy behavior: ACAO=appUrl unconditionally.
|
|
5069
|
+
nestApp.enableCors({
|
|
5070
|
+
origin: appUrl,
|
|
5071
|
+
methods: [
|
|
5072
|
+
'GET',
|
|
5073
|
+
'POST',
|
|
5074
|
+
'OPTIONS'
|
|
5075
|
+
]
|
|
5076
|
+
});
|
|
5077
|
+
}
|
|
4912
5078
|
}
|
|
4913
5079
|
|
|
4914
5080
|
/**
|
|
@@ -6049,7 +6215,7 @@ var OidcInteractionController_1;
|
|
|
6049
6215
|
* @throws {HttpException} HTTP 400 when the consent interaction cannot be completed.
|
|
6050
6216
|
*/ function postConsent(uid, body, res) {
|
|
6051
6217
|
return _async_to_generator$2(function() {
|
|
6052
|
-
var startedAt, clientId, accountId, _ref, _prompt_details_missingOIDCScope, _this_accountService_providerConfig_adminOnlyScopes, _ref1, _ref2, _prompt_details_missingOIDCClaims, _prompt_details_missingResourceScopes, _this_accountService_delegate_isAdminUser, _this_accountService_delegate,
|
|
6218
|
+
var startedAt, clientId, accountId, _ref, _prompt_details_missingOIDCScope, _this_accountService_providerConfig_adminOnlyScopes, _ref1, _ref2, _ref3, _prompt_details_missingOIDCClaims, _prompt_details_missingResourceScopes, _this_accountService_delegate_isAdminUser, _this_accountService_delegate, _ref4, redirectTo, interaction, prompt, params, session, missingOIDCScope, existingGrant, _tmp, encounteredOIDCScopes, clientPayload, requestedOIDCScopeSet, adminOnlyScopes, requestsServiceToken, isAdmin, _tmp1, _ref5, redirectTo1, providerProfiles, _oidcClientProviderProfileScopes, clientUnlockedScopes, clientRequiredScopes, profileGatedScopes, disallowedGatedScopes, _ref6, redirectTo2, missingRequiredScopes, _ref7, redirectTo3, requestedRawTtl, clientMaxSessionTtl, expiresInSeconds, grant, _tmp2, _resolveEffectiveSubset, granted, rejected, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, value, encounteredOIDCClaims, missingOIDCClaims, _resolveEffectiveSubset1, granted1, rejected1, missingResourceScopes, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, _step_value, indicator, scopes, _body_grantedResourceScopes, requestedSubset, encounteredResourceScopes, _resolveEffectiveSubset2, granted2, rejected2, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, value1, grantId, _ref8, redirectTo4, err;
|
|
6053
6219
|
return _ts_generator$2(this, function(_state) {
|
|
6054
6220
|
switch(_state.label){
|
|
6055
6221
|
case 0:
|
|
@@ -6064,9 +6230,9 @@ var OidcInteractionController_1;
|
|
|
6064
6230
|
case 2:
|
|
6065
6231
|
_state.trys.push([
|
|
6066
6232
|
2,
|
|
6067
|
-
|
|
6233
|
+
24,
|
|
6068
6234
|
,
|
|
6069
|
-
|
|
6235
|
+
25
|
|
6070
6236
|
]);
|
|
6071
6237
|
if (!!body.approved) return [
|
|
6072
6238
|
3,
|
|
@@ -6082,7 +6248,7 @@ var OidcInteractionController_1;
|
|
|
6082
6248
|
})
|
|
6083
6249
|
];
|
|
6084
6250
|
case 3:
|
|
6085
|
-
|
|
6251
|
+
_ref4 = _state.sent(), redirectTo = _ref4.returnTo;
|
|
6086
6252
|
res.json({
|
|
6087
6253
|
redirectTo: redirectTo
|
|
6088
6254
|
});
|
|
@@ -6125,6 +6291,12 @@ var OidcInteractionController_1;
|
|
|
6125
6291
|
// and re-submits them all. We accept already-encountered values as silent no-ops so a re-consent on a
|
|
6126
6292
|
// client the user has previously authorized doesn't fail validation.
|
|
6127
6293
|
encounteredOIDCScopes = existingGrant ? existingGrant.getOIDCScopeEncountered().split(' ').filter(Boolean) : [];
|
|
6294
|
+
return [
|
|
6295
|
+
4,
|
|
6296
|
+
this.oidcService.findClientPayload(clientId)
|
|
6297
|
+
];
|
|
6298
|
+
case 9:
|
|
6299
|
+
clientPayload = _state.sent();
|
|
6128
6300
|
// Admin-only scope gate. The requested OIDC scope set is `missingOIDCScope ∪ encounteredOIDCScopes`
|
|
6129
6301
|
// (a fresh consent has everything in `missing`; a re-consent may carry already-granted scopes in
|
|
6130
6302
|
// `encountered`). If that set intersects the provider's `adminOnlyScopes` and the resolving user is
|
|
@@ -6136,26 +6308,26 @@ var OidcInteractionController_1;
|
|
|
6136
6308
|
});
|
|
6137
6309
|
if (!accountId) return [
|
|
6138
6310
|
3,
|
|
6139
|
-
|
|
6311
|
+
11
|
|
6140
6312
|
];
|
|
6141
6313
|
return [
|
|
6142
6314
|
4,
|
|
6143
6315
|
(_ref1 = (_this_accountService_delegate_isAdminUser = (_this_accountService_delegate = this.accountService.delegate).isAdminUser) === null || _this_accountService_delegate_isAdminUser === void 0 ? void 0 : _this_accountService_delegate_isAdminUser.call(_this_accountService_delegate, this.accountService.userContext(accountId).authUserContext)) !== null && _ref1 !== void 0 ? _ref1 : false
|
|
6144
6316
|
];
|
|
6145
|
-
case
|
|
6317
|
+
case 10:
|
|
6146
6318
|
_tmp1 = _state.sent();
|
|
6147
6319
|
return [
|
|
6148
6320
|
3,
|
|
6149
|
-
|
|
6321
|
+
12
|
|
6150
6322
|
];
|
|
6151
|
-
case 10:
|
|
6152
|
-
_tmp1 = false;
|
|
6153
|
-
_state.label = 11;
|
|
6154
6323
|
case 11:
|
|
6324
|
+
_tmp1 = false;
|
|
6325
|
+
_state.label = 12;
|
|
6326
|
+
case 12:
|
|
6155
6327
|
isAdmin = _tmp1;
|
|
6156
6328
|
if (!(requestsServiceToken && !isAdmin)) return [
|
|
6157
6329
|
3,
|
|
6158
|
-
|
|
6330
|
+
14
|
|
6159
6331
|
];
|
|
6160
6332
|
return [
|
|
6161
6333
|
4,
|
|
@@ -6166,8 +6338,8 @@ var OidcInteractionController_1;
|
|
|
6166
6338
|
mergeWithLastSubmission: true
|
|
6167
6339
|
})
|
|
6168
6340
|
];
|
|
6169
|
-
case
|
|
6170
|
-
|
|
6341
|
+
case 13:
|
|
6342
|
+
_ref5 = _state.sent(), redirectTo1 = _ref5.returnTo;
|
|
6171
6343
|
emitOidcAnalyticsEvent(this._analytics, {
|
|
6172
6344
|
type: 'consent',
|
|
6173
6345
|
isSuccessful: false,
|
|
@@ -6184,20 +6356,89 @@ var OidcInteractionController_1;
|
|
|
6184
6356
|
return [
|
|
6185
6357
|
2
|
|
6186
6358
|
];
|
|
6187
|
-
case
|
|
6359
|
+
case 14:
|
|
6360
|
+
// Provider-profile scope gate. Any scope referenced by a provider profile is "gated" — available
|
|
6361
|
+
// only to clients whose assigned profiles unlock it. Independent of the admin-only gate above; a
|
|
6362
|
+
// scope may be subject to both.
|
|
6363
|
+
providerProfiles = this.accountService.providerConfig.providerProfiles;
|
|
6364
|
+
_oidcClientProviderProfileScopes = oidcClientProviderProfileScopes(providerProfiles, (_ref2 = clientPayload === null || clientPayload === void 0 ? void 0 : clientPayload.dbx_provider_profiles) !== null && _ref2 !== void 0 ? _ref2 : undefined), clientUnlockedScopes = _oidcClientProviderProfileScopes.unlocked, clientRequiredScopes = _oidcClientProviderProfileScopes.required;
|
|
6365
|
+
profileGatedScopes = firebase.scopesForOidcProviderProfiles(providerProfiles !== null && providerProfiles !== void 0 ? providerProfiles : []);
|
|
6366
|
+
// Unlock gate: reject any requested gated scope this client's profiles do not unlock.
|
|
6367
|
+
disallowedGatedScopes = Array.from(requestedOIDCScopeSet).filter(function(scope) {
|
|
6368
|
+
return profileGatedScopes.has(scope) && !clientUnlockedScopes.has(scope);
|
|
6369
|
+
});
|
|
6370
|
+
if (!(disallowedGatedScopes.length > 0)) return [
|
|
6371
|
+
3,
|
|
6372
|
+
16
|
|
6373
|
+
];
|
|
6374
|
+
return [
|
|
6375
|
+
4,
|
|
6376
|
+
this.oidcInteractionService.finishInteractionByUid(uid, {
|
|
6377
|
+
error: 'access_denied',
|
|
6378
|
+
error_description: "The following scope(s) are not available to this client: ".concat(disallowedGatedScopes.join(', '), ".")
|
|
6379
|
+
}, {
|
|
6380
|
+
mergeWithLastSubmission: true
|
|
6381
|
+
})
|
|
6382
|
+
];
|
|
6383
|
+
case 15:
|
|
6384
|
+
_ref6 = _state.sent(), redirectTo2 = _ref6.returnTo;
|
|
6385
|
+
emitOidcAnalyticsEvent(this._analytics, {
|
|
6386
|
+
type: 'consent',
|
|
6387
|
+
isSuccessful: false,
|
|
6388
|
+
uid: accountId,
|
|
6389
|
+
clientId: clientId,
|
|
6390
|
+
reason: 'scope_not_unlocked_for_client',
|
|
6391
|
+
durationMs: Date.now() - startedAt
|
|
6392
|
+
}, this._logger);
|
|
6393
|
+
res.json({
|
|
6394
|
+
redirectTo: redirectTo2
|
|
6395
|
+
});
|
|
6396
|
+
return [
|
|
6397
|
+
2
|
|
6398
|
+
];
|
|
6399
|
+
case 16:
|
|
6400
|
+
// Required gate: a scope a client's profiles force-require (`require: 'required'`) must be present
|
|
6401
|
+
// in the request. Reject when the client did not request a required scope.
|
|
6402
|
+
missingRequiredScopes = Array.from(clientRequiredScopes).filter(function(scope) {
|
|
6403
|
+
return !requestedOIDCScopeSet.has(scope);
|
|
6404
|
+
});
|
|
6405
|
+
if (!(missingRequiredScopes.length > 0)) return [
|
|
6406
|
+
3,
|
|
6407
|
+
18
|
|
6408
|
+
];
|
|
6409
|
+
return [
|
|
6410
|
+
4,
|
|
6411
|
+
this.oidcInteractionService.finishInteractionByUid(uid, {
|
|
6412
|
+
error: 'access_denied',
|
|
6413
|
+
error_description: "This client must request the required scope(s): ".concat(missingRequiredScopes.join(', '), ".")
|
|
6414
|
+
}, {
|
|
6415
|
+
mergeWithLastSubmission: true
|
|
6416
|
+
})
|
|
6417
|
+
];
|
|
6418
|
+
case 17:
|
|
6419
|
+
_ref7 = _state.sent(), redirectTo3 = _ref7.returnTo;
|
|
6420
|
+
emitOidcAnalyticsEvent(this._analytics, {
|
|
6421
|
+
type: 'consent',
|
|
6422
|
+
isSuccessful: false,
|
|
6423
|
+
uid: accountId,
|
|
6424
|
+
clientId: clientId,
|
|
6425
|
+
reason: 'required_scope_missing',
|
|
6426
|
+
durationMs: Date.now() - startedAt
|
|
6427
|
+
}, this._logger);
|
|
6428
|
+
res.json({
|
|
6429
|
+
redirectTo: redirectTo3
|
|
6430
|
+
});
|
|
6431
|
+
return [
|
|
6432
|
+
2
|
|
6433
|
+
];
|
|
6434
|
+
case 18:
|
|
6188
6435
|
// Resolve the requested login duration up-front. The configured Grant TTL function (in
|
|
6189
6436
|
// OidcService.buildProviderConfiguration) only fires when oidc-provider's koa middleware
|
|
6190
6437
|
// drives `grant.save()`, so its `ctx.oidc.params` lookup of `dbx_session_ttl` returns
|
|
6191
6438
|
// undefined when the consent submit runs in this controller. We pre-set `expiresIn` on
|
|
6192
6439
|
// newly-created grants so they persist with the correct (tiered) TTL.
|
|
6193
6440
|
requestedRawTtl = params[DBX_FIREBASE_SERVER_OIDC_SESSION_TTL_PARAM];
|
|
6194
|
-
|
|
6195
|
-
4,
|
|
6196
|
-
this.oidcService.findClientPayload(clientId)
|
|
6197
|
-
];
|
|
6198
|
-
case 14:
|
|
6199
|
-
clientPayload = _state.sent();
|
|
6200
|
-
clientMaxSessionTtl = (_ref2 = clientPayload === null || clientPayload === void 0 ? void 0 : clientPayload.dbx_max_session_ttl) !== null && _ref2 !== void 0 ? _ref2 : undefined;
|
|
6441
|
+
clientMaxSessionTtl = (_ref3 = clientPayload === null || clientPayload === void 0 ? void 0 : clientPayload.dbx_max_session_ttl) !== null && _ref3 !== void 0 ? _ref3 : undefined;
|
|
6201
6442
|
expiresInSeconds = this.oidcService.resolveLoginDurationForGrant(requestedRawTtl, {
|
|
6202
6443
|
dbx_max_session_ttl: clientMaxSessionTtl
|
|
6203
6444
|
}, {
|
|
@@ -6206,28 +6447,30 @@ var OidcInteractionController_1;
|
|
|
6206
6447
|
});
|
|
6207
6448
|
if (!(existingGrant !== null && existingGrant !== void 0)) return [
|
|
6208
6449
|
3,
|
|
6209
|
-
|
|
6450
|
+
19
|
|
6210
6451
|
];
|
|
6211
6452
|
_tmp2 = existingGrant;
|
|
6212
6453
|
return [
|
|
6213
6454
|
3,
|
|
6214
|
-
|
|
6455
|
+
21
|
|
6215
6456
|
];
|
|
6216
|
-
case
|
|
6457
|
+
case 19:
|
|
6217
6458
|
return [
|
|
6218
6459
|
4,
|
|
6219
6460
|
this.oidcInteractionService.findOrCreateGrant(interaction.grantId, accountId, clientId, expiresInSeconds)
|
|
6220
6461
|
];
|
|
6221
|
-
case
|
|
6462
|
+
case 20:
|
|
6222
6463
|
_tmp2 = _state.sent();
|
|
6223
|
-
_state.label =
|
|
6224
|
-
case
|
|
6464
|
+
_state.label = 21;
|
|
6465
|
+
case 21:
|
|
6225
6466
|
grant = _tmp2;
|
|
6226
6467
|
if (missingOIDCScope.length > 0) {
|
|
6468
|
+
// Force-grant the client's required profile scopes (in addition to `openid`) so they cannot be
|
|
6469
|
+
// dropped at consent — the required gate above already guarantees they were requested.
|
|
6227
6470
|
_resolveEffectiveSubset = resolveEffectiveSubset({
|
|
6228
6471
|
missing: missingOIDCScope,
|
|
6229
6472
|
requestedSubset: body.grantedOIDCScopes,
|
|
6230
|
-
alwaysGranted: ALWAYS_GRANTED_OIDC_SCOPES,
|
|
6473
|
+
alwaysGranted: _to_consumable_array$1(ALWAYS_GRANTED_OIDC_SCOPES).concat(_to_consumable_array$1(clientRequiredScopes)),
|
|
6231
6474
|
alreadyEncountered: encounteredOIDCScopes
|
|
6232
6475
|
}), granted = _resolveEffectiveSubset.granted, rejected = _resolveEffectiveSubset.rejected;
|
|
6233
6476
|
if (granted.length > 0) {
|
|
@@ -6324,7 +6567,7 @@ var OidcInteractionController_1;
|
|
|
6324
6567
|
4,
|
|
6325
6568
|
grant.save()
|
|
6326
6569
|
];
|
|
6327
|
-
case
|
|
6570
|
+
case 22:
|
|
6328
6571
|
grantId = _state.sent();
|
|
6329
6572
|
return [
|
|
6330
6573
|
4,
|
|
@@ -6336,8 +6579,8 @@ var OidcInteractionController_1;
|
|
|
6336
6579
|
mergeWithLastSubmission: true
|
|
6337
6580
|
})
|
|
6338
6581
|
];
|
|
6339
|
-
case
|
|
6340
|
-
|
|
6582
|
+
case 23:
|
|
6583
|
+
_ref8 = _state.sent(), redirectTo4 = _ref8.returnTo;
|
|
6341
6584
|
emitOidcAnalyticsEvent(this._analytics, {
|
|
6342
6585
|
type: 'consent',
|
|
6343
6586
|
isSuccessful: true,
|
|
@@ -6349,13 +6592,13 @@ var OidcInteractionController_1;
|
|
|
6349
6592
|
durationMs: Date.now() - startedAt
|
|
6350
6593
|
}, this._logger);
|
|
6351
6594
|
res.json({
|
|
6352
|
-
redirectTo:
|
|
6595
|
+
redirectTo: redirectTo4
|
|
6353
6596
|
});
|
|
6354
6597
|
return [
|
|
6355
6598
|
3,
|
|
6356
|
-
|
|
6599
|
+
25
|
|
6357
6600
|
];
|
|
6358
|
-
case
|
|
6601
|
+
case 24:
|
|
6359
6602
|
err = _state.sent();
|
|
6360
6603
|
emitOidcAnalyticsEvent(this._analytics, {
|
|
6361
6604
|
type: 'consent',
|
|
@@ -6370,7 +6613,7 @@ var OidcInteractionController_1;
|
|
|
6370
6613
|
throw err;
|
|
6371
6614
|
}
|
|
6372
6615
|
throw new common.HttpException('Consent interaction failed', common.HttpStatus.BAD_REQUEST);
|
|
6373
|
-
case
|
|
6616
|
+
case 25:
|
|
6374
6617
|
return [
|
|
6375
6618
|
2
|
|
6376
6619
|
];
|
|
@@ -7540,31 +7783,43 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
7540
7783
|
|
|
7541
7784
|
/**
|
|
7542
7785
|
* Builds a {@link AssertModelCrudRequestFunction} that rejects callModel requests
|
|
7543
|
-
* lacking the OIDC scope
|
|
7786
|
+
* lacking the required OIDC scope(s) for the call.
|
|
7787
|
+
*
|
|
7788
|
+
* Enforcement is additive: an OIDC caller must hold BOTH the per-verb scope mapped
|
|
7789
|
+
* from the call type (`model.<call>`) AND any per-function scope a handler declared
|
|
7790
|
+
* via `withApiDetails({ requiredScope })` — surfaced on `context.requiredScope`.
|
|
7544
7791
|
*
|
|
7545
7792
|
* Bypasses the check (no-op) when the request is not OIDC-authenticated — i.e.
|
|
7546
7793
|
* when {@link getOidcScopesFromRequest} returns `undefined` because there is no
|
|
7547
7794
|
* `auth.token.scope` claim on the request. Regular Firebase ID-token callers are
|
|
7548
7795
|
* unaffected and continue to be gated by auth roles.
|
|
7549
7796
|
*
|
|
7550
|
-
* Bypasses the check for custom (non-CRUD) call types
|
|
7551
|
-
* remain unrestricted unless an app wires its own
|
|
7797
|
+
* Bypasses the check for custom (non-CRUD) call types that declare no per-function
|
|
7798
|
+
* scope, so app-specific verbs remain unrestricted unless an app wires its own
|
|
7799
|
+
* assertion or declares a `requiredScope`.
|
|
7552
7800
|
*
|
|
7553
7801
|
* Wire as the `preAssert` of {@link onCallModel}.
|
|
7554
7802
|
*
|
|
7555
7803
|
* @returns The pre-assertion function ready to plug into `OnCallModelConfig.preAssert`.
|
|
7556
7804
|
*/ function oidcCallModelScopePreAssert() {
|
|
7557
7805
|
var fn = function fn(context) {
|
|
7558
|
-
var
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7806
|
+
var requiredScopes = util.filterMaybeArrayValues([
|
|
7807
|
+
firebase.callModelOidcScopeForCallType(context.call),
|
|
7808
|
+
context.requiredScope
|
|
7809
|
+
]);
|
|
7810
|
+
// No requirement (custom verb + no per-function scope) short-circuits without reading scopes.
|
|
7811
|
+
// A non-OIDC caller yields `undefined` scopes below and bypasses just like the per-verb check.
|
|
7812
|
+
var scopes = requiredScopes.length === 0 ? undefined : getOidcScopesFromRequest(context.request);
|
|
7813
|
+
var missingScopes = scopes == null ? [] : requiredScopes.filter(function(scope) {
|
|
7814
|
+
return !scopes.has(scope);
|
|
7815
|
+
});
|
|
7816
|
+
if (missingScopes.length > 0) {
|
|
7562
7817
|
throw firebaseServer.forbiddenError({
|
|
7563
7818
|
status: 403,
|
|
7564
7819
|
code: firebase.CALL_MODEL_MISSING_OIDC_SCOPE_ERROR_CODE,
|
|
7565
|
-
message: "Missing required OIDC scope for callModel: ".concat(
|
|
7820
|
+
message: "Missing required OIDC scope for callModel: ".concat(missingScopes.join(', ')),
|
|
7566
7821
|
data: {
|
|
7567
|
-
|
|
7822
|
+
requiredScopes: missingScopes,
|
|
7568
7823
|
call: context.call
|
|
7569
7824
|
}
|
|
7570
7825
|
});
|
|
@@ -7573,6 +7828,7 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
7573
7828
|
return fn;
|
|
7574
7829
|
}
|
|
7575
7830
|
|
|
7831
|
+
exports.DBX_FIREBASE_SERVER_OIDC_PROVIDER_PROFILES_CLIENT_METADATA = DBX_FIREBASE_SERVER_OIDC_PROVIDER_PROFILES_CLIENT_METADATA;
|
|
7576
7832
|
exports.DEFAULT_APP_OAUTH_CONSENT_PATH_PART = DEFAULT_APP_OAUTH_CONSENT_PATH_PART;
|
|
7577
7833
|
exports.DEFAULT_APP_OAUTH_INTERACTION_PATH = DEFAULT_APP_OAUTH_INTERACTION_PATH;
|
|
7578
7834
|
exports.DEFAULT_APP_OAUTH_LOGIN_PATH_PART = DEFAULT_APP_OAUTH_LOGIN_PATH_PART;
|
|
@@ -7635,6 +7891,8 @@ exports.jwksKeysWithStatusQuery = jwksKeysWithStatusQuery;
|
|
|
7635
7891
|
exports.nonRetiredJwksKeysQuery = nonRetiredJwksKeysQuery;
|
|
7636
7892
|
exports.noopOidcAnalyticsService = noopOidcAnalyticsService;
|
|
7637
7893
|
exports.oidcCallModelScopePreAssert = oidcCallModelScopePreAssert;
|
|
7894
|
+
exports.oidcClientProviderProfileScopes = oidcClientProviderProfileScopes;
|
|
7895
|
+
exports.oidcCorsOriginDelegate = oidcCorsOriginDelegate;
|
|
7638
7896
|
exports.oidcFirestoreCollectionsFactory = oidcFirestoreCollectionsFactory;
|
|
7639
7897
|
exports.oidcModelServerActions = oidcModelServerActions;
|
|
7640
7898
|
exports.oidcModelServerActionsFactory = oidcModelServerActionsFactory;
|