@atproto/oauth-provider 0.1.3 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +35 -0
- package/dist/account/account.d.ts +6 -2
- package/dist/account/account.d.ts.map +1 -1
- package/dist/assets/app/bundle-manifest.json +3 -3
- package/dist/assets/app/main.css +1 -1
- package/dist/assets/app/main.js +1 -1
- package/dist/assets/app/main.js.map +1 -1
- package/dist/assets/assets-middleware.d.ts +2 -1
- package/dist/assets/assets-middleware.d.ts.map +1 -1
- package/dist/assets/assets-middleware.js +7 -0
- package/dist/assets/assets-middleware.js.map +1 -1
- package/dist/client/client-manager.d.ts +4 -3
- package/dist/client/client-manager.d.ts.map +1 -1
- package/dist/client/client-manager.js +60 -37
- package/dist/client/client-manager.js.map +1 -1
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +1 -3
- package/dist/client/client.js.map +1 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -1
- package/dist/constants.js.map +1 -1
- package/dist/device/device-manager.d.ts +1 -1
- package/dist/device/device-manager.d.ts.map +1 -1
- package/dist/device/device-manager.js +2 -2
- package/dist/device/device-manager.js.map +1 -1
- package/dist/errors/invalid-authorization-details-error.d.ts +4 -3
- package/dist/errors/invalid-authorization-details-error.d.ts.map +1 -1
- package/dist/errors/invalid-authorization-details-error.js +4 -4
- package/dist/errors/invalid-authorization-details-error.js.map +1 -1
- package/dist/lib/http/request.d.ts +3 -0
- package/dist/lib/http/request.d.ts.map +1 -1
- package/dist/lib/http/request.js +24 -12
- package/dist/lib/http/request.js.map +1 -1
- package/dist/metadata/build-metadata.d.ts +0 -1
- package/dist/metadata/build-metadata.d.ts.map +1 -1
- package/dist/metadata/build-metadata.js +9 -35
- package/dist/metadata/build-metadata.js.map +1 -1
- package/dist/oauth-hooks.d.ts +3 -10
- package/dist/oauth-hooks.d.ts.map +1 -1
- package/dist/oauth-provider.d.ts +8 -13
- package/dist/oauth-provider.d.ts.map +1 -1
- package/dist/oauth-provider.js +169 -109
- package/dist/oauth-provider.js.map +1 -1
- package/dist/oauth-verifier.d.ts +1 -2
- package/dist/oauth-verifier.d.ts.map +1 -1
- package/dist/oauth-verifier.js.map +1 -1
- package/dist/output/build-authorize-data.d.ts +6 -0
- package/dist/output/build-authorize-data.d.ts.map +1 -1
- package/dist/output/build-authorize-data.js +1 -0
- package/dist/output/build-authorize-data.js.map +1 -1
- package/dist/replay/replay-manager.d.ts +1 -0
- package/dist/replay/replay-manager.d.ts.map +1 -1
- package/dist/replay/replay-manager.js +3 -0
- package/dist/replay/replay-manager.js.map +1 -1
- package/dist/replay/replay-store.d.ts +1 -1
- package/dist/request/request-info.d.ts +2 -0
- package/dist/request/request-info.d.ts.map +1 -1
- package/dist/request/request-manager.d.ts +3 -9
- package/dist/request/request-manager.d.ts.map +1 -1
- package/dist/request/request-manager.js +52 -77
- package/dist/request/request-manager.js.map +1 -1
- package/dist/request/types.d.ts +10 -10
- package/dist/signer/signed-token-payload.d.ts +85 -85
- package/dist/signer/signer.d.ts +23 -30
- package/dist/signer/signer.d.ts.map +1 -1
- package/dist/signer/signer.js +0 -40
- package/dist/signer/signer.js.map +1 -1
- package/dist/token/token-claims.d.ts +81 -81
- package/dist/token/token-manager.d.ts +1 -2
- package/dist/token/token-manager.d.ts.map +1 -1
- package/dist/token/token-manager.js +10 -37
- package/dist/token/token-manager.js.map +1 -1
- package/dist/token/types.d.ts +10 -10
- package/package.json +2 -3
- package/src/account/account.ts +11 -7
- package/src/assets/app/backend-data.ts +9 -2
- package/src/assets/app/components/accept-form.tsx +65 -51
- package/src/assets/app/components/client-name.tsx +24 -16
- package/src/assets/app/views/accept-view.tsx +7 -4
- package/src/assets/app/views/authorize-view.tsx +2 -1
- package/src/assets/assets-middleware.ts +14 -2
- package/src/client/client-manager.ts +78 -60
- package/src/client/client.ts +1 -4
- package/src/constants.ts +3 -0
- package/src/device/device-manager.ts +7 -1
- package/src/errors/invalid-authorization-details-error.ts +9 -4
- package/src/lib/http/request.ts +61 -15
- package/src/metadata/build-metadata.ts +9 -42
- package/src/oauth-hooks.ts +3 -13
- package/src/oauth-provider.ts +181 -159
- package/src/oauth-verifier.ts +1 -2
- package/src/output/build-authorize-data.ts +8 -0
- package/src/replay/replay-manager.ts +9 -0
- package/src/replay/replay-store.ts +1 -1
- package/src/request/request-info.ts +2 -0
- package/src/request/request-manager.ts +81 -107
- package/src/signer/signer.ts +0 -63
- package/src/token/token-manager.ts +8 -41
- package/dist/oidc/claims.d.ts +0 -16
- package/dist/oidc/claims.d.ts.map +0 -1
- package/dist/oidc/claims.js +0 -29
- package/dist/oidc/claims.js.map +0 -1
- package/dist/oidc/userinfo.d.ts +0 -7
- package/dist/oidc/userinfo.d.ts.map +0 -1
- package/dist/oidc/userinfo.js +0 -3
- package/dist/oidc/userinfo.js.map +0 -1
- package/dist/parameters/claims-requested.d.ts +0 -3
- package/dist/parameters/claims-requested.d.ts.map +0 -1
- package/dist/parameters/claims-requested.js +0 -77
- package/dist/parameters/claims-requested.js.map +0 -1
- package/dist/parameters/oidc-payload.d.ts +0 -31
- package/dist/parameters/oidc-payload.d.ts.map +0 -1
- package/dist/parameters/oidc-payload.js +0 -25
- package/dist/parameters/oidc-payload.js.map +0 -1
- package/src/assets/app/components/client-identifier.tsx +0 -31
- package/src/oidc/claims.ts +0 -35
- package/src/oidc/userinfo.ts +0 -11
- package/src/parameters/claims-requested.ts +0 -106
- package/src/parameters/oidc-payload.ts +0 -28
@@ -1,77 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.claimRequested = void 0;
|
4
|
-
const invalid_request_error_js_1 = require("../errors/invalid-request-error.js");
|
5
|
-
function claimRequested(parameters, entityType, claimName, value) {
|
6
|
-
if (claimAvailable(parameters, entityType, claimName, value)) {
|
7
|
-
return true;
|
8
|
-
}
|
9
|
-
const entityClaims = parameters.claims?.[entityType];
|
10
|
-
if (entityClaims?.[claimName]?.essential === true) {
|
11
|
-
// https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.5.5.1
|
12
|
-
//
|
13
|
-
// > By requesting Claims as Essential Claims, the RP indicates to the
|
14
|
-
// > End-User that releasing these Claims will ensure a smooth
|
15
|
-
// > authorization for the specific task requested by the End-User. Note
|
16
|
-
// > that even if the Claims are not available because the End-User did
|
17
|
-
// > not authorize their release or they are not present, the
|
18
|
-
// > Authorization Server MUST NOT generate an error when Claims are not
|
19
|
-
// > returned, whether they are Essential or Voluntary, unless otherwise
|
20
|
-
// > specified in the description of the specific claim.
|
21
|
-
switch (claimName) {
|
22
|
-
case 'acr':
|
23
|
-
// https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.5.5.1.1
|
24
|
-
//
|
25
|
-
// > If this is an Essential Claim and the requirement cannot be met,
|
26
|
-
// > then the Authorization Server MUST treat that outcome as a failed
|
27
|
-
// > authentication attempt.
|
28
|
-
throw new invalid_request_error_js_1.InvalidRequestError(`Unable to provide essential claim: ${claimName}`);
|
29
|
-
}
|
30
|
-
}
|
31
|
-
return false;
|
32
|
-
}
|
33
|
-
exports.claimRequested = claimRequested;
|
34
|
-
function claimAvailable(parameters, entityType, claimName, value) {
|
35
|
-
if (value === undefined)
|
36
|
-
return false;
|
37
|
-
if (parameters.claims) {
|
38
|
-
const entityClaims = parameters.claims[entityType];
|
39
|
-
if (entityClaims === undefined)
|
40
|
-
return false;
|
41
|
-
const claimConfig = entityClaims[claimName];
|
42
|
-
if (claimConfig === undefined)
|
43
|
-
return false;
|
44
|
-
if (claimConfig === null)
|
45
|
-
return true;
|
46
|
-
if (claimConfig.value !== undefined &&
|
47
|
-
!compareClaimValue(claimConfig.value, value)) {
|
48
|
-
return false;
|
49
|
-
}
|
50
|
-
if (claimConfig?.values !== undefined &&
|
51
|
-
!claimConfig.values.some((v) => compareClaimValue(v, value))) {
|
52
|
-
return false;
|
53
|
-
}
|
54
|
-
}
|
55
|
-
return true;
|
56
|
-
}
|
57
|
-
function compareClaimValue(expectedValue, value) {
|
58
|
-
const expectedType = typeof expectedValue;
|
59
|
-
const valueType = typeof value;
|
60
|
-
if (expectedType !== valueType)
|
61
|
-
return false;
|
62
|
-
switch (typeof expectedValue) {
|
63
|
-
case 'undefined':
|
64
|
-
case 'string':
|
65
|
-
case 'number':
|
66
|
-
case 'boolean':
|
67
|
-
return expectedValue === value;
|
68
|
-
case 'object':
|
69
|
-
if (expectedValue === null)
|
70
|
-
return value === null;
|
71
|
-
// @TODO (?): allow object comparison
|
72
|
-
// falls through
|
73
|
-
default:
|
74
|
-
throw new invalid_request_error_js_1.InvalidRequestError(`Unable to compare claim value of type ${expectedType}`);
|
75
|
-
}
|
76
|
-
}
|
77
|
-
//# sourceMappingURL=claims-requested.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"claims-requested.js","sourceRoot":"","sources":["../../src/parameters/claims-requested.ts"],"names":[],"mappings":";;;AAKA,iFAAwE;AAExE,SAAgB,cAAc,CAC5B,UAAgD,EAChD,UAA0B,EAC1B,SAA8B,EAC9B,KAAc;IAEd,IAAI,cAAc,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;QAC7D,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,CAAA;IACpD,IAAI,YAAY,EAAE,CAAC,SAAS,CAAC,EAAE,SAAS,KAAK,IAAI,EAAE,CAAC;QAClD,0EAA0E;QAC1E,EAAE;QACF,sEAAsE;QACtE,8DAA8D;QAC9D,wEAAwE;QACxE,uEAAuE;QACvE,6DAA6D;QAC7D,wEAAwE;QACxE,wEAAwE;QACxE,wDAAwD;QACxD,QAAQ,SAAS,EAAE,CAAC;YAClB,KAAK,KAAK;gBACR,4EAA4E;gBAC5E,EAAE;gBACF,qEAAqE;gBACrE,sEAAsE;gBACtE,4BAA4B;gBAC5B,MAAM,IAAI,8CAAmB,CAC3B,sCAAsC,SAAS,EAAE,CAClD,CAAA;QACL,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AApCD,wCAoCC;AAED,SAAS,cAAc,CACrB,UAAgD,EAChD,UAA0B,EAC1B,SAA8B,EAC9B,KAAc;IAEd,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IAErC,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;QAClD,IAAI,YAAY,KAAK,SAAS;YAAE,OAAO,KAAK,CAAA;QAE5C,MAAM,WAAW,GAAG,YAAY,CAAC,SAAS,CAAC,CAAA;QAC3C,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO,KAAK,CAAA;QAC3C,IAAI,WAAW,KAAK,IAAI;YAAE,OAAO,IAAI,CAAA;QAErC,IACE,WAAW,CAAC,KAAK,KAAK,SAAS;YAC/B,CAAC,iBAAiB,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,EAC5C,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;QAED,IACE,WAAW,EAAE,MAAM,KAAK,SAAS;YACjC,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAC5D,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAID,SAAS,iBAAiB,CACxB,aAA2B,EAC3B,KAAmB;IAEnB,MAAM,YAAY,GAAG,OAAO,aAAa,CAAA;IACzC,MAAM,SAAS,GAAG,OAAO,KAAK,CAAA;IAE9B,IAAI,YAAY,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IAE5C,QAAQ,OAAO,aAAa,EAAE,CAAC;QAC7B,KAAK,WAAW,CAAC;QACjB,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS;YACZ,OAAO,aAAa,KAAK,KAAK,CAAA;QAChC,KAAK,QAAQ;YACX,IAAI,aAAa,KAAK,IAAI;gBAAE,OAAO,KAAK,KAAK,IAAI,CAAA;QACnD,qCAAqC;QACrC,gBAAgB;QAChB;YACE,MAAM,IAAI,8CAAmB,CAC3B,yCAAyC,YAAY,EAAE,CACxD,CAAA;IACL,CAAC;AACH,CAAC"}
|
@@ -1,31 +0,0 @@
|
|
1
|
-
import { OAuthAuthenticationRequestParameters } from '@atproto/oauth-types';
|
2
|
-
import { Account } from '../account/account.js';
|
3
|
-
export declare function oidcPayload(params: OAuthAuthenticationRequestParameters, account: Account): Partial<{
|
4
|
-
name?: string | undefined;
|
5
|
-
email?: string | undefined;
|
6
|
-
email_verified?: boolean | undefined;
|
7
|
-
phone_number?: string | undefined;
|
8
|
-
phone_number_verified?: boolean | undefined;
|
9
|
-
address?: {
|
10
|
-
formatted?: string | undefined;
|
11
|
-
street_address?: string | undefined;
|
12
|
-
locality?: string | undefined;
|
13
|
-
region?: string | undefined;
|
14
|
-
postal_code?: string | undefined;
|
15
|
-
country?: string | undefined;
|
16
|
-
} | undefined;
|
17
|
-
profile?: string | undefined;
|
18
|
-
family_name?: string | undefined;
|
19
|
-
given_name?: string | undefined;
|
20
|
-
middle_name?: string | undefined;
|
21
|
-
nickname?: string | undefined;
|
22
|
-
preferred_username?: string | undefined;
|
23
|
-
gender?: string | undefined;
|
24
|
-
picture?: string | undefined;
|
25
|
-
website?: string | undefined;
|
26
|
-
birthdate?: string | undefined;
|
27
|
-
zoneinfo?: string | undefined;
|
28
|
-
locale?: string | undefined;
|
29
|
-
updated_at?: number | undefined;
|
30
|
-
}>;
|
31
|
-
//# sourceMappingURL=oidc-payload.d.ts.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"oidc-payload.d.ts","sourceRoot":"","sources":["../../src/parameters/oidc-payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oCAAoC,EAAE,MAAM,sBAAsB,CAAA;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAI/C,wBAAgB,WAAW,CACzB,MAAM,EAAE,oCAAoC,EAC5C,OAAO,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoBjB"}
|
@@ -1,25 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.oidcPayload = void 0;
|
4
|
-
const claims_js_1 = require("../oidc/claims.js");
|
5
|
-
const claims_requested_js_1 = require("./claims-requested.js");
|
6
|
-
function oidcPayload(params, account) {
|
7
|
-
const payload = {};
|
8
|
-
const scopes = params.scope ? params.scope?.split(' ') : undefined;
|
9
|
-
if (scopes) {
|
10
|
-
for (const [scope, claims] of Object.entries(claims_js_1.OIDC_SCOPE_CLAIMS)) {
|
11
|
-
const allowed = scopes.includes(scope);
|
12
|
-
for (const claim of claims) {
|
13
|
-
const value = allowed ? account[claim] : undefined;
|
14
|
-
// Should not throw as RequestManager should have already checked
|
15
|
-
// that all the essential claims are available.
|
16
|
-
if ((0, claims_requested_js_1.claimRequested)(params, 'id_token', claim, value)) {
|
17
|
-
payload[claim] = value; // All good as long as the account props match the claims
|
18
|
-
}
|
19
|
-
}
|
20
|
-
}
|
21
|
-
}
|
22
|
-
return payload;
|
23
|
-
}
|
24
|
-
exports.oidcPayload = oidcPayload;
|
25
|
-
//# sourceMappingURL=oidc-payload.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"oidc-payload.js","sourceRoot":"","sources":["../../src/parameters/oidc-payload.ts"],"names":[],"mappings":";;;AAEA,iDAA0E;AAC1E,+DAAsD;AAEtD,SAAgB,WAAW,CACzB,MAA4C,EAC5C,OAAgB;IAEhB,MAAM,OAAO,GAAwB,EAAE,CAAA;IAEvC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAClE,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,6BAAiB,CAAC,EAAE,CAAC;YAChE,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACtC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;gBAClD,iEAAiE;gBACjE,+CAA+C;gBAC/C,IAAI,IAAA,oCAAc,EAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;oBACrD,OAAO,CAAC,KAAK,CAAC,GAAG,KAAY,CAAA,CAAC,yDAAyD;gBACzF,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAtBD,kCAsBC"}
|
@@ -1,31 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
isOAuthClientIdDiscoverable,
|
3
|
-
isOAuthClientIdLoopback,
|
4
|
-
OAuthClientMetadata,
|
5
|
-
} from '@atproto/oauth-types'
|
6
|
-
import { HTMLAttributes } from 'react'
|
7
|
-
|
8
|
-
import { UrlViewer } from './url-viewer'
|
9
|
-
|
10
|
-
export type ClientIdentifierProps = {
|
11
|
-
clientId: string
|
12
|
-
clientMetadata: OAuthClientMetadata
|
13
|
-
as?: keyof JSX.IntrinsicElements
|
14
|
-
}
|
15
|
-
|
16
|
-
export function ClientIdentifier({
|
17
|
-
clientId,
|
18
|
-
clientMetadata,
|
19
|
-
as: As = 'span',
|
20
|
-
...attrs
|
21
|
-
}: ClientIdentifierProps & HTMLAttributes<Element>) {
|
22
|
-
if (isOAuthClientIdLoopback(clientId)) {
|
23
|
-
return <As {...attrs}>An application on your device</As>
|
24
|
-
}
|
25
|
-
|
26
|
-
if (isOAuthClientIdDiscoverable(clientId)) {
|
27
|
-
return <UrlViewer as={As} {...attrs} url={clientId} proto path />
|
28
|
-
}
|
29
|
-
|
30
|
-
return <As {...attrs}>{clientMetadata.client_name || clientId}</As>
|
31
|
-
}
|
package/src/oidc/claims.ts
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
import { JwtPayload } from '@atproto/jwk'
|
2
|
-
|
3
|
-
/**
|
4
|
-
* @see {@link https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims | OpenID Connect Core 1.0, 5.4. Requesting Claims using Scope Values}
|
5
|
-
*/
|
6
|
-
export const OIDC_SCOPE_CLAIMS = Object.freeze({
|
7
|
-
email: Object.freeze(['email', 'email_verified'] as const),
|
8
|
-
phone: Object.freeze(['phone_number', 'phone_number_verified'] as const),
|
9
|
-
address: Object.freeze(['address'] as const),
|
10
|
-
profile: Object.freeze([
|
11
|
-
'name',
|
12
|
-
'family_name',
|
13
|
-
'given_name',
|
14
|
-
'middle_name',
|
15
|
-
'nickname',
|
16
|
-
'preferred_username',
|
17
|
-
'gender',
|
18
|
-
'picture',
|
19
|
-
'profile',
|
20
|
-
'website',
|
21
|
-
'birthdate',
|
22
|
-
'zoneinfo',
|
23
|
-
'locale',
|
24
|
-
'updated_at',
|
25
|
-
] as const),
|
26
|
-
})
|
27
|
-
|
28
|
-
export const OIDC_STANDARD_CLAIMS = Object.freeze(
|
29
|
-
Object.values(OIDC_SCOPE_CLAIMS).flat(),
|
30
|
-
)
|
31
|
-
|
32
|
-
export type OIDCStandardClaim = (typeof OIDC_STANDARD_CLAIMS)[number]
|
33
|
-
export type OIDCStandardPayload = Partial<{
|
34
|
-
[K in OIDCStandardClaim]?: JwtPayload[K]
|
35
|
-
}>
|
package/src/oidc/userinfo.ts
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
import { OIDCStandardPayload } from './claims.js'
|
2
|
-
|
3
|
-
export type Userinfo = OIDCStandardPayload & {
|
4
|
-
// "The sub (subject) Claim MUST always be returned in the UserInfo Response."
|
5
|
-
sub: string
|
6
|
-
|
7
|
-
// client_id is not mandatory per spec, but we require it here for convenience
|
8
|
-
client_id: string
|
9
|
-
|
10
|
-
username?: string
|
11
|
-
}
|
@@ -1,106 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
OAuthAuthenticationRequestParameters,
|
3
|
-
OidcClaimsParameter,
|
4
|
-
OidcEntityType,
|
5
|
-
} from '@atproto/oauth-types'
|
6
|
-
import { InvalidRequestError } from '../errors/invalid-request-error.js'
|
7
|
-
|
8
|
-
export function claimRequested(
|
9
|
-
parameters: OAuthAuthenticationRequestParameters,
|
10
|
-
entityType: OidcEntityType,
|
11
|
-
claimName: OidcClaimsParameter,
|
12
|
-
value: unknown,
|
13
|
-
): boolean {
|
14
|
-
if (claimAvailable(parameters, entityType, claimName, value)) {
|
15
|
-
return true
|
16
|
-
}
|
17
|
-
|
18
|
-
const entityClaims = parameters.claims?.[entityType]
|
19
|
-
if (entityClaims?.[claimName]?.essential === true) {
|
20
|
-
// https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.5.5.1
|
21
|
-
//
|
22
|
-
// > By requesting Claims as Essential Claims, the RP indicates to the
|
23
|
-
// > End-User that releasing these Claims will ensure a smooth
|
24
|
-
// > authorization for the specific task requested by the End-User. Note
|
25
|
-
// > that even if the Claims are not available because the End-User did
|
26
|
-
// > not authorize their release or they are not present, the
|
27
|
-
// > Authorization Server MUST NOT generate an error when Claims are not
|
28
|
-
// > returned, whether they are Essential or Voluntary, unless otherwise
|
29
|
-
// > specified in the description of the specific claim.
|
30
|
-
switch (claimName) {
|
31
|
-
case 'acr':
|
32
|
-
// https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.5.5.1.1
|
33
|
-
//
|
34
|
-
// > If this is an Essential Claim and the requirement cannot be met,
|
35
|
-
// > then the Authorization Server MUST treat that outcome as a failed
|
36
|
-
// > authentication attempt.
|
37
|
-
throw new InvalidRequestError(
|
38
|
-
`Unable to provide essential claim: ${claimName}`,
|
39
|
-
)
|
40
|
-
}
|
41
|
-
}
|
42
|
-
|
43
|
-
return false
|
44
|
-
}
|
45
|
-
|
46
|
-
function claimAvailable(
|
47
|
-
parameters: OAuthAuthenticationRequestParameters,
|
48
|
-
entityType: OidcEntityType,
|
49
|
-
claimName: OidcClaimsParameter,
|
50
|
-
value: unknown,
|
51
|
-
): boolean {
|
52
|
-
if (value === undefined) return false
|
53
|
-
|
54
|
-
if (parameters.claims) {
|
55
|
-
const entityClaims = parameters.claims[entityType]
|
56
|
-
if (entityClaims === undefined) return false
|
57
|
-
|
58
|
-
const claimConfig = entityClaims[claimName]
|
59
|
-
if (claimConfig === undefined) return false
|
60
|
-
if (claimConfig === null) return true
|
61
|
-
|
62
|
-
if (
|
63
|
-
claimConfig.value !== undefined &&
|
64
|
-
!compareClaimValue(claimConfig.value, value)
|
65
|
-
) {
|
66
|
-
return false
|
67
|
-
}
|
68
|
-
|
69
|
-
if (
|
70
|
-
claimConfig?.values !== undefined &&
|
71
|
-
!claimConfig.values.some((v) => compareClaimValue(v, value))
|
72
|
-
) {
|
73
|
-
return false
|
74
|
-
}
|
75
|
-
}
|
76
|
-
|
77
|
-
return true
|
78
|
-
}
|
79
|
-
|
80
|
-
type DefinedValue = NonNullable<unknown> | null
|
81
|
-
|
82
|
-
function compareClaimValue(
|
83
|
-
expectedValue: DefinedValue,
|
84
|
-
value: DefinedValue,
|
85
|
-
): boolean {
|
86
|
-
const expectedType = typeof expectedValue
|
87
|
-
const valueType = typeof value
|
88
|
-
|
89
|
-
if (expectedType !== valueType) return false
|
90
|
-
|
91
|
-
switch (typeof expectedValue) {
|
92
|
-
case 'undefined':
|
93
|
-
case 'string':
|
94
|
-
case 'number':
|
95
|
-
case 'boolean':
|
96
|
-
return expectedValue === value
|
97
|
-
case 'object':
|
98
|
-
if (expectedValue === null) return value === null
|
99
|
-
// @TODO (?): allow object comparison
|
100
|
-
// falls through
|
101
|
-
default:
|
102
|
-
throw new InvalidRequestError(
|
103
|
-
`Unable to compare claim value of type ${expectedType}`,
|
104
|
-
)
|
105
|
-
}
|
106
|
-
}
|
@@ -1,28 +0,0 @@
|
|
1
|
-
import { OAuthAuthenticationRequestParameters } from '@atproto/oauth-types'
|
2
|
-
import { Account } from '../account/account.js'
|
3
|
-
import { OIDCStandardPayload, OIDC_SCOPE_CLAIMS } from '../oidc/claims.js'
|
4
|
-
import { claimRequested } from './claims-requested.js'
|
5
|
-
|
6
|
-
export function oidcPayload(
|
7
|
-
params: OAuthAuthenticationRequestParameters,
|
8
|
-
account: Account,
|
9
|
-
) {
|
10
|
-
const payload: OIDCStandardPayload = {}
|
11
|
-
|
12
|
-
const scopes = params.scope ? params.scope?.split(' ') : undefined
|
13
|
-
if (scopes) {
|
14
|
-
for (const [scope, claims] of Object.entries(OIDC_SCOPE_CLAIMS)) {
|
15
|
-
const allowed = scopes.includes(scope)
|
16
|
-
for (const claim of claims) {
|
17
|
-
const value = allowed ? account[claim] : undefined
|
18
|
-
// Should not throw as RequestManager should have already checked
|
19
|
-
// that all the essential claims are available.
|
20
|
-
if (claimRequested(params, 'id_token', claim, value)) {
|
21
|
-
payload[claim] = value as any // All good as long as the account props match the claims
|
22
|
-
}
|
23
|
-
}
|
24
|
-
}
|
25
|
-
}
|
26
|
-
|
27
|
-
return payload
|
28
|
-
}
|