@dereekb/firebase-server 14.2.0 → 14.3.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/calcom/package.json +10 -10
- package/discord/package.json +10 -10
- package/mailgun/package.json +9 -9
- package/mcp/package.json +11 -11
- package/model/package.json +10 -10
- package/oidc/index.esm.js +322 -122
- package/oidc/package.json +10 -10
- package/oidc/src/lib/controller/oidc.interaction.controller.d.ts +3 -1
- package/oidc/src/lib/service/index.d.ts +1 -0
- package/oidc/src/lib/service/oidc.grant.d.ts +103 -0
- package/package.json +13 -13
- package/test/index.esm.js +84 -28
- package/test/package.json +11 -11
- package/test/src/lib/oidc/oidc.test.flow.d.ts +51 -0
- package/twilio/package.json +8 -8
- package/zoho/package.json +10 -10
package/oidc/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/oidc",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.3.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@dereekb/analytics": "14.
|
|
8
|
-
"@dereekb/date": "14.
|
|
9
|
-
"@dereekb/firebase": "14.
|
|
10
|
-
"@dereekb/firebase-server": "14.
|
|
11
|
-
"@dereekb/model": "14.
|
|
12
|
-
"@dereekb/nestjs": "14.
|
|
13
|
-
"@dereekb/rxjs": "14.
|
|
14
|
-
"@dereekb/util": "14.
|
|
15
|
-
"@dereekb/zoho": "14.
|
|
7
|
+
"@dereekb/analytics": "14.3.0",
|
|
8
|
+
"@dereekb/date": "14.3.0",
|
|
9
|
+
"@dereekb/firebase": "14.3.0",
|
|
10
|
+
"@dereekb/firebase-server": "14.3.0",
|
|
11
|
+
"@dereekb/model": "14.3.0",
|
|
12
|
+
"@dereekb/nestjs": "14.3.0",
|
|
13
|
+
"@dereekb/rxjs": "14.3.0",
|
|
14
|
+
"@dereekb/util": "14.3.0",
|
|
15
|
+
"@dereekb/zoho": "14.3.0",
|
|
16
16
|
"@nestjs/common": "^12.0.1",
|
|
17
17
|
"@nestjs/config": "^12.0.0",
|
|
18
18
|
"express": "^5.2.1",
|
|
@@ -86,7 +86,9 @@ export interface ResolveEffectiveSubsetInput {
|
|
|
86
86
|
*/
|
|
87
87
|
readonly alwaysGranted?: readonly string[];
|
|
88
88
|
/**
|
|
89
|
-
* Entries the existing Grant has
|
|
89
|
+
* Entries the existing Grant has already decided and this consent leaves as-is. Tolerated as no-ops on
|
|
90
|
+
* re-consent. A previously-rejected entry the request names again belongs in `missing` instead — see
|
|
91
|
+
* `reconsiderRejectedValues` — or it can never be granted on that Grant.
|
|
90
92
|
*/
|
|
91
93
|
readonly alreadyEncountered?: readonly string[];
|
|
92
94
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { type Grant } from 'oidc-provider';
|
|
2
|
+
/**
|
|
3
|
+
* Removes previously-rejected OIDC scopes from a Grant's rejected set.
|
|
4
|
+
*
|
|
5
|
+
* oidc-provider exposes `rejectOIDCScope()` but no inverse, and a rejected scope is subtracted from
|
|
6
|
+
* `getOIDCScope()` on every read — so `addOIDCScope()` alone cannot put a once-rejected scope back in
|
|
7
|
+
* force. `rejected` is plain persisted data (`Pick<Grant, 'openid' | 'resources'>`), which is what
|
|
8
|
+
* makes editing it directly the supported shape of an un-reject.
|
|
9
|
+
*
|
|
10
|
+
* @param grant - The grant to edit in place.
|
|
11
|
+
* @param scopes - The scopes to un-reject. Scopes not currently rejected are ignored.
|
|
12
|
+
*/
|
|
13
|
+
export declare function unrejectOIDCScopes(grant: Grant, scopes: Iterable<string>): void;
|
|
14
|
+
/**
|
|
15
|
+
* Removes previously-rejected OIDC claims from a Grant's rejected set.
|
|
16
|
+
*
|
|
17
|
+
* @param grant - The grant to edit in place.
|
|
18
|
+
* @param claims - The claims to un-reject. Claims not currently rejected are ignored.
|
|
19
|
+
* @see unrejectOIDCScopes
|
|
20
|
+
*/
|
|
21
|
+
export declare function unrejectOIDCClaims(grant: Grant, claims: Iterable<string>): void;
|
|
22
|
+
/**
|
|
23
|
+
* Removes previously-rejected resource scopes for one resource indicator from a Grant's rejected set.
|
|
24
|
+
*
|
|
25
|
+
* @param grant - The grant to edit in place.
|
|
26
|
+
* @param resource - The resource indicator.
|
|
27
|
+
* @param scopes - The scopes to un-reject. Scopes not currently rejected for the resource are ignored.
|
|
28
|
+
* @see unrejectOIDCScopes
|
|
29
|
+
*/
|
|
30
|
+
export declare function unrejectResourceScopes(grant: Grant, resource: string, scopes: Iterable<string>): void;
|
|
31
|
+
/**
|
|
32
|
+
* Input for {@link reconsiderRejectedValues}.
|
|
33
|
+
*/
|
|
34
|
+
export interface ReconsiderRejectedValuesInput {
|
|
35
|
+
/**
|
|
36
|
+
* Values oidc-provider reports as still undecided for this consent (e.g. `prompt.details.missingOIDCScope`).
|
|
37
|
+
*/
|
|
38
|
+
readonly missing: readonly string[];
|
|
39
|
+
/**
|
|
40
|
+
* Values the existing Grant has already decided — granted or rejected.
|
|
41
|
+
*/
|
|
42
|
+
readonly encountered: readonly string[];
|
|
43
|
+
/**
|
|
44
|
+
* The subset of `encountered` the existing Grant has REJECTED.
|
|
45
|
+
*/
|
|
46
|
+
readonly rejected: readonly string[];
|
|
47
|
+
/**
|
|
48
|
+
* Values the current authorization request asks for. Only a rejected value the request names again is
|
|
49
|
+
* reconsidered; a rejection from an earlier, wider request stays in force.
|
|
50
|
+
*/
|
|
51
|
+
readonly requested: ReadonlySet<string>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Output of {@link reconsiderRejectedValues}.
|
|
55
|
+
*/
|
|
56
|
+
export interface ReconsiderRejectedValuesResult {
|
|
57
|
+
/**
|
|
58
|
+
* `missing` plus the reconsidered values, so a consent decides them again.
|
|
59
|
+
*/
|
|
60
|
+
readonly missing: string[];
|
|
61
|
+
/**
|
|
62
|
+
* `encountered` minus the reconsidered values, so they are no longer treated as settled no-ops.
|
|
63
|
+
*/
|
|
64
|
+
readonly encountered: string[];
|
|
65
|
+
/**
|
|
66
|
+
* The values moved from `encountered` back into `missing`: rejected on the Grant and named by the
|
|
67
|
+
* current request. A consent that grants one of these must un-reject it on the Grant as well.
|
|
68
|
+
*/
|
|
69
|
+
readonly reconsidered: string[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Moves previously-rejected values the current request asks for again from the "encountered" set back into
|
|
73
|
+
* the "missing" set, so a re-consent decides them afresh.
|
|
74
|
+
*
|
|
75
|
+
* oidc-provider counts a rejected value as encountered: it never reappears in the prompt's `missing*`
|
|
76
|
+
* details, so without this a consent that names it again is a silent no-op and the value can never be
|
|
77
|
+
* granted on that Grant — even when the user explicitly ticks it. Values the Grant has GRANTED are left in
|
|
78
|
+
* `encountered`: they are already in force and need no re-application.
|
|
79
|
+
*
|
|
80
|
+
* @param input - The missing, encountered, rejected, and requested sets.
|
|
81
|
+
* @returns The adjusted missing/encountered sets plus the reconsidered values.
|
|
82
|
+
*
|
|
83
|
+
* @__NO_SIDE_EFFECTS__
|
|
84
|
+
*/
|
|
85
|
+
export declare function reconsiderRejectedValues(input: ReconsiderRejectedValuesInput): ReconsiderRejectedValuesResult;
|
|
86
|
+
/**
|
|
87
|
+
* Names every claim an authorization request's `claims` parameter asks for, across `id_token` and `userinfo`.
|
|
88
|
+
*
|
|
89
|
+
* @param claimsParam - The raw `claims` request parameter (a JSON string), or undefined.
|
|
90
|
+
* @returns The requested claim names; empty when the parameter is absent or malformed.
|
|
91
|
+
*
|
|
92
|
+
* @__NO_SIDE_EFFECTS__
|
|
93
|
+
*/
|
|
94
|
+
export declare function requestedOIDCClaimNames(claimsParam: unknown): Set<string>;
|
|
95
|
+
/**
|
|
96
|
+
* Normalizes an authorization request's `resource` parameter to its list of resource indicators.
|
|
97
|
+
*
|
|
98
|
+
* @param resourceParam - The raw `resource` request parameter (a string, an array of strings, or undefined).
|
|
99
|
+
* @returns The resource indicators; empty when the parameter is absent.
|
|
100
|
+
*
|
|
101
|
+
* @__NO_SIDE_EFFECTS__
|
|
102
|
+
*/
|
|
103
|
+
export declare function requestedResourceIndicators(resourceParam: unknown): string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
@@ -57,18 +57,18 @@
|
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"@cantoo/pdf-lib": "
|
|
61
|
-
"@dereekb/analytics": "14.
|
|
62
|
-
"@dereekb/calcom": "14.
|
|
63
|
-
"@dereekb/date": "14.
|
|
64
|
-
"@dereekb/dbx-core": "14.
|
|
65
|
-
"@dereekb/discord": "14.
|
|
66
|
-
"@dereekb/firebase": "14.
|
|
67
|
-
"@dereekb/model": "14.
|
|
68
|
-
"@dereekb/nestjs": "14.
|
|
69
|
-
"@dereekb/rxjs": "14.
|
|
70
|
-
"@dereekb/util": "14.
|
|
71
|
-
"@dereekb/zoho": "14.
|
|
60
|
+
"@cantoo/pdf-lib": ">=2.6.5 <2.11.0",
|
|
61
|
+
"@dereekb/analytics": "14.3.0",
|
|
62
|
+
"@dereekb/calcom": "14.3.0",
|
|
63
|
+
"@dereekb/date": "14.3.0",
|
|
64
|
+
"@dereekb/dbx-core": "14.3.0",
|
|
65
|
+
"@dereekb/discord": "14.3.0",
|
|
66
|
+
"@dereekb/firebase": "14.3.0",
|
|
67
|
+
"@dereekb/model": "14.3.0",
|
|
68
|
+
"@dereekb/nestjs": "14.3.0",
|
|
69
|
+
"@dereekb/rxjs": "14.3.0",
|
|
70
|
+
"@dereekb/util": "14.3.0",
|
|
71
|
+
"@dereekb/zoho": "14.3.0",
|
|
72
72
|
"@google-cloud/firestore": "^7.11.6",
|
|
73
73
|
"@google-cloud/storage": "^7.22.0",
|
|
74
74
|
"@modelcontextprotocol/node": "2.0.0",
|
package/test/index.esm.js
CHANGED
|
@@ -13,7 +13,7 @@ import { HttpsError } from 'firebase-functions/https';
|
|
|
13
13
|
import { BaseError } from 'make-error';
|
|
14
14
|
import request from 'supertest';
|
|
15
15
|
import { randomBytes, createHash } from 'node:crypto';
|
|
16
|
-
import { OidcClientService, JwksService, OidcAccountService } from '@dereekb/firebase-server/oidc';
|
|
16
|
+
import { OidcProviderConfigService, OidcClientService, JwksService, OidcAccountService } from '@dereekb/firebase-server/oidc';
|
|
17
17
|
|
|
18
18
|
function _assert_this_initialized$9(self) {
|
|
19
19
|
if (self === void 0) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
@@ -4767,6 +4767,16 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4767
4767
|
var url = location.startsWith('/') ? new URL(location, 'http://localhost') : new URL(location);
|
|
4768
4768
|
return url.searchParams.get('uid');
|
|
4769
4769
|
}
|
|
4770
|
+
/**
|
|
4771
|
+
* Whether a redirect response points at the given interaction frontend URL (the login or consent screen).
|
|
4772
|
+
*
|
|
4773
|
+
* @param res - Supertest response to inspect.
|
|
4774
|
+
* @param frontendUrl - The frontend URL to match, without its query string.
|
|
4775
|
+
* @returns True when the response's `Location` header starts with `frontendUrl`.
|
|
4776
|
+
*/ function isRedirectTo(res, frontendUrl) {
|
|
4777
|
+
var location = res.headers['location'];
|
|
4778
|
+
return location != null && location.startsWith(frontendUrl);
|
|
4779
|
+
}
|
|
4770
4780
|
/**
|
|
4771
4781
|
* Cookie jar helpers for the OAuth flow.
|
|
4772
4782
|
*
|
|
@@ -4873,15 +4883,16 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4873
4883
|
* @throws {Error} When the token exchange step fails (the response body and status are included in the message).
|
|
4874
4884
|
*/ function performFullOAuthFlow(input) {
|
|
4875
4885
|
return _async_to_generator$1(function() {
|
|
4876
|
-
var _ref, _ref1, _ref2, server, oidcClientService, nestApp, uid, config,
|
|
4886
|
+
var _ref, _ref1, _ref2, _ref3, _ref4, _config_session, _config_session1, server, oidcClientService, nestApp, uid, config, cookieJar, collectCookies, cookieHeader, redirectUri, clientName, tokenEndpointAuthMethod, providerProfiles, scopes, client, _ref5, client_id, client_secret, client_id1, client_secret1, codeVerifier, codeChallenge, authRes, idToken, providerConfigService, interactionRes, loginUid, loginRes, resumeAfterLoginPath, callbackRedirectRes, consentUid, consentRes, resumeAfterConsentPath, callbackUrl, authorizationCode, tokenRes;
|
|
4877
4887
|
return _ts_generator$1(this, function(_state) {
|
|
4878
4888
|
switch(_state.label){
|
|
4879
4889
|
case 0:
|
|
4880
4890
|
server = input.server, oidcClientService = input.oidcClientService, nestApp = input.nestApp, uid = input.uid, config = input.config;
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4891
|
+
cookieJar = (_ref = config === null || config === void 0 ? void 0 : (_config_session = config.session) === null || _config_session === void 0 ? void 0 : _config_session.cookieJar) !== null && _ref !== void 0 ? _ref : createCookieJar();
|
|
4892
|
+
collectCookies = cookieJar.collectCookies, cookieHeader = cookieJar.cookieHeader;
|
|
4893
|
+
redirectUri = (_ref1 = (_ref2 = config === null || config === void 0 ? void 0 : (_config_session1 = config.session) === null || _config_session1 === void 0 ? void 0 : _config_session1.client.redirectUri) !== null && _ref2 !== void 0 ? _ref2 : config === null || config === void 0 ? void 0 : config.redirectUri) !== null && _ref1 !== void 0 ? _ref1 : 'https://example.com/callback';
|
|
4894
|
+
clientName = (_ref3 = config === null || config === void 0 ? void 0 : config.clientName) !== null && _ref3 !== void 0 ? _ref3 : 'test-oauth-context';
|
|
4895
|
+
tokenEndpointAuthMethod = (_ref4 = config === null || config === void 0 ? void 0 : config.tokenEndpointAuthMethod) !== null && _ref4 !== void 0 ? _ref4 : 'client_secret_post';
|
|
4885
4896
|
providerProfiles = config === null || config === void 0 ? void 0 : config.providerProfiles;
|
|
4886
4897
|
return [
|
|
4887
4898
|
4,
|
|
@@ -4889,6 +4900,16 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4889
4900
|
];
|
|
4890
4901
|
case 1:
|
|
4891
4902
|
scopes = _state.sent();
|
|
4903
|
+
if (!(config === null || config === void 0 ? void 0 : config.session)) return [
|
|
4904
|
+
3,
|
|
4905
|
+
2
|
|
4906
|
+
];
|
|
4907
|
+
client = config.session.client;
|
|
4908
|
+
return [
|
|
4909
|
+
3,
|
|
4910
|
+
4
|
|
4911
|
+
];
|
|
4912
|
+
case 2:
|
|
4892
4913
|
return [
|
|
4893
4914
|
4,
|
|
4894
4915
|
oidcClientService.createClient(_object_spread({
|
|
@@ -4901,15 +4922,23 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4901
4922
|
dbx_provider_profiles: _to_consumable_array(providerProfiles)
|
|
4902
4923
|
}))
|
|
4903
4924
|
];
|
|
4904
|
-
case
|
|
4905
|
-
|
|
4925
|
+
case 3:
|
|
4926
|
+
_ref5 = _state.sent(), client_id = _ref5.client_id, client_secret = _ref5.client_secret;
|
|
4927
|
+
client = {
|
|
4928
|
+
client_id: client_id,
|
|
4929
|
+
client_secret: client_secret,
|
|
4930
|
+
redirectUri: redirectUri
|
|
4931
|
+
};
|
|
4932
|
+
_state.label = 4;
|
|
4933
|
+
case 4:
|
|
4934
|
+
client_id1 = client.client_id, client_secret1 = client.client_secret;
|
|
4906
4935
|
// 2. Generate PKCE code_verifier and code_challenge
|
|
4907
4936
|
codeVerifier = randomBytes(32).toString('base64url');
|
|
4908
4937
|
codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url');
|
|
4909
4938
|
return [
|
|
4910
4939
|
4,
|
|
4911
|
-
request(server).get('/oidc/auth').query({
|
|
4912
|
-
client_id:
|
|
4940
|
+
request(server).get('/oidc/auth').query(_object_spread({
|
|
4941
|
+
client_id: client_id1,
|
|
4913
4942
|
redirect_uri: redirectUri,
|
|
4914
4943
|
response_type: 'code',
|
|
4915
4944
|
scope: scopes,
|
|
@@ -4917,25 +4946,33 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4917
4946
|
code_challenge_method: 'S256',
|
|
4918
4947
|
state: 'test-state',
|
|
4919
4948
|
nonce: 'test-nonce'
|
|
4920
|
-
}
|
|
4949
|
+
}, (config === null || config === void 0 ? void 0 : config.prompt) == null ? {} : {
|
|
4950
|
+
prompt: config.prompt
|
|
4951
|
+
})).redirects(0)
|
|
4921
4952
|
];
|
|
4922
|
-
case
|
|
4953
|
+
case 5:
|
|
4923
4954
|
authRes = _state.sent();
|
|
4924
4955
|
collectCookies(authRes);
|
|
4925
|
-
loginUid = extractInteractionUid(authRes);
|
|
4926
4956
|
return [
|
|
4927
4957
|
4,
|
|
4928
4958
|
createTestIdToken(nestApp, uid)
|
|
4929
4959
|
];
|
|
4930
|
-
case
|
|
4960
|
+
case 6:
|
|
4931
4961
|
idToken = _state.sent();
|
|
4962
|
+
providerConfigService = nestApp.get(OidcProviderConfigService);
|
|
4963
|
+
interactionRes = authRes;
|
|
4964
|
+
if (!isRedirectTo(authRes, providerConfigService.appLoginUrl)) return [
|
|
4965
|
+
3,
|
|
4966
|
+
9
|
|
4967
|
+
];
|
|
4968
|
+
loginUid = extractInteractionUid(authRes);
|
|
4932
4969
|
return [
|
|
4933
4970
|
4,
|
|
4934
4971
|
request(server).post("/interaction/".concat(loginUid, "/login")).set('Cookie', cookieHeader()).send({
|
|
4935
4972
|
idToken: idToken
|
|
4936
4973
|
})
|
|
4937
4974
|
];
|
|
4938
|
-
case
|
|
4975
|
+
case 7:
|
|
4939
4976
|
loginRes = _state.sent();
|
|
4940
4977
|
// 5. Resume after login → consent redirect
|
|
4941
4978
|
resumeAfterLoginPath = new URL(loginRes.body.redirectTo).pathname + new URL(loginRes.body.redirectTo).search;
|
|
@@ -4943,18 +4980,28 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4943
4980
|
4,
|
|
4944
4981
|
request(server).get(resumeAfterLoginPath).set('Cookie', cookieHeader()).redirects(0)
|
|
4945
4982
|
];
|
|
4946
|
-
case
|
|
4947
|
-
|
|
4948
|
-
collectCookies(
|
|
4949
|
-
|
|
4983
|
+
case 8:
|
|
4984
|
+
interactionRes = _state.sent();
|
|
4985
|
+
collectCookies(interactionRes);
|
|
4986
|
+
_state.label = 9;
|
|
4987
|
+
case 9:
|
|
4988
|
+
// 6. Approve consent — unless nothing needed consenting and the provider went straight to the callback
|
|
4989
|
+
callbackRedirectRes = interactionRes;
|
|
4990
|
+
if (!isRedirectTo(interactionRes, providerConfigService.appConsentUrl)) return [
|
|
4991
|
+
3,
|
|
4992
|
+
12
|
|
4993
|
+
];
|
|
4994
|
+
consentUid = extractInteractionUid(interactionRes);
|
|
4950
4995
|
return [
|
|
4951
4996
|
4,
|
|
4952
|
-
request(server).post("/interaction/".concat(consentUid, "/consent")).set('Cookie', cookieHeader()).send({
|
|
4997
|
+
request(server).post("/interaction/".concat(consentUid, "/consent")).set('Cookie', cookieHeader()).send(_object_spread({
|
|
4953
4998
|
idToken: idToken,
|
|
4954
4999
|
approved: true
|
|
4955
|
-
})
|
|
5000
|
+
}, (config === null || config === void 0 ? void 0 : config.grantedOIDCScopes) == null ? {} : {
|
|
5001
|
+
grantedOIDCScopes: _to_consumable_array(config.grantedOIDCScopes)
|
|
5002
|
+
}))
|
|
4956
5003
|
];
|
|
4957
|
-
case
|
|
5004
|
+
case 10:
|
|
4958
5005
|
consentRes = _state.sent();
|
|
4959
5006
|
// 7. Follow resume redirect → callback with authorization code
|
|
4960
5007
|
resumeAfterConsentPath = new URL(consentRes.body.redirectTo).pathname + new URL(consentRes.body.redirectTo).search;
|
|
@@ -4962,9 +5009,11 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4962
5009
|
4,
|
|
4963
5010
|
request(server).get(resumeAfterConsentPath).set('Cookie', cookieHeader()).redirects(0)
|
|
4964
5011
|
];
|
|
4965
|
-
case
|
|
5012
|
+
case 11:
|
|
4966
5013
|
callbackRedirectRes = _state.sent();
|
|
4967
5014
|
collectCookies(callbackRedirectRes);
|
|
5015
|
+
_state.label = 12;
|
|
5016
|
+
case 12:
|
|
4968
5017
|
callbackUrl = new URL(callbackRedirectRes.headers['location']);
|
|
4969
5018
|
authorizationCode = callbackUrl.searchParams.get('code');
|
|
4970
5019
|
return [
|
|
@@ -4973,12 +5022,12 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4973
5022
|
grant_type: 'authorization_code',
|
|
4974
5023
|
code: authorizationCode,
|
|
4975
5024
|
redirect_uri: redirectUri,
|
|
4976
|
-
client_id:
|
|
4977
|
-
client_secret:
|
|
5025
|
+
client_id: client_id1,
|
|
5026
|
+
client_secret: client_secret1,
|
|
4978
5027
|
code_verifier: codeVerifier
|
|
4979
5028
|
})
|
|
4980
5029
|
];
|
|
4981
|
-
case
|
|
5030
|
+
case 13:
|
|
4982
5031
|
tokenRes = _state.sent();
|
|
4983
5032
|
if (!tokenRes.body.access_token) {
|
|
4984
5033
|
throw new Error("OAuth token exchange failed (status ".concat(tokenRes.status, "): ").concat(JSON.stringify(tokenRes.body)));
|
|
@@ -4987,7 +5036,12 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4987
5036
|
2,
|
|
4988
5037
|
{
|
|
4989
5038
|
accessToken: tokenRes.body.access_token,
|
|
4990
|
-
idToken: tokenRes.body.id_token
|
|
5039
|
+
idToken: tokenRes.body.id_token,
|
|
5040
|
+
scope: tokenRes.body.scope,
|
|
5041
|
+
session: {
|
|
5042
|
+
client: client,
|
|
5043
|
+
cookieJar: cookieJar
|
|
5044
|
+
}
|
|
4991
5045
|
}
|
|
4992
5046
|
];
|
|
4993
5047
|
}
|
|
@@ -5425,7 +5479,9 @@ function _type_of(obj) {
|
|
|
5425
5479
|
"makeFixture",
|
|
5426
5480
|
"makeInstance"
|
|
5427
5481
|
]);
|
|
5428
|
-
var flowConfig =
|
|
5482
|
+
var flowConfig = Object.values(flowConfigOverrides).some(function(value) {
|
|
5483
|
+
return value != null;
|
|
5484
|
+
}) ? flowConfigOverrides : undefined;
|
|
5429
5485
|
return function(params, buildTests) {
|
|
5430
5486
|
var f = params.f, u = params.u;
|
|
5431
5487
|
describe('(oauth)', function() {
|
package/test/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/test",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.3.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@dereekb/analytics": "14.
|
|
8
|
-
"@dereekb/date": "14.
|
|
9
|
-
"@dereekb/firebase": "14.
|
|
10
|
-
"@dereekb/firebase-server": "14.
|
|
11
|
-
"@dereekb/firebase-server/oidc": "14.
|
|
12
|
-
"@dereekb/model": "14.
|
|
13
|
-
"@dereekb/nestjs": "14.
|
|
14
|
-
"@dereekb/rxjs": "14.
|
|
15
|
-
"@dereekb/util": "14.
|
|
7
|
+
"@dereekb/analytics": "14.3.0",
|
|
8
|
+
"@dereekb/date": "14.3.0",
|
|
9
|
+
"@dereekb/firebase": "14.3.0",
|
|
10
|
+
"@dereekb/firebase-server": "14.3.0",
|
|
11
|
+
"@dereekb/firebase-server/oidc": "14.3.0",
|
|
12
|
+
"@dereekb/model": "14.3.0",
|
|
13
|
+
"@dereekb/nestjs": "14.3.0",
|
|
14
|
+
"@dereekb/rxjs": "14.3.0",
|
|
15
|
+
"@dereekb/util": "14.3.0",
|
|
16
16
|
"@google-cloud/firestore": "^7.11.6",
|
|
17
17
|
"@google-cloud/storage": "^7.22.0",
|
|
18
18
|
"@nestjs/common": "^12.0.1",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"supertest": "^7.2.2"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@dereekb/nestjs": "14.
|
|
28
|
+
"@dereekb/nestjs": "14.3.0"
|
|
29
29
|
},
|
|
30
30
|
"exports": {
|
|
31
31
|
"./package.json": "./package.json",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import request from 'supertest';
|
|
1
2
|
import { type INestApplication } from '@nestjs/common';
|
|
2
3
|
import { type OidcProviderProfileKey, type OidcTokenEndpointAuthMethod } from '@dereekb/firebase';
|
|
3
4
|
import { OidcClientService } from '@dereekb/firebase-server/oidc';
|
|
@@ -33,10 +34,60 @@ export interface OAuthTestFlowConfig {
|
|
|
33
34
|
* "all registered scopes" resolution deliberately drops assignment-only scopes.
|
|
34
35
|
*/
|
|
35
36
|
readonly providerProfiles?: readonly OidcProviderProfileKey[];
|
|
37
|
+
/**
|
|
38
|
+
* OAuth `prompt` parameter for the authorization request (e.g. `'consent'` to force the consent screen
|
|
39
|
+
* on a session that has already authorized the client). Omitted by default.
|
|
40
|
+
*/
|
|
41
|
+
readonly prompt?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Explicit subset of the requested OIDC scopes to grant at consent (the consent request's
|
|
44
|
+
* `grantedOIDCScopes`). Omitted by default, which grants every requested scope.
|
|
45
|
+
*/
|
|
46
|
+
readonly grantedOIDCScopes?: readonly string[];
|
|
47
|
+
/**
|
|
48
|
+
* A prior flow's client and cookies to run this flow against — the same OAuth client, the same
|
|
49
|
+
* provider session, and therefore the same Grant. Omitted by default, which creates a fresh client
|
|
50
|
+
* and starts a fresh session.
|
|
51
|
+
*
|
|
52
|
+
* When the session is still logged in, the provider skips the login prompt and the flow goes straight
|
|
53
|
+
* to consent (or straight to the callback when nothing new needs consenting and `prompt` is unset).
|
|
54
|
+
*/
|
|
55
|
+
readonly session?: OAuthTestFlowSession;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The client and cookies a flow ran with, for chaining a second flow onto the same provider session.
|
|
59
|
+
*/
|
|
60
|
+
export interface OAuthTestFlowSession {
|
|
61
|
+
readonly client: OAuthTestFlowClient;
|
|
62
|
+
readonly cookieJar: OAuthTestFlowCookieJar;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The OAuth client a flow created (or reused).
|
|
66
|
+
*/
|
|
67
|
+
export interface OAuthTestFlowClient {
|
|
68
|
+
readonly client_id: string;
|
|
69
|
+
readonly client_secret?: string;
|
|
70
|
+
readonly redirectUri: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Cookie jar helpers for the OAuth flow. See {@link createCookieJar}.
|
|
74
|
+
*/
|
|
75
|
+
export interface OAuthTestFlowCookieJar {
|
|
76
|
+
readonly collectCookies: (res: request.Response) => void;
|
|
77
|
+
readonly cookieHeader: () => string;
|
|
36
78
|
}
|
|
37
79
|
export interface PerformFullOAuthFlowResult {
|
|
38
80
|
readonly accessToken: string;
|
|
39
81
|
readonly idToken: string;
|
|
82
|
+
/**
|
|
83
|
+
* The space-separated scope the token endpoint reported for the access token.
|
|
84
|
+
*/
|
|
85
|
+
readonly scope: string;
|
|
86
|
+
/**
|
|
87
|
+
* The client and cookies this flow ran with, for chaining another flow onto the same session via
|
|
88
|
+
* {@link OAuthTestFlowConfig.session}.
|
|
89
|
+
*/
|
|
90
|
+
readonly session: OAuthTestFlowSession;
|
|
40
91
|
}
|
|
41
92
|
/**
|
|
42
93
|
* Input for {@link performFullOAuthFlow}.
|
package/twilio/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/twilio",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.3.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@dereekb/date": "14.
|
|
8
|
-
"@dereekb/firebase": "14.
|
|
9
|
-
"@dereekb/firebase-server": "14.
|
|
10
|
-
"@dereekb/model": "14.
|
|
11
|
-
"@dereekb/nestjs": "14.
|
|
12
|
-
"@dereekb/rxjs": "14.
|
|
13
|
-
"@dereekb/util": "14.
|
|
7
|
+
"@dereekb/date": "14.3.0",
|
|
8
|
+
"@dereekb/firebase": "14.3.0",
|
|
9
|
+
"@dereekb/firebase-server": "14.3.0",
|
|
10
|
+
"@dereekb/model": "14.3.0",
|
|
11
|
+
"@dereekb/nestjs": "14.3.0",
|
|
12
|
+
"@dereekb/rxjs": "14.3.0",
|
|
13
|
+
"@dereekb/util": "14.3.0"
|
|
14
14
|
},
|
|
15
15
|
"exports": {
|
|
16
16
|
"./package.json": "./package.json",
|
package/zoho/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/zoho",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.3.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@dereekb/analytics": "14.
|
|
8
|
-
"@dereekb/date": "14.
|
|
9
|
-
"@dereekb/model": "14.
|
|
10
|
-
"@dereekb/nestjs": "14.
|
|
11
|
-
"@dereekb/rxjs": "14.
|
|
12
|
-
"@dereekb/firebase": "14.
|
|
13
|
-
"@dereekb/firebase-server": "14.
|
|
14
|
-
"@dereekb/util": "14.
|
|
15
|
-
"@dereekb/zoho": "14.
|
|
7
|
+
"@dereekb/analytics": "14.3.0",
|
|
8
|
+
"@dereekb/date": "14.3.0",
|
|
9
|
+
"@dereekb/model": "14.3.0",
|
|
10
|
+
"@dereekb/nestjs": "14.3.0",
|
|
11
|
+
"@dereekb/rxjs": "14.3.0",
|
|
12
|
+
"@dereekb/firebase": "14.3.0",
|
|
13
|
+
"@dereekb/firebase-server": "14.3.0",
|
|
14
|
+
"@dereekb/util": "14.3.0",
|
|
15
|
+
"@dereekb/zoho": "14.3.0",
|
|
16
16
|
"@nestjs/common": "^12.0.1",
|
|
17
17
|
"@nestjs/config": "^12.0.0",
|
|
18
18
|
"express": "^5.2.1"
|