@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.
Files changed (120) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/account/account.d.ts +6 -2
  3. package/dist/account/account.d.ts.map +1 -1
  4. package/dist/assets/app/bundle-manifest.json +3 -3
  5. package/dist/assets/app/main.css +1 -1
  6. package/dist/assets/app/main.js +1 -1
  7. package/dist/assets/app/main.js.map +1 -1
  8. package/dist/assets/assets-middleware.d.ts +2 -1
  9. package/dist/assets/assets-middleware.d.ts.map +1 -1
  10. package/dist/assets/assets-middleware.js +7 -0
  11. package/dist/assets/assets-middleware.js.map +1 -1
  12. package/dist/client/client-manager.d.ts +4 -3
  13. package/dist/client/client-manager.d.ts.map +1 -1
  14. package/dist/client/client-manager.js +60 -37
  15. package/dist/client/client-manager.js.map +1 -1
  16. package/dist/client/client.d.ts.map +1 -1
  17. package/dist/client/client.js +1 -3
  18. package/dist/client/client.js.map +1 -1
  19. package/dist/constants.d.ts +2 -0
  20. package/dist/constants.d.ts.map +1 -1
  21. package/dist/constants.js +3 -1
  22. package/dist/constants.js.map +1 -1
  23. package/dist/device/device-manager.d.ts +1 -1
  24. package/dist/device/device-manager.d.ts.map +1 -1
  25. package/dist/device/device-manager.js +2 -2
  26. package/dist/device/device-manager.js.map +1 -1
  27. package/dist/errors/invalid-authorization-details-error.d.ts +4 -3
  28. package/dist/errors/invalid-authorization-details-error.d.ts.map +1 -1
  29. package/dist/errors/invalid-authorization-details-error.js +4 -4
  30. package/dist/errors/invalid-authorization-details-error.js.map +1 -1
  31. package/dist/lib/http/request.d.ts +3 -0
  32. package/dist/lib/http/request.d.ts.map +1 -1
  33. package/dist/lib/http/request.js +24 -12
  34. package/dist/lib/http/request.js.map +1 -1
  35. package/dist/metadata/build-metadata.d.ts +0 -1
  36. package/dist/metadata/build-metadata.d.ts.map +1 -1
  37. package/dist/metadata/build-metadata.js +9 -35
  38. package/dist/metadata/build-metadata.js.map +1 -1
  39. package/dist/oauth-hooks.d.ts +3 -10
  40. package/dist/oauth-hooks.d.ts.map +1 -1
  41. package/dist/oauth-provider.d.ts +8 -13
  42. package/dist/oauth-provider.d.ts.map +1 -1
  43. package/dist/oauth-provider.js +169 -109
  44. package/dist/oauth-provider.js.map +1 -1
  45. package/dist/oauth-verifier.d.ts +1 -2
  46. package/dist/oauth-verifier.d.ts.map +1 -1
  47. package/dist/oauth-verifier.js.map +1 -1
  48. package/dist/output/build-authorize-data.d.ts +6 -0
  49. package/dist/output/build-authorize-data.d.ts.map +1 -1
  50. package/dist/output/build-authorize-data.js +1 -0
  51. package/dist/output/build-authorize-data.js.map +1 -1
  52. package/dist/replay/replay-manager.d.ts +1 -0
  53. package/dist/replay/replay-manager.d.ts.map +1 -1
  54. package/dist/replay/replay-manager.js +3 -0
  55. package/dist/replay/replay-manager.js.map +1 -1
  56. package/dist/replay/replay-store.d.ts +1 -1
  57. package/dist/request/request-info.d.ts +2 -0
  58. package/dist/request/request-info.d.ts.map +1 -1
  59. package/dist/request/request-manager.d.ts +3 -9
  60. package/dist/request/request-manager.d.ts.map +1 -1
  61. package/dist/request/request-manager.js +52 -77
  62. package/dist/request/request-manager.js.map +1 -1
  63. package/dist/request/types.d.ts +10 -10
  64. package/dist/signer/signed-token-payload.d.ts +85 -85
  65. package/dist/signer/signer.d.ts +23 -30
  66. package/dist/signer/signer.d.ts.map +1 -1
  67. package/dist/signer/signer.js +0 -40
  68. package/dist/signer/signer.js.map +1 -1
  69. package/dist/token/token-claims.d.ts +81 -81
  70. package/dist/token/token-manager.d.ts +1 -2
  71. package/dist/token/token-manager.d.ts.map +1 -1
  72. package/dist/token/token-manager.js +10 -37
  73. package/dist/token/token-manager.js.map +1 -1
  74. package/dist/token/types.d.ts +10 -10
  75. package/package.json +2 -3
  76. package/src/account/account.ts +11 -7
  77. package/src/assets/app/backend-data.ts +9 -2
  78. package/src/assets/app/components/accept-form.tsx +65 -51
  79. package/src/assets/app/components/client-name.tsx +24 -16
  80. package/src/assets/app/views/accept-view.tsx +7 -4
  81. package/src/assets/app/views/authorize-view.tsx +2 -1
  82. package/src/assets/assets-middleware.ts +14 -2
  83. package/src/client/client-manager.ts +78 -60
  84. package/src/client/client.ts +1 -4
  85. package/src/constants.ts +3 -0
  86. package/src/device/device-manager.ts +7 -1
  87. package/src/errors/invalid-authorization-details-error.ts +9 -4
  88. package/src/lib/http/request.ts +61 -15
  89. package/src/metadata/build-metadata.ts +9 -42
  90. package/src/oauth-hooks.ts +3 -13
  91. package/src/oauth-provider.ts +181 -159
  92. package/src/oauth-verifier.ts +1 -2
  93. package/src/output/build-authorize-data.ts +8 -0
  94. package/src/replay/replay-manager.ts +9 -0
  95. package/src/replay/replay-store.ts +1 -1
  96. package/src/request/request-info.ts +2 -0
  97. package/src/request/request-manager.ts +81 -107
  98. package/src/signer/signer.ts +0 -63
  99. package/src/token/token-manager.ts +8 -41
  100. package/dist/oidc/claims.d.ts +0 -16
  101. package/dist/oidc/claims.d.ts.map +0 -1
  102. package/dist/oidc/claims.js +0 -29
  103. package/dist/oidc/claims.js.map +0 -1
  104. package/dist/oidc/userinfo.d.ts +0 -7
  105. package/dist/oidc/userinfo.d.ts.map +0 -1
  106. package/dist/oidc/userinfo.js +0 -3
  107. package/dist/oidc/userinfo.js.map +0 -1
  108. package/dist/parameters/claims-requested.d.ts +0 -3
  109. package/dist/parameters/claims-requested.d.ts.map +0 -1
  110. package/dist/parameters/claims-requested.js +0 -77
  111. package/dist/parameters/claims-requested.js.map +0 -1
  112. package/dist/parameters/oidc-payload.d.ts +0 -31
  113. package/dist/parameters/oidc-payload.d.ts.map +0 -1
  114. package/dist/parameters/oidc-payload.js +0 -25
  115. package/dist/parameters/oidc-payload.js.map +0 -1
  116. package/src/assets/app/components/client-identifier.tsx +0 -31
  117. package/src/oidc/claims.ts +0 -35
  118. package/src/oidc/userinfo.ts +0 -11
  119. package/src/parameters/claims-requested.ts +0 -106
  120. 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
- }
@@ -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
- }>
@@ -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
- }