@atproto/oauth-types 0.1.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 (146) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE.txt +7 -0
  3. package/README.md +3 -0
  4. package/dist/access-token.d.ts +4 -0
  5. package/dist/access-token.d.ts.map +1 -0
  6. package/dist/access-token.js +6 -0
  7. package/dist/access-token.js.map +1 -0
  8. package/dist/atproto-loopback-client-metadata.d.ts +3 -0
  9. package/dist/atproto-loopback-client-metadata.d.ts.map +1 -0
  10. package/dist/atproto-loopback-client-metadata.js +26 -0
  11. package/dist/atproto-loopback-client-metadata.js.map +1 -0
  12. package/dist/constants.d.ts +3 -0
  13. package/dist/constants.d.ts.map +1 -0
  14. package/dist/constants.js +11 -0
  15. package/dist/constants.js.map +1 -0
  16. package/dist/index.d.ts +27 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +43 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/oauth-authentication-request-parameters.d.ts +128 -0
  21. package/dist/oauth-authentication-request-parameters.d.ts.map +1 -0
  22. package/dist/oauth-authentication-request-parameters.js +76 -0
  23. package/dist/oauth-authentication-request-parameters.js.map +1 -0
  24. package/dist/oauth-authorization-details.d.ts +54 -0
  25. package/dist/oauth-authorization-details.d.ts.map +1 -0
  26. package/dist/oauth-authorization-details.js +20 -0
  27. package/dist/oauth-authorization-details.js.map +1 -0
  28. package/dist/oauth-authorization-server-metadata.d.ts +428 -0
  29. package/dist/oauth-authorization-server-metadata.d.ts.map +1 -0
  30. package/dist/oauth-authorization-server-metadata.js +88 -0
  31. package/dist/oauth-authorization-server-metadata.js.map +1 -0
  32. package/dist/oauth-client-credentials.d.ts +66 -0
  33. package/dist/oauth-client-credentials.d.ts.map +1 -0
  34. package/dist/oauth-client-credentials.js +30 -0
  35. package/dist/oauth-client-credentials.js.map +1 -0
  36. package/dist/oauth-client-id-discoverable.d.ts +8 -0
  37. package/dist/oauth-client-id-discoverable.d.ts.map +1 -0
  38. package/dist/oauth-client-id-discoverable.js +48 -0
  39. package/dist/oauth-client-id-discoverable.js.map +1 -0
  40. package/dist/oauth-client-id-loopback.d.ts +5 -0
  41. package/dist/oauth-client-id-loopback.d.ts.map +1 -0
  42. package/dist/oauth-client-id-loopback.js +44 -0
  43. package/dist/oauth-client-id-loopback.js.map +1 -0
  44. package/dist/oauth-client-id-url.d.ts +3 -0
  45. package/dist/oauth-client-id-url.d.ts.map +1 -0
  46. package/dist/oauth-client-id-url.js +21 -0
  47. package/dist/oauth-client-id-url.js.map +1 -0
  48. package/dist/oauth-client-id.d.ts +4 -0
  49. package/dist/oauth-client-id.d.ts.map +1 -0
  50. package/dist/oauth-client-id.js +6 -0
  51. package/dist/oauth-client-id.js.map +1 -0
  52. package/dist/oauth-client-identification.d.ts +31 -0
  53. package/dist/oauth-client-identification.d.ts.map +1 -0
  54. package/dist/oauth-client-identification.js +12 -0
  55. package/dist/oauth-client-identification.js.map +1 -0
  56. package/dist/oauth-client-metadata.d.ts +1576 -0
  57. package/dist/oauth-client-metadata.d.ts.map +1 -0
  58. package/dist/oauth-client-metadata.js +70 -0
  59. package/dist/oauth-client-metadata.js.map +1 -0
  60. package/dist/oauth-endpoint-auth-method.d.ts +4 -0
  61. package/dist/oauth-endpoint-auth-method.d.ts.map +1 -0
  62. package/dist/oauth-endpoint-auth-method.js +14 -0
  63. package/dist/oauth-endpoint-auth-method.js.map +1 -0
  64. package/dist/oauth-endpoint-name.d.ts +2 -0
  65. package/dist/oauth-endpoint-name.d.ts.map +1 -0
  66. package/dist/oauth-endpoint-name.js +3 -0
  67. package/dist/oauth-endpoint-name.js.map +1 -0
  68. package/dist/oauth-grant-type.d.ts +4 -0
  69. package/dist/oauth-grant-type.d.ts.map +1 -0
  70. package/dist/oauth-grant-type.js +14 -0
  71. package/dist/oauth-grant-type.js.map +1 -0
  72. package/dist/oauth-issuer-identifier.d.ts +3 -0
  73. package/dist/oauth-issuer-identifier.d.ts.map +1 -0
  74. package/dist/oauth-issuer-identifier.js +59 -0
  75. package/dist/oauth-issuer-identifier.js.map +1 -0
  76. package/dist/oauth-par-response.d.ts +10 -0
  77. package/dist/oauth-par-response.d.ts.map +1 -0
  78. package/dist/oauth-par-response.js +8 -0
  79. package/dist/oauth-par-response.js.map +1 -0
  80. package/dist/oauth-protected-resource-metadata.d.ts +90 -0
  81. package/dist/oauth-protected-resource-metadata.d.ts.map +1 -0
  82. package/dist/oauth-protected-resource-metadata.js +75 -0
  83. package/dist/oauth-protected-resource-metadata.js.map +1 -0
  84. package/dist/oauth-response-mode.d.ts +4 -0
  85. package/dist/oauth-response-mode.d.ts.map +1 -0
  86. package/dist/oauth-response-mode.js +10 -0
  87. package/dist/oauth-response-mode.js.map +1 -0
  88. package/dist/oauth-response-type.d.ts +4 -0
  89. package/dist/oauth-response-type.d.ts.map +1 -0
  90. package/dist/oauth-response-type.js +17 -0
  91. package/dist/oauth-response-type.js.map +1 -0
  92. package/dist/oauth-token-response.d.ts +103 -0
  93. package/dist/oauth-token-response.d.ts.map +1 -0
  94. package/dist/oauth-token-response.js +26 -0
  95. package/dist/oauth-token-response.js.map +1 -0
  96. package/dist/oauth-token-type.d.ts +4 -0
  97. package/dist/oauth-token-type.d.ts.map +1 -0
  98. package/dist/oauth-token-type.js +16 -0
  99. package/dist/oauth-token-type.js.map +1 -0
  100. package/dist/oidc-claims-parameter.d.ts +4 -0
  101. package/dist/oidc-claims-parameter.d.ts.map +1 -0
  102. package/dist/oidc-claims-parameter.js +36 -0
  103. package/dist/oidc-claims-parameter.js.map +1 -0
  104. package/dist/oidc-claims-properties.d.ts +16 -0
  105. package/dist/oidc-claims-properties.d.ts.map +1 -0
  106. package/dist/oidc-claims-properties.js +11 -0
  107. package/dist/oidc-claims-properties.js.map +1 -0
  108. package/dist/oidc-entity-type.d.ts +4 -0
  109. package/dist/oidc-entity-type.d.ts.map +1 -0
  110. package/dist/oidc-entity-type.js +6 -0
  111. package/dist/oidc-entity-type.js.map +1 -0
  112. package/dist/util.d.ts +5 -0
  113. package/dist/util.d.ts.map +1 -0
  114. package/dist/util.js +23 -0
  115. package/dist/util.js.map +1 -0
  116. package/package.json +37 -0
  117. package/src/access-token.ts +4 -0
  118. package/src/atproto-loopback-client-metadata.ts +30 -0
  119. package/src/constants.ts +9 -0
  120. package/src/index.ts +27 -0
  121. package/src/oauth-authentication-request-parameters.ts +104 -0
  122. package/src/oauth-authorization-details.ts +28 -0
  123. package/src/oauth-authorization-server-metadata.ts +106 -0
  124. package/src/oauth-client-credentials.ts +34 -0
  125. package/src/oauth-client-id-discoverable.ts +66 -0
  126. package/src/oauth-client-id-loopback.ts +58 -0
  127. package/src/oauth-client-id-url.ts +25 -0
  128. package/src/oauth-client-id.ts +4 -0
  129. package/src/oauth-client-identification.ts +14 -0
  130. package/src/oauth-client-metadata.ts +75 -0
  131. package/src/oauth-endpoint-auth-method.ts +13 -0
  132. package/src/oauth-endpoint-name.ts +5 -0
  133. package/src/oauth-grant-type.ts +13 -0
  134. package/src/oauth-issuer-identifier.ts +61 -0
  135. package/src/oauth-par-response.ts +7 -0
  136. package/src/oauth-protected-resource-metadata.ts +85 -0
  137. package/src/oauth-response-mode.ts +9 -0
  138. package/src/oauth-response-type.ts +17 -0
  139. package/src/oauth-token-response.ts +29 -0
  140. package/src/oauth-token-type.ts +15 -0
  141. package/src/oidc-claims-parameter.ts +40 -0
  142. package/src/oidc-claims-properties.ts +11 -0
  143. package/src/oidc-entity-type.ts +5 -0
  144. package/src/util.ts +20 -0
  145. package/tsconfig.build.json +8 -0
  146. package/tsconfig.json +4 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-token-response.js","sourceRoot":"","sources":["../src/oauth-token-response.ts"],"names":[],"mappings":";;;AAAA,sCAA8C;AAC9C,6BAAuB;AAEvB,qFAAkF;AAClF,+DAA4D;AAE5D;;GAEG;AACU,QAAA,wBAAwB,GAAG,OAAC;KACtC,MAAM,CAAC;IACN,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE;IACxB,UAAU,EAAE,0CAAoB;IAChC,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACnC,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,QAAQ,EAAE,qBAAe,CAAC,QAAQ,EAAE;IACpC,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,qBAAqB,EAAE,gEAA+B,CAAC,QAAQ,EAAE;CAClE,CAAC;IACF,0DAA0D;IAC1D,qEAAqE;KACpE,WAAW,EAAE,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { z } from 'zod';
2
+ export declare const oauthTokenTypeSchema: z.ZodUnion<[z.ZodEffects<z.ZodString, "DPoP", string>, z.ZodEffects<z.ZodString, "Bearer", string>]>;
3
+ export type OAuthTokenType = z.infer<typeof oauthTokenTypeSchema>;
4
+ //# sourceMappingURL=oauth-token-type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-token-type.d.ts","sourceRoot":"","sources":["../src/oauth-token-type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,oBAAoB,sGAS/B,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.oauthTokenTypeSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ // Case insensitive input, normalized output
6
+ exports.oauthTokenTypeSchema = zod_1.z.union([
7
+ zod_1.z
8
+ .string()
9
+ .regex(/^DPoP$/i)
10
+ .transform(() => 'DPoP'),
11
+ zod_1.z
12
+ .string()
13
+ .regex(/^Bearer$/i)
14
+ .transform(() => 'Bearer'),
15
+ ]);
16
+ //# sourceMappingURL=oauth-token-type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-token-type.js","sourceRoot":"","sources":["../src/oauth-token-type.ts"],"names":[],"mappings":";;;AAAA,6BAAuB;AAEvB,4CAA4C;AAC/B,QAAA,oBAAoB,GAAG,OAAC,CAAC,KAAK,CAAC;IAC1C,OAAC;SACE,MAAM,EAAE;SACR,KAAK,CAAC,SAAS,CAAC;SAChB,SAAS,CAAC,GAAG,EAAE,CAAC,MAAe,CAAC;IACnC,OAAC;SACE,MAAM,EAAE;SACR,KAAK,CAAC,WAAW,CAAC;SAClB,SAAS,CAAC,GAAG,EAAE,CAAC,QAAiB,CAAC;CACtC,CAAC,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { z } from 'zod';
2
+ export declare const oidcClaimsParameterSchema: z.ZodEnum<["auth_time", "nonce", "acr", "name", "family_name", "given_name", "middle_name", "nickname", "preferred_username", "gender", "picture", "profile", "website", "birthdate", "zoneinfo", "locale", "updated_at", "email", "email_verified", "phone_number", "phone_number_verified", "address"]>;
3
+ export type OidcClaimsParameter = z.infer<typeof oidcClaimsParameterSchema>;
4
+ //# sourceMappingURL=oidc-claims-parameter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-claims-parameter.d.ts","sourceRoot":"","sources":["../src/oidc-claims-parameter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,yBAAyB,2SAmCpC,CAAA;AAEF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.oidcClaimsParameterSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ exports.oidcClaimsParameterSchema = zod_1.z.enum([
6
+ // https://openid.net/specs/openid-provider-authentication-policy-extension-1_0.html#rfc.section.5.2
7
+ // if client metadata "require_auth_time" is true, this *must* be provided
8
+ 'auth_time',
9
+ // OIDC
10
+ 'nonce',
11
+ 'acr',
12
+ // OpenID: "profile" scope
13
+ 'name',
14
+ 'family_name',
15
+ 'given_name',
16
+ 'middle_name',
17
+ 'nickname',
18
+ 'preferred_username',
19
+ 'gender',
20
+ 'picture',
21
+ 'profile',
22
+ 'website',
23
+ 'birthdate',
24
+ 'zoneinfo',
25
+ 'locale',
26
+ 'updated_at',
27
+ // OpenID: "email" scope
28
+ 'email',
29
+ 'email_verified',
30
+ // OpenID: "phone" scope
31
+ 'phone_number',
32
+ 'phone_number_verified',
33
+ // OpenID: "address" scope
34
+ 'address',
35
+ ]);
36
+ //# sourceMappingURL=oidc-claims-parameter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-claims-parameter.js","sourceRoot":"","sources":["../src/oidc-claims-parameter.ts"],"names":[],"mappings":";;;AAAA,6BAAuB;AAEV,QAAA,yBAAyB,GAAG,OAAC,CAAC,IAAI,CAAC;IAC9C,oGAAoG;IACpG,0EAA0E;IAC1E,WAAW;IAEX,OAAO;IACP,OAAO;IACP,KAAK;IAEL,0BAA0B;IAC1B,MAAM;IACN,aAAa;IACb,YAAY;IACZ,aAAa;IACb,UAAU;IACV,oBAAoB;IACpB,QAAQ;IACR,SAAS;IACT,SAAS;IACT,SAAS;IACT,WAAW;IACX,UAAU;IACV,QAAQ;IACR,YAAY;IAEZ,wBAAwB;IACxB,OAAO;IACP,gBAAgB;IAEhB,wBAAwB;IACxB,cAAc;IACd,uBAAuB;IAEvB,0BAA0B;IAC1B,SAAS;CACV,CAAC,CAAA"}
@@ -0,0 +1,16 @@
1
+ import { z } from 'zod';
2
+ export declare const oidcClaimsPropertiesSchema: z.ZodObject<{
3
+ essential: z.ZodOptional<z.ZodBoolean>;
4
+ value: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
5
+ values: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>, "many">>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ values?: (string | number | boolean)[] | undefined;
8
+ value?: string | number | boolean | undefined;
9
+ essential?: boolean | undefined;
10
+ }, {
11
+ values?: (string | number | boolean)[] | undefined;
12
+ value?: string | number | boolean | undefined;
13
+ essential?: boolean | undefined;
14
+ }>;
15
+ export type OidcClaimsProperties = z.infer<typeof oidcClaimsPropertiesSchema>;
16
+ //# sourceMappingURL=oidc-claims-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-claims-properties.d.ts","sourceRoot":"","sources":["../src/oidc-claims-properties.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,0BAA0B;;;;;;;;;;;;EAIrC,CAAA;AAEF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAA"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.oidcClaimsPropertiesSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const oidcClaimsValueSchema = zod_1.z.union([zod_1.z.string(), zod_1.z.number(), zod_1.z.boolean()]);
6
+ exports.oidcClaimsPropertiesSchema = zod_1.z.object({
7
+ essential: zod_1.z.boolean().optional(),
8
+ value: oidcClaimsValueSchema.optional(),
9
+ values: zod_1.z.array(oidcClaimsValueSchema).optional(),
10
+ });
11
+ //# sourceMappingURL=oidc-claims-properties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-claims-properties.js","sourceRoot":"","sources":["../src/oidc-claims-properties.ts"],"names":[],"mappings":";;;AAAA,6BAAuB;AAEvB,MAAM,qBAAqB,GAAG,OAAC,CAAC,KAAK,CAAC,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;AAE/D,QAAA,0BAA0B,GAAG,OAAC,CAAC,MAAM,CAAC;IACjD,SAAS,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACjC,KAAK,EAAE,qBAAqB,CAAC,QAAQ,EAAE;IACvC,MAAM,EAAE,OAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,QAAQ,EAAE;CAClD,CAAC,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { z } from 'zod';
2
+ export declare const oidcEntityTypeSchema: z.ZodEnum<["userinfo", "id_token"]>;
3
+ export type OidcEntityType = z.infer<typeof oidcEntityTypeSchema>;
4
+ //# sourceMappingURL=oidc-entity-type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-entity-type.d.ts","sourceRoot":"","sources":["../src/oidc-entity-type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,oBAAoB,qCAAmC,CAAA;AAEpE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.oidcEntityTypeSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ exports.oidcEntityTypeSchema = zod_1.z.enum(['userinfo', 'id_token']);
6
+ //# sourceMappingURL=oidc-entity-type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-entity-type.js","sourceRoot":"","sources":["../src/oidc-entity-type.ts"],"names":[],"mappings":";;;AAAA,6BAAuB;AAEV,QAAA,oBAAoB,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAA"}
package/dist/util.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export declare function isIP(hostname: string): boolean;
2
+ export type LoopbackHost = 'localhost' | '127.0.0.1' | '[::1]';
3
+ export declare function isLoopbackHost(host: unknown): host is LoopbackHost;
4
+ export declare function isLoopbackUrl(input: URL | string): boolean;
5
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,wBAAgB,IAAI,CAAC,QAAQ,EAAE,MAAM,WAQpC;AAED,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAA;AAE9D,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,YAAY,CAElE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,GAAG,OAAO,CAG1D"}
package/dist/util.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isLoopbackUrl = exports.isLoopbackHost = exports.isIP = void 0;
4
+ function isIP(hostname) {
5
+ // IPv4
6
+ if (hostname.match(/^\d+\.\d+\.\d+\.\d+$/))
7
+ return true;
8
+ // IPv6
9
+ if (hostname.startsWith('[') && hostname.endsWith(']'))
10
+ return true;
11
+ return false;
12
+ }
13
+ exports.isIP = isIP;
14
+ function isLoopbackHost(host) {
15
+ return host === 'localhost' || host === '127.0.0.1' || host === '[::1]';
16
+ }
17
+ exports.isLoopbackHost = isLoopbackHost;
18
+ function isLoopbackUrl(input) {
19
+ const url = typeof input === 'string' ? new URL(input) : input;
20
+ return isLoopbackHost(url.hostname);
21
+ }
22
+ exports.isLoopbackUrl = isLoopbackUrl;
23
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;;AAAA,SAAgB,IAAI,CAAC,QAAgB;IACnC,OAAO;IACP,IAAI,QAAQ,CAAC,KAAK,CAAC,sBAAsB,CAAC;QAAE,OAAO,IAAI,CAAA;IAEvD,OAAO;IACP,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IAEnE,OAAO,KAAK,CAAA;AACd,CAAC;AARD,oBAQC;AAID,SAAgB,cAAc,CAAC,IAAa;IAC1C,OAAO,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,OAAO,CAAA;AACzE,CAAC;AAFD,wCAEC;AAED,SAAgB,aAAa,CAAC,KAAmB;IAC/C,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IAC9D,OAAO,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;AACrC,CAAC;AAHD,sCAGC"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@atproto/oauth-types",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "description": "OAuth typing & validation library",
6
+ "keywords": [
7
+ "atproto",
8
+ "oauth",
9
+ "types",
10
+ "isomorphic"
11
+ ],
12
+ "homepage": "https://atproto.com",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/bluesky-social/atproto",
16
+ "directory": "packages/oauth/oauth-types"
17
+ },
18
+ "type": "commonjs",
19
+ "main": "dist/index.js",
20
+ "types": "dist/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "default": "./dist/index.js"
25
+ }
26
+ },
27
+ "dependencies": {
28
+ "zod": "^3.23.8",
29
+ "@atproto/jwk": "0.1.0"
30
+ },
31
+ "devDependencies": {
32
+ "typescript": "^5.3.3"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc --build tsconfig.build.json"
36
+ }
37
+ }
@@ -0,0 +1,4 @@
1
+ import { z } from 'zod'
2
+
3
+ export const accessTokenSchema = z.string().min(1)
4
+ export type AccessToken = z.infer<typeof accessTokenSchema>
@@ -0,0 +1,30 @@
1
+ import { isOAuthClientIdLoopback } from './oauth-client-id-loopback.js'
2
+ import { OAuthClientMetadataInput } from './oauth-client-metadata.js'
3
+ import { parseOAuthClientIdUrl } from './oauth-client-id-url.js'
4
+
5
+ export function atprotoLoopbackClientMetadata(
6
+ clientId: string,
7
+ ): OAuthClientMetadataInput {
8
+ if (!isOAuthClientIdLoopback(clientId)) {
9
+ throw new TypeError(`Invalid loopback client ID ${clientId}`)
10
+ }
11
+
12
+ const { origin, pathname, searchParams } = parseOAuthClientIdUrl(clientId)
13
+
14
+ return {
15
+ client_id: clientId,
16
+ client_name: 'Loopback client',
17
+ response_types: ['code id_token', 'code'],
18
+ grant_types: ['authorization_code', 'implicit', 'refresh_token'],
19
+ scope: 'openid profile offline_access',
20
+ redirect_uris: searchParams.has('redirect_uri')
21
+ ? (searchParams.getAll('redirect_uri') as [string, ...string[]])
22
+ : (['127.0.0.1', '[::1]'].map(
23
+ (ip) =>
24
+ Object.assign(new URL(pathname, origin), { hostname: ip }).href,
25
+ ) as [string, ...string[]]),
26
+ token_endpoint_auth_method: 'none',
27
+ application_type: 'native',
28
+ dpop_bound_access_tokens: true,
29
+ }
30
+ }
@@ -0,0 +1,9 @@
1
+ export const CLIENT_ASSERTION_TYPE_JWT_BEARER =
2
+ 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
3
+
4
+ export const OAUTH_AUTHENTICATED_ENDPOINT_NAMES = [
5
+ 'token',
6
+ 'revocation',
7
+ 'introspection',
8
+ 'pushed_authorization_request',
9
+ ] as const
package/src/index.ts ADDED
@@ -0,0 +1,27 @@
1
+ export * from './constants.js'
2
+ export * from './util.js'
3
+
4
+ export * from './access-token.js'
5
+ export * from './atproto-loopback-client-metadata.js'
6
+ export * from './oauth-client-id-discoverable.js'
7
+ export * from './oauth-client-id-loopback.js'
8
+ export * from './oauth-authentication-request-parameters.js'
9
+ export * from './oauth-authorization-details.js'
10
+ export * from './oauth-authorization-server-metadata.js'
11
+ export * from './oauth-client-credentials.js'
12
+ export * from './oauth-client-id.js'
13
+ export * from './oauth-client-identification.js'
14
+ export * from './oauth-client-metadata.js'
15
+ export * from './oauth-endpoint-auth-method.js'
16
+ export * from './oauth-endpoint-name.js'
17
+ export * from './oauth-grant-type.js'
18
+ export * from './oauth-issuer-identifier.js'
19
+ export * from './oauth-par-response.js'
20
+ export * from './oauth-protected-resource-metadata.js'
21
+ export * from './oauth-response-mode.js'
22
+ export * from './oauth-response-type.js'
23
+ export * from './oauth-token-response.js'
24
+ export * from './oauth-token-type.js'
25
+ export * from './oidc-claims-parameter.js'
26
+ export * from './oidc-claims-properties.js'
27
+ export * from './oidc-entity-type.js'
@@ -0,0 +1,104 @@
1
+ import { signedJwtSchema } from '@atproto/jwk'
2
+ import { z } from 'zod'
3
+
4
+ import { oauthAuthorizationDetailsSchema } from './oauth-authorization-details.js'
5
+ import { oauthClientIdSchema } from './oauth-client-id.js'
6
+ import { oidcClaimsParameterSchema } from './oidc-claims-parameter.js'
7
+ import { oidcClaimsPropertiesSchema } from './oidc-claims-properties.js'
8
+ import { oidcEntityTypeSchema } from './oidc-entity-type.js'
9
+
10
+ /**
11
+ * @see {@link https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest | OIDC}
12
+ */
13
+ export const oauthAuthenticationRequestParametersSchema = z.object({
14
+ client_id: oauthClientIdSchema,
15
+
16
+ state: z.string().optional(),
17
+ nonce: z.string().optional(),
18
+ dpop_jkt: z.string().optional(),
19
+
20
+ response_type: z.enum([
21
+ // OAuth2 (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-10#section-4.1.1)
22
+ 'code',
23
+ 'token',
24
+
25
+ // OIDC (https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html)
26
+ 'id_token',
27
+ 'none',
28
+ 'code token',
29
+ 'code id_token',
30
+ 'id_token token',
31
+ 'code id_token token',
32
+ ]),
33
+
34
+ // Default depend on response_type
35
+ response_mode: z.enum(['query', 'fragment', 'form_post']).optional(),
36
+
37
+ // PKCE
38
+ code_challenge: z.string().optional(),
39
+ code_challenge_method: z.enum(['S256', 'plain']).default('S256').optional(),
40
+
41
+ redirect_uri: z.string().url().optional(),
42
+
43
+ // email profile openid (other?)
44
+ scope: z
45
+ .string()
46
+ .regex(/^[a-zA-Z0-9_]+( [a-zA-Z0-9_]+)*$/)
47
+ .optional(),
48
+
49
+ // OIDC
50
+
51
+ // Specifies the allowable elapsed time in seconds since the last time the
52
+ // End-User was actively authenticated by the OP. If the elapsed time is
53
+ // greater than this value, the OP MUST attempt to actively re-authenticate
54
+ // the End-User. (The max_age request parameter corresponds to the OpenID 2.0
55
+ // PAPE [OpenID.PAPE] max_auth_age request parameter.) When max_age is used,
56
+ // the ID Token returned MUST include an auth_time Claim Value. Note that
57
+ // max_age=0 is equivalent to prompt=login.
58
+ max_age: z.number().int().min(0).optional(),
59
+
60
+ claims: z
61
+ .record(
62
+ oidcEntityTypeSchema,
63
+ z.record(
64
+ oidcClaimsParameterSchema,
65
+ z.union([z.literal(null), oidcClaimsPropertiesSchema]),
66
+ ),
67
+ )
68
+ .optional(),
69
+
70
+ // https://openid.net/specs/openid-connect-core-1_0.html#RegistrationParameter
71
+ // Not supported by this library (yet?)
72
+ // registration: clientMetadataSchema.optional(),
73
+
74
+ login_hint: z.string().min(1).optional(),
75
+
76
+ ui_locales: z
77
+ .string()
78
+ .regex(/^[a-z]{2}(-[A-Z]{2})?( [a-z]{2}(-[A-Z]{2})?)*$/) // fr-CA fr en
79
+ .optional(),
80
+
81
+ // Previous ID Token, should be provided when prompt=none is used
82
+ id_token_hint: signedJwtSchema.optional(),
83
+
84
+ // Type of UI the AS is displayed on
85
+ display: z.enum(['page', 'popup', 'touch']).optional(),
86
+
87
+ /**
88
+ * - "none" will only be allowed if the user already allowed the client on the same device
89
+ * - "login" will force the user to login again, unless he very recently logged in
90
+ * - "consent" will force the user to consent again
91
+ * - "select_account" will force the user to select an account
92
+ */
93
+ prompt: z.enum(['none', 'login', 'consent', 'select_account']).optional(),
94
+
95
+ // https://datatracker.ietf.org/doc/html/rfc9396
96
+ authorization_details: oauthAuthorizationDetailsSchema.optional(),
97
+ })
98
+
99
+ /**
100
+ * @see {oauthAuthenticationRequestParametersSchema}
101
+ */
102
+ export type OAuthAuthenticationRequestParameters = z.infer<
103
+ typeof oauthAuthenticationRequestParametersSchema
104
+ >
@@ -0,0 +1,28 @@
1
+ import { z } from 'zod'
2
+
3
+ /**
4
+ * @see {@link https://datatracker.ietf.org/doc/html/rfc9396#section-2 | RFC 9396, Section 2}
5
+ */
6
+ export const oauthAuthorizationDetailSchema = z.object({
7
+ type: z.string(),
8
+ locations: z.array(z.string().url()).optional(),
9
+ actions: z.array(z.string()).optional(),
10
+ datatypes: z.array(z.string()).optional(),
11
+ identifier: z.string().optional(),
12
+ privileges: z.array(z.string()).optional(),
13
+ })
14
+
15
+ export type OAuthAuthorizationDetail = z.infer<
16
+ typeof oauthAuthorizationDetailSchema
17
+ >
18
+
19
+ /**
20
+ * @see {@link https://datatracker.ietf.org/doc/html/rfc9396#section-2 | RFC 9396, Section 2}
21
+ */
22
+ export const oauthAuthorizationDetailsSchema = z.array(
23
+ oauthAuthorizationDetailSchema,
24
+ )
25
+
26
+ export type OAuthAuthorizationDetails = z.infer<
27
+ typeof oauthAuthorizationDetailsSchema
28
+ >
@@ -0,0 +1,106 @@
1
+ import { z } from 'zod'
2
+
3
+ import { oauthIssuerIdentifierSchema } from './oauth-issuer-identifier.js'
4
+
5
+ /**
6
+ * @see {@link https://datatracker.ietf.org/doc/html/rfc8414}
7
+ */
8
+ export const oauthAuthorizationServerMetadataSchema = z.object({
9
+ issuer: oauthIssuerIdentifierSchema,
10
+
11
+ claims_supported: z.array(z.string()).optional(),
12
+ claims_locales_supported: z.array(z.string()).optional(),
13
+ claims_parameter_supported: z.boolean().optional(),
14
+ request_parameter_supported: z.boolean().optional(),
15
+ request_uri_parameter_supported: z.boolean().optional(),
16
+ require_request_uri_registration: z.boolean().optional(),
17
+ scopes_supported: z.array(z.string()).optional(),
18
+ subject_types_supported: z.array(z.string()).optional(),
19
+ response_types_supported: z.array(z.string()).optional(),
20
+ response_modes_supported: z.array(z.string()).optional(),
21
+ grant_types_supported: z.array(z.string()).optional(),
22
+ code_challenge_methods_supported: z.array(z.string()).min(1).optional(),
23
+ ui_locales_supported: z.array(z.string()).optional(),
24
+ id_token_signing_alg_values_supported: z.array(z.string()).optional(),
25
+ display_values_supported: z.array(z.string()).optional(),
26
+ request_object_signing_alg_values_supported: z.array(z.string()).optional(),
27
+ authorization_response_iss_parameter_supported: z.boolean().optional(),
28
+ authorization_details_types_supported: z.array(z.string()).optional(),
29
+ request_object_encryption_alg_values_supported: z
30
+ .array(z.string())
31
+ .optional(),
32
+ request_object_encryption_enc_values_supported: z
33
+ .array(z.string())
34
+ .optional(),
35
+
36
+ jwks_uri: z.string().url().optional(),
37
+
38
+ authorization_endpoint: z.string().url(), // .optional(),
39
+
40
+ token_endpoint: z.string().url(), // .optional(),
41
+ token_endpoint_auth_methods_supported: z.array(z.string()).optional(),
42
+ token_endpoint_auth_signing_alg_values_supported: z
43
+ .array(z.string())
44
+ .optional(),
45
+
46
+ revocation_endpoint: z.string().url().optional(),
47
+ revocation_endpoint_auth_methods_supported: z.array(z.string()).optional(),
48
+ revocation_endpoint_auth_signing_alg_values_supported: z
49
+ .array(z.string())
50
+ .optional(),
51
+
52
+ introspection_endpoint: z.string().url().optional(),
53
+ introspection_endpoint_auth_methods_supported: z.array(z.string()).optional(),
54
+ introspection_endpoint_auth_signing_alg_values_supported: z
55
+ .array(z.string())
56
+ .optional(),
57
+
58
+ pushed_authorization_request_endpoint: z.string().url().optional(),
59
+ pushed_authorization_request_endpoint_auth_methods_supported: z
60
+ .array(z.string())
61
+ .optional(),
62
+ pushed_authorization_request_endpoint_auth_signing_alg_values_supported: z
63
+ .array(z.string())
64
+ .optional(),
65
+
66
+ require_pushed_authorization_requests: z.boolean().optional(),
67
+
68
+ userinfo_endpoint: z.string().url().optional(),
69
+ end_session_endpoint: z.string().url().optional(),
70
+ registration_endpoint: z.string().url().optional(),
71
+
72
+ // https://datatracker.ietf.org/doc/html/rfc9449#section-5.1
73
+ dpop_signing_alg_values_supported: z.array(z.string()).optional(),
74
+
75
+ // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-resource-metadata-05#section-4
76
+ protected_resources: z.array(z.string().url()).optional(),
77
+ })
78
+
79
+ export type OAuthAuthorizationServerMetadata = z.infer<
80
+ typeof oauthAuthorizationServerMetadataSchema
81
+ >
82
+
83
+ export const oauthAuthorizationServerMetadataValidator =
84
+ oauthAuthorizationServerMetadataSchema
85
+ .superRefine((data, ctx) => {
86
+ if (
87
+ data.require_pushed_authorization_requests &&
88
+ !data.pushed_authorization_request_endpoint
89
+ ) {
90
+ ctx.addIssue({
91
+ code: z.ZodIssueCode.custom,
92
+ message:
93
+ '"pushed_authorization_request_endpoint" required when "require_pushed_authorization_requests" is true',
94
+ })
95
+ }
96
+ })
97
+ .superRefine((data, ctx) => {
98
+ if (data.response_types_supported) {
99
+ if (!data.response_types_supported.includes('code')) {
100
+ ctx.addIssue({
101
+ code: z.ZodIssueCode.custom,
102
+ message: 'Response type "code" is required',
103
+ })
104
+ }
105
+ }
106
+ })
@@ -0,0 +1,34 @@
1
+ import { z } from 'zod'
2
+ import { signedJwtSchema } from '@atproto/jwk'
3
+
4
+ import { oauthClientIdSchema } from './oauth-client-id.js'
5
+ import { CLIENT_ASSERTION_TYPE_JWT_BEARER } from './constants.js'
6
+
7
+ export const oauthClientCredentialsJwtBearerSchema = z.object({
8
+ client_id: oauthClientIdSchema,
9
+ client_assertion_type: z.literal(CLIENT_ASSERTION_TYPE_JWT_BEARER),
10
+ /**
11
+ * - "sub" the subject MUST be the "client_id" of the OAuth client
12
+ * - "iat" is required and MUST be less than one minute
13
+ * - "aud" must containing a value that identifies the authorization server
14
+ * - The JWT MAY contain a "jti" (JWT ID) claim that provides a unique identifier for the token.
15
+ * - Note that the authorization server may reject JWTs with an "exp" claim value that is unreasonably far in the future.
16
+ *
17
+ * @see {@link https://datatracker.ietf.org/doc/html/draft-ietf-oauth-jwt-bearer-11#section-3}
18
+ */
19
+ client_assertion: signedJwtSchema,
20
+ })
21
+
22
+ export const oauthClientCredentialsSecretPostSchema = z.object({
23
+ client_id: oauthClientIdSchema,
24
+ client_secret: z.string(),
25
+ })
26
+
27
+ export const oauthClientCredentialsSchema = z.union([
28
+ oauthClientCredentialsJwtBearerSchema,
29
+ oauthClientCredentialsSecretPostSchema,
30
+ ])
31
+
32
+ export type OAuthClientCredentials = z.infer<
33
+ typeof oauthClientCredentialsSchema
34
+ >
@@ -0,0 +1,66 @@
1
+ import { parseOAuthClientIdUrl } from './oauth-client-id-url.js'
2
+ import { OAuthClientId } from './oauth-client-id.js'
3
+ import { isIP } from './util.js'
4
+
5
+ /**
6
+ * @see {@link https://drafts.aaronpk.com/draft-parecki-oauth-client-id-metadata-document/draft-parecki-oauth-client-id-metadata-document.html}
7
+ */
8
+ export type OAuthClientIdDiscoverable = OAuthClientId & `https://${string}`
9
+
10
+ export function isOAuthClientIdDiscoverable<C extends OAuthClientId>(
11
+ clientId: C,
12
+ ): clientId is C & OAuthClientIdDiscoverable {
13
+ try {
14
+ parseOAuthDiscoverableClientId(clientId)
15
+ return true
16
+ } catch {
17
+ return false
18
+ }
19
+ }
20
+
21
+ export function parseOAuthDiscoverableClientId(clientId: OAuthClientId): URL {
22
+ const url = parseOAuthClientIdUrl(clientId)
23
+
24
+ // Optimization: cheap checks first
25
+
26
+ if (url.hostname === 'localhost') {
27
+ throw new TypeError('ClientID must not be a loopback hostname')
28
+ }
29
+
30
+ if (url.protocol !== 'https:') {
31
+ throw new TypeError('ClientID must use the "https:" protocol')
32
+ }
33
+
34
+ if (url.hash) {
35
+ throw new TypeError('ClientID must not contain a fragment')
36
+ }
37
+
38
+ if (url.username || url.password) {
39
+ throw new TypeError('ClientID must not contain credentials')
40
+ }
41
+
42
+ if (url.pathname === '/') {
43
+ throw new TypeError(
44
+ 'ClientID must contain a path (e.g. "/client-metadata")',
45
+ )
46
+ }
47
+
48
+ if (url.pathname !== '/' && url.pathname.endsWith('/')) {
49
+ throw new TypeError('ClientID must not end with a trailing slash')
50
+ }
51
+
52
+ if (url.pathname.includes('//')) {
53
+ throw new TypeError(
54
+ `ClientID must not contain any double slashes in its path`,
55
+ )
56
+ }
57
+
58
+ // Note: Query string is allowed
59
+ // Note: no restriction on the port for non-loopback URIs
60
+
61
+ if (isIP(url.hostname)) {
62
+ throw new TypeError('ClientID must not be an IP address')
63
+ }
64
+
65
+ return url
66
+ }