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