@atproto/oauth-types 0.7.3 → 0.7.4

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 (59) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/util.d.ts +1 -1
  3. package/dist/util.d.ts.map +1 -1
  4. package/dist/util.js.map +1 -1
  5. package/package.json +11 -7
  6. package/src/atproto-loopback-client-id.ts +0 -78
  7. package/src/atproto-loopback-client-metadata.ts +0 -47
  8. package/src/atproto-loopback-client-redirect-uris.ts +0 -4
  9. package/src/atproto-oauth-scope.ts +0 -34
  10. package/src/atproto-oauth-token-response.ts +0 -16
  11. package/src/constants.ts +0 -2
  12. package/src/index.ts +0 -50
  13. package/src/oauth-access-token.ts +0 -4
  14. package/src/oauth-authorization-code-grant-token-request.ts +0 -19
  15. package/src/oauth-authorization-details.ts +0 -48
  16. package/src/oauth-authorization-request-jar.ts +0 -16
  17. package/src/oauth-authorization-request-par.ts +0 -12
  18. package/src/oauth-authorization-request-parameters.ts +0 -100
  19. package/src/oauth-authorization-request-query.ts +0 -21
  20. package/src/oauth-authorization-request-uri.ts +0 -10
  21. package/src/oauth-authorization-response-error.ts +0 -25
  22. package/src/oauth-authorization-server-metadata.ts +0 -120
  23. package/src/oauth-client-credentials-grant-token-request.ts +0 -9
  24. package/src/oauth-client-credentials.ts +0 -53
  25. package/src/oauth-client-id-discoverable.ts +0 -130
  26. package/src/oauth-client-id-loopback.ts +0 -164
  27. package/src/oauth-client-id.ts +0 -4
  28. package/src/oauth-client-metadata.ts +0 -80
  29. package/src/oauth-code-challenge-method.ts +0 -3
  30. package/src/oauth-endpoint-auth-method.ts +0 -13
  31. package/src/oauth-endpoint-name.ts +0 -8
  32. package/src/oauth-grant-type.ts +0 -13
  33. package/src/oauth-introspection-response.ts +0 -23
  34. package/src/oauth-issuer-identifier.ts +0 -47
  35. package/src/oauth-par-response.ts +0 -8
  36. package/src/oauth-password-grant-token-request.ts +0 -11
  37. package/src/oauth-prompt-mode.ts +0 -18
  38. package/src/oauth-protected-resource-metadata.ts +0 -94
  39. package/src/oauth-redirect-uri.ts +0 -73
  40. package/src/oauth-refresh-token-grant-token-request.ts +0 -11
  41. package/src/oauth-refresh-token.ts +0 -4
  42. package/src/oauth-request-uri.ts +0 -5
  43. package/src/oauth-response-mode.ts +0 -9
  44. package/src/oauth-response-type.ts +0 -17
  45. package/src/oauth-scope.ts +0 -21
  46. package/src/oauth-token-identification.ts +0 -12
  47. package/src/oauth-token-request.ts +0 -14
  48. package/src/oauth-token-response.ts +0 -29
  49. package/src/oauth-token-type.ts +0 -15
  50. package/src/oidc-authorization-error-response.ts +0 -29
  51. package/src/oidc-claims-parameter.ts +0 -40
  52. package/src/oidc-claims-properties.ts +0 -11
  53. package/src/oidc-entity-type.ts +0 -5
  54. package/src/oidc-userinfo.ts +0 -15
  55. package/src/uri.ts +0 -221
  56. package/src/util.ts +0 -170
  57. package/tsconfig.build.json +0 -8
  58. package/tsconfig.build.tsbuildinfo +0 -1
  59. package/tsconfig.json +0 -4
@@ -1,120 +0,0 @@
1
- import { z } from 'zod'
2
- import { oauthCodeChallengeMethodSchema } from './oauth-code-challenge-method.js'
3
- import { oauthIssuerIdentifierSchema } from './oauth-issuer-identifier.js'
4
- import { oauthPromptModeSchema } from './oauth-prompt-mode.js'
5
- import { webUriSchema } from './uri.js'
6
-
7
- /**
8
- * @see {@link https://datatracker.ietf.org/doc/html/rfc8414}
9
- * @note we do not enforce https: scheme in URIs to support development
10
- * environments. Make sure to validate the URIs before using it in a production
11
- * environment.
12
- */
13
- export const oauthAuthorizationServerMetadataSchema = z.object({
14
- issuer: oauthIssuerIdentifierSchema,
15
-
16
- claims_supported: z.array(z.string()).optional(),
17
- claims_locales_supported: z.array(z.string()).optional(),
18
- claims_parameter_supported: z.boolean().optional(),
19
- request_parameter_supported: z.boolean().optional(),
20
- request_uri_parameter_supported: z.boolean().optional(),
21
- require_request_uri_registration: z.boolean().optional(),
22
- scopes_supported: z.array(z.string()).optional(),
23
- subject_types_supported: z.array(z.string()).optional(),
24
- response_types_supported: z.array(z.string()).optional(),
25
- response_modes_supported: z.array(z.string()).optional(),
26
- grant_types_supported: z.array(z.string()).optional(),
27
- code_challenge_methods_supported: z
28
- .array(oauthCodeChallengeMethodSchema)
29
- .min(1)
30
- .optional(),
31
- ui_locales_supported: z.array(z.string()).optional(),
32
- id_token_signing_alg_values_supported: z.array(z.string()).optional(),
33
- display_values_supported: z.array(z.string()).optional(),
34
- request_object_signing_alg_values_supported: z.array(z.string()).optional(),
35
- authorization_response_iss_parameter_supported: z.boolean().optional(),
36
- authorization_details_types_supported: z.array(z.string()).optional(),
37
- request_object_encryption_alg_values_supported: z
38
- .array(z.string())
39
- .optional(),
40
- request_object_encryption_enc_values_supported: z
41
- .array(z.string())
42
- .optional(),
43
-
44
- jwks_uri: webUriSchema.optional(),
45
-
46
- authorization_endpoint: webUriSchema, // .optional(),
47
-
48
- token_endpoint: webUriSchema, // .optional(),
49
- // https://www.rfc-editor.org/rfc/rfc8414.html#section-2
50
- token_endpoint_auth_methods_supported: z
51
- .array(z.string())
52
- // > If omitted, the default is "client_secret_basic" [...].
53
- .default(['client_secret_basic']),
54
- token_endpoint_auth_signing_alg_values_supported: z
55
- .array(z.string())
56
- .optional(),
57
-
58
- revocation_endpoint: webUriSchema.optional(),
59
- introspection_endpoint: webUriSchema.optional(),
60
- pushed_authorization_request_endpoint: webUriSchema.optional(),
61
-
62
- require_pushed_authorization_requests: z.boolean().optional(),
63
-
64
- userinfo_endpoint: webUriSchema.optional(),
65
- end_session_endpoint: webUriSchema.optional(),
66
- registration_endpoint: webUriSchema.optional(),
67
-
68
- // https://datatracker.ietf.org/doc/html/rfc9449#section-5.1
69
- dpop_signing_alg_values_supported: z.array(z.string()).optional(),
70
-
71
- // https://www.rfc-editor.org/rfc/rfc9728.html#section-4
72
- protected_resources: z.array(webUriSchema).optional(),
73
-
74
- // https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html
75
- client_id_metadata_document_supported: z.boolean().optional(),
76
-
77
- // https://openid.net/specs/openid-connect-prompt-create-1_0.html#section-4.2
78
- prompt_values_supported: z.array(oauthPromptModeSchema).optional(),
79
- })
80
-
81
- export type OAuthAuthorizationServerMetadata = z.infer<
82
- typeof oauthAuthorizationServerMetadataSchema
83
- >
84
-
85
- export const oauthAuthorizationServerMetadataValidator =
86
- oauthAuthorizationServerMetadataSchema
87
- .superRefine((data, ctx) => {
88
- if (
89
- data.require_pushed_authorization_requests &&
90
- !data.pushed_authorization_request_endpoint
91
- ) {
92
- ctx.addIssue({
93
- code: z.ZodIssueCode.custom,
94
- message:
95
- '"pushed_authorization_request_endpoint" required when "require_pushed_authorization_requests" is true',
96
- })
97
- }
98
- })
99
- .superRefine((data, ctx) => {
100
- if (data.response_types_supported) {
101
- if (!data.response_types_supported.includes('code')) {
102
- ctx.addIssue({
103
- code: z.ZodIssueCode.custom,
104
- message: 'Response type "code" is required',
105
- })
106
- }
107
- }
108
- })
109
- .superRefine((data, ctx) => {
110
- if (
111
- data.token_endpoint_auth_signing_alg_values_supported?.includes('none')
112
- ) {
113
- // https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3
114
- // > The value `none` MUST NOT be used.
115
- ctx.addIssue({
116
- code: z.ZodIssueCode.custom,
117
- message: 'Client authentication method "none" is not allowed',
118
- })
119
- }
120
- })
@@ -1,9 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- export const oauthClientCredentialsGrantTokenRequestSchema = z.object({
4
- grant_type: z.literal('client_credentials'),
5
- })
6
-
7
- export type OAuthClientCredentialsGrantTokenRequest = z.infer<
8
- typeof oauthClientCredentialsGrantTokenRequestSchema
9
- >
@@ -1,53 +0,0 @@
1
- import { z } from 'zod'
2
- import { signedJwtSchema } from '@atproto/jwk'
3
- import { CLIENT_ASSERTION_TYPE_JWT_BEARER } from './constants.js'
4
- import { oauthClientIdSchema } from './oauth-client-id.js'
5
-
6
- export const oauthClientCredentialsJwtBearerSchema = z.object({
7
- client_id: oauthClientIdSchema,
8
- client_assertion_type: z.literal(CLIENT_ASSERTION_TYPE_JWT_BEARER),
9
- /**
10
- * - "sub" the subject MUST be the "client_id" of the OAuth client
11
- * - "iat" is required and MUST be less than one minute
12
- * - "aud" must containing a value that identifies the authorization server
13
- * - The JWT MAY contain a "jti" (JWT ID) claim that provides a unique identifier for the token.
14
- * - Note that the authorization server may reject JWTs with an "exp" claim value that is unreasonably far in the future.
15
- *
16
- * @see {@link https://datatracker.ietf.org/doc/html/rfc7523#section-3}
17
- */
18
- client_assertion: signedJwtSchema,
19
- })
20
-
21
- export type OAuthClientCredentialsJwtBearer = z.infer<
22
- typeof oauthClientCredentialsJwtBearerSchema
23
- >
24
-
25
- export const oauthClientCredentialsSecretPostSchema = z.object({
26
- client_id: oauthClientIdSchema,
27
- client_secret: z.string(),
28
- })
29
-
30
- export type OAuthClientCredentialsSecretPost = z.infer<
31
- typeof oauthClientCredentialsSecretPostSchema
32
- >
33
-
34
- export const oauthClientCredentialsNoneSchema = z.object({
35
- client_id: oauthClientIdSchema,
36
- })
37
-
38
- export type OAuthClientCredentialsNone = z.infer<
39
- typeof oauthClientCredentialsNoneSchema
40
- >
41
-
42
- //
43
-
44
- export const oauthClientCredentialsSchema = z.union([
45
- oauthClientCredentialsJwtBearerSchema,
46
- oauthClientCredentialsSecretPostSchema,
47
- // Must be last since it is less specific
48
- oauthClientCredentialsNoneSchema,
49
- ])
50
-
51
- export type OAuthClientCredentials = z.infer<
52
- typeof oauthClientCredentialsSchema
53
- >
@@ -1,130 +0,0 @@
1
- import { TypeOf, z } from 'zod'
2
- import { oauthClientIdSchema } from './oauth-client-id.js'
3
- import { httpsUriSchema } from './uri.js'
4
- import { extractUrlPath, isHostnameIP } from './util.js'
5
-
6
- /**
7
- * @see {@link https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html}
8
- */
9
- export const oauthClientIdDiscoverableSchema = z
10
- .intersection(oauthClientIdSchema, httpsUriSchema)
11
- .superRefine((value, ctx): value is `https://${string}/${string}` => {
12
- const url = new URL(value)
13
-
14
- if (url.username || url.password) {
15
- ctx.addIssue({
16
- code: z.ZodIssueCode.custom,
17
- message: 'ClientID must not contain credentials',
18
- })
19
- return false
20
- }
21
-
22
- if (url.hash) {
23
- ctx.addIssue({
24
- code: z.ZodIssueCode.custom,
25
- message: 'ClientID must not contain a fragment',
26
- })
27
- return false
28
- }
29
-
30
- if (url.pathname === '/') {
31
- ctx.addIssue({
32
- code: z.ZodIssueCode.custom,
33
- message:
34
- 'ClientID must contain a path component (e.g. "/client-metadata.json")',
35
- })
36
- return false
37
- }
38
-
39
- if (url.pathname.endsWith('/')) {
40
- ctx.addIssue({
41
- code: z.ZodIssueCode.custom,
42
- message: 'ClientID path must not end with a trailing slash',
43
- })
44
- return false
45
- }
46
-
47
- if (isHostnameIP(url.hostname)) {
48
- ctx.addIssue({
49
- code: z.ZodIssueCode.custom,
50
- message: 'ClientID hostname must not be an IP address',
51
- })
52
- return false
53
- }
54
-
55
- // URL constructor normalizes the URL, so we extract the path manually to
56
- // avoid normalization, then compare it to the normalized path to ensure
57
- // that the URL does not contain path traversal or other unexpected characters
58
- if (extractUrlPath(value) !== url.pathname) {
59
- ctx.addIssue({
60
- code: z.ZodIssueCode.custom,
61
- message: `ClientID must be in canonical form ("${url.href}", got "${value}")`,
62
- })
63
- return false
64
- }
65
-
66
- return true
67
- })
68
-
69
- export type OAuthClientIdDiscoverable = TypeOf<
70
- typeof oauthClientIdDiscoverableSchema
71
- >
72
-
73
- export function isOAuthClientIdDiscoverable(
74
- clientId: string,
75
- ): clientId is OAuthClientIdDiscoverable {
76
- return oauthClientIdDiscoverableSchema.safeParse(clientId).success
77
- }
78
-
79
- export const conventionalOAuthClientIdSchema =
80
- oauthClientIdDiscoverableSchema.superRefine(
81
- (value, ctx): value is `https://${string}/oauth-client-metadata.json` => {
82
- const url = new URL(value)
83
-
84
- if (url.port) {
85
- ctx.addIssue({
86
- code: z.ZodIssueCode.custom,
87
- message: 'ClientID must not contain a port',
88
- })
89
- return false
90
- }
91
-
92
- if (url.search) {
93
- ctx.addIssue({
94
- code: z.ZodIssueCode.custom,
95
- message: 'ClientID must not contain a query string',
96
- })
97
- return false
98
- }
99
-
100
- if (url.pathname !== '/oauth-client-metadata.json') {
101
- ctx.addIssue({
102
- code: z.ZodIssueCode.custom,
103
- message: 'ClientID must be "/oauth-client-metadata.json"',
104
- })
105
- return false
106
- }
107
-
108
- return true
109
- },
110
- )
111
-
112
- export type ConventionalOAuthClientId = TypeOf<
113
- typeof conventionalOAuthClientIdSchema
114
- >
115
-
116
- export function isConventionalOAuthClientId(
117
- clientId: string,
118
- ): clientId is ConventionalOAuthClientId {
119
- return conventionalOAuthClientIdSchema.safeParse(clientId).success
120
- }
121
-
122
- export function assertOAuthDiscoverableClientId(
123
- value: string,
124
- ): asserts value is OAuthClientIdDiscoverable {
125
- void oauthClientIdDiscoverableSchema.parse(value)
126
- }
127
-
128
- export function parseOAuthDiscoverableClientId(clientId: string): URL {
129
- return new URL(oauthClientIdDiscoverableSchema.parse(clientId))
130
- }
@@ -1,164 +0,0 @@
1
- import { oauthClientIdSchema } from './oauth-client-id.js'
2
- import {
3
- OAuthLoopbackRedirectURI,
4
- oauthLoopbackClientRedirectUriSchema,
5
- } from './oauth-redirect-uri.js'
6
- import { OAuthScope, oauthScopeSchema } from './oauth-scope.js'
7
-
8
- export const LOOPBACK_CLIENT_ID_ORIGIN = 'http://localhost'
9
-
10
- // @NOTE This is not actually based on a standard, but rather a convention
11
- // established by Bluesky in the Atproto specs and implementation. As such, and
12
- // in order to respect the convention from this package, these should be
13
- // prefixed with "Atproto" instead of "OAuth". For legacy reasons, we keep the
14
- // current names, but we should rename them in a future major release, unless
15
- // loopback client ids have since then been standardized.
16
-
17
- export type OAuthClientIdLoopback =
18
- `http://localhost${'' | `/`}${'' | `?${string}`}`
19
-
20
- export type OAuthLoopbackClientIdParams = {
21
- scope?: OAuthScope
22
- redirect_uris?: [OAuthLoopbackRedirectURI, ...OAuthLoopbackRedirectURI[]]
23
- }
24
-
25
- export const oauthClientIdLoopbackSchema = oauthClientIdSchema.superRefine(
26
- (input, ctx): input is OAuthClientIdLoopback => {
27
- const result = safeParseOAuthLoopbackClientId(input)
28
- if (!result.success) {
29
- ctx.addIssue({ code: 'custom', message: result.message })
30
- }
31
- return result.success
32
- },
33
- )
34
-
35
- export function assertOAuthLoopbackClientId(
36
- input: string,
37
- ): asserts input is OAuthClientIdLoopback {
38
- void parseOAuthLoopbackClientId(input)
39
- }
40
-
41
- export function isOAuthClientIdLoopback<T extends string>(
42
- input: T,
43
- ): input is T & OAuthClientIdLoopback {
44
- return safeParseOAuthLoopbackClientId(input).success
45
- }
46
-
47
- export function asOAuthClientIdLoopback<T extends string>(input: T) {
48
- assertOAuthLoopbackClientId(input)
49
- return input
50
- }
51
-
52
- export function parseOAuthLoopbackClientId(
53
- input: string,
54
- ): OAuthLoopbackClientIdParams {
55
- const result = safeParseOAuthLoopbackClientId(input)
56
- if (result.success) return result.value
57
-
58
- throw new TypeError(`Invalid loopback client ID: ${result.message}`)
59
- }
60
-
61
- /**
62
- * Similar to Zod's {@link SafeParseReturnType} but uses a simple "message"
63
- * string instead of an "error" Error object.
64
- */
65
- type LightParseReturnType<T> =
66
- | { success: true; value: T }
67
- | { success: false; message: string }
68
-
69
- export function safeParseOAuthLoopbackClientId(
70
- input: string,
71
- ): LightParseReturnType<OAuthLoopbackClientIdParams> {
72
- // @NOTE Not using "new URL" to ensure input indeed matches the type
73
- // OAuthClientIdLoopback
74
-
75
- if (!input.startsWith(LOOPBACK_CLIENT_ID_ORIGIN)) {
76
- return {
77
- success: false,
78
- message: `Value must start with "${LOOPBACK_CLIENT_ID_ORIGIN}"`,
79
- }
80
- }
81
-
82
- if (input.includes('#', LOOPBACK_CLIENT_ID_ORIGIN.length)) {
83
- return {
84
- success: false,
85
- message: 'Value must not contain a hash component',
86
- }
87
- }
88
-
89
- // Since we don't allow a path component (except for a single "/") the query
90
- // string starts after the origin (+ 1 if there is a "/")
91
- const queryStringIdx =
92
- input.length > LOOPBACK_CLIENT_ID_ORIGIN.length &&
93
- input.charCodeAt(LOOPBACK_CLIENT_ID_ORIGIN.length) === 0x2f /* '/' */
94
- ? LOOPBACK_CLIENT_ID_ORIGIN.length + 1
95
- : LOOPBACK_CLIENT_ID_ORIGIN.length
96
-
97
- // Since we determined the position of the query string based on the origin
98
- // length (instead of looking for a "?"), we need to make sure the query
99
- // string position (if any) indeed starts with a "?".
100
- if (
101
- input.length !== queryStringIdx &&
102
- input.charCodeAt(queryStringIdx) !== 0x3f /* '?' */
103
- ) {
104
- return {
105
- success: false,
106
- message: 'Value must not contain a path component',
107
- }
108
- }
109
-
110
- const queryString = input.slice(queryStringIdx + 1)
111
- return safeParseOAuthLoopbackClientIdQueryString(queryString)
112
- }
113
-
114
- export function safeParseOAuthLoopbackClientIdQueryString(
115
- input: string | Iterable<[key: string, value: string]>,
116
- ): LightParseReturnType<OAuthLoopbackClientIdParams> {
117
- // Parse query params
118
- const params: OAuthLoopbackClientIdParams = {}
119
-
120
- const it = typeof input === 'string' ? new URLSearchParams(input) : input
121
- for (const [key, value] of it) {
122
- if (key === 'scope') {
123
- if ('scope' in params) {
124
- return {
125
- success: false,
126
- message: 'Duplicate "scope" query parameter',
127
- }
128
- }
129
-
130
- const res = oauthScopeSchema.safeParse(value)
131
- if (!res.success) {
132
- const reason = res.error.issues.map((i) => i.message).join(', ')
133
- return {
134
- success: false,
135
- message: `Invalid "scope" query parameter: ${reason || 'Validation failed'}`,
136
- }
137
- }
138
-
139
- params.scope = res.data
140
- } else if (key === 'redirect_uri') {
141
- const res = oauthLoopbackClientRedirectUriSchema.safeParse(value)
142
- if (!res.success) {
143
- const reason = res.error.issues.map((i) => i.message).join(', ')
144
- return {
145
- success: false,
146
- message: `Invalid "redirect_uri" query parameter: ${reason || 'Validation failed'}`,
147
- }
148
- }
149
-
150
- if (params.redirect_uris == null) params.redirect_uris = [res.data]
151
- else params.redirect_uris.push(res.data)
152
- } else {
153
- return {
154
- success: false,
155
- message: `Unexpected query parameter "${key}"`,
156
- }
157
- }
158
- }
159
-
160
- return {
161
- success: true,
162
- value: params,
163
- }
164
- }
@@ -1,4 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- export const oauthClientIdSchema = z.string().min(1)
4
- export type OAuthClientId = z.infer<typeof oauthClientIdSchema>
@@ -1,80 +0,0 @@
1
- import { z } from 'zod'
2
- import { jwksPubSchema } from '@atproto/jwk'
3
- import { oauthClientIdSchema } from './oauth-client-id.js'
4
- import { oauthEndpointAuthMethod } from './oauth-endpoint-auth-method.js'
5
- import { oauthGrantTypeSchema } from './oauth-grant-type.js'
6
- import { oauthRedirectUriSchema } from './oauth-redirect-uri.js'
7
- import { oauthResponseTypeSchema } from './oauth-response-type.js'
8
- import { oauthScopeSchema } from './oauth-scope.js'
9
- import { webUriSchema } from './uri.js'
10
-
11
- /**
12
- * @see {@link https://openid.net/specs/openid-connect-registration-1_0.html}
13
- * @see {@link https://datatracker.ietf.org/doc/html/rfc7591}
14
- * @note we do not enforce https: scheme in URIs to support development
15
- * environments. Make sure to validate the URIs before using it in a production
16
- * environment.
17
- */
18
- export const oauthClientMetadataSchema = z.object({
19
- /**
20
- * @note redirect_uris require additional validation
21
- */
22
- // https://www.rfc-editor.org/rfc/rfc7591.html#section-2
23
- redirect_uris: z.array(oauthRedirectUriSchema).nonempty(),
24
- response_types: z
25
- .array(oauthResponseTypeSchema)
26
- .nonempty()
27
- // > If omitted, the default is that the client will use only the "code"
28
- // > response type.
29
- .default(['code']),
30
- grant_types: z
31
- .array(oauthGrantTypeSchema)
32
- .nonempty()
33
- // > If omitted, the default behavior is that the client will use only the
34
- // > "authorization_code" Grant Type.
35
- .default(['authorization_code']),
36
- scope: oauthScopeSchema.optional(),
37
- // https://www.rfc-editor.org/rfc/rfc7591.html#section-2
38
- token_endpoint_auth_method: oauthEndpointAuthMethod
39
- // > If unspecified or omitted, the default is "client_secret_basic" [...].
40
- .default('client_secret_basic'),
41
- token_endpoint_auth_signing_alg: z.string().optional(),
42
- userinfo_signed_response_alg: z.string().optional(),
43
- userinfo_encrypted_response_alg: z.string().optional(),
44
- jwks_uri: webUriSchema.optional(),
45
- jwks: jwksPubSchema.optional(),
46
- application_type: z.enum(['web', 'native']).default('web'), // default, per spec, is "web"
47
- subject_type: z.enum(['public', 'pairwise']).default('public'),
48
- request_object_signing_alg: z.string().optional(),
49
- id_token_signed_response_alg: z.string().optional(),
50
- authorization_signed_response_alg: z.string().default('RS256'),
51
- authorization_encrypted_response_enc: z.enum(['A128CBC-HS256']).optional(),
52
- authorization_encrypted_response_alg: z.string().optional(),
53
- client_id: oauthClientIdSchema.optional(),
54
- client_name: z.string().optional(),
55
- client_uri: webUriSchema.optional(),
56
- policy_uri: webUriSchema.optional(),
57
- tos_uri: webUriSchema.optional(),
58
- logo_uri: webUriSchema.optional(), // @TODO: allow data: uri ?
59
-
60
- /**
61
- * Default Maximum Authentication Age. Specifies that the End-User MUST be
62
- * actively authenticated if the End-User was authenticated longer ago than
63
- * the specified number of seconds. The max_age request parameter overrides
64
- * this default value. If omitted, no default Maximum Authentication Age is
65
- * specified.
66
- */
67
- default_max_age: z.number().optional(),
68
- require_auth_time: z.boolean().optional(),
69
- contacts: z.array(z.string().email()).optional(),
70
- tls_client_certificate_bound_access_tokens: z.boolean().optional(),
71
-
72
- // https://datatracker.ietf.org/doc/html/rfc9449#section-5.2
73
- dpop_bound_access_tokens: z.boolean().optional(),
74
-
75
- // https://datatracker.ietf.org/doc/html/rfc9396#section-14.5
76
- authorization_details_types: z.array(z.string()).optional(),
77
- })
78
-
79
- export type OAuthClientMetadata = z.infer<typeof oauthClientMetadataSchema>
80
- export type OAuthClientMetadataInput = z.input<typeof oauthClientMetadataSchema>
@@ -1,3 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- export const oauthCodeChallengeMethodSchema = z.enum(['S256', 'plain'])
@@ -1,13 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- export const oauthEndpointAuthMethod = z.enum([
4
- 'client_secret_basic',
5
- 'client_secret_jwt',
6
- 'client_secret_post',
7
- 'none',
8
- 'private_key_jwt',
9
- 'self_signed_tls_client_auth',
10
- 'tls_client_auth',
11
- ])
12
-
13
- export type OauthEndpointAuthMethod = z.infer<typeof oauthEndpointAuthMethod>
@@ -1,8 +0,0 @@
1
- export const OAUTH_ENDPOINT_NAMES = [
2
- 'token',
3
- 'revocation',
4
- 'introspection',
5
- 'pushed_authorization_request',
6
- ] as const
7
-
8
- export type OAuthEndpointName = (typeof OAUTH_ENDPOINT_NAMES)[number]
@@ -1,13 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- export const oauthGrantTypeSchema = z.enum([
4
- 'authorization_code',
5
- 'implicit',
6
- 'refresh_token',
7
- 'password', // Not part of OAuth 2.1
8
- 'client_credentials',
9
- 'urn:ietf:params:oauth:grant-type:jwt-bearer',
10
- 'urn:ietf:params:oauth:grant-type:saml2-bearer',
11
- ])
12
-
13
- export type OAuthGrantType = z.infer<typeof oauthGrantTypeSchema>
@@ -1,23 +0,0 @@
1
- import { OAuthAuthorizationDetails } from './oauth-authorization-details.js'
2
- import { OAuthTokenType } from './oauth-token-type.js'
3
-
4
- // https://datatracker.ietf.org/doc/html/rfc7662#section-2.2
5
- export type OAuthIntrospectionResponse =
6
- | { active: false }
7
- | {
8
- active: true
9
-
10
- scope?: string
11
- client_id?: string
12
- username?: string
13
- token_type?: OAuthTokenType
14
- authorization_details?: OAuthAuthorizationDetails
15
-
16
- aud?: string | [string, ...string[]]
17
- exp?: number
18
- iat?: number
19
- iss?: string
20
- jti?: string
21
- nbf?: number
22
- sub?: string
23
- }
@@ -1,47 +0,0 @@
1
- import { z } from 'zod'
2
- import { webUriSchema } from './uri.js'
3
-
4
- export const oauthIssuerIdentifierSchema = webUriSchema.superRefine(
5
- (value, ctx) => {
6
- // Validate the issuer (MIX-UP attacks)
7
-
8
- if (value.endsWith('/')) {
9
- ctx.addIssue({
10
- code: z.ZodIssueCode.custom,
11
- message: 'Issuer URL must not end with a slash',
12
- })
13
- return false
14
- }
15
-
16
- const url = new URL(value)
17
-
18
- if (url.username || url.password) {
19
- ctx.addIssue({
20
- code: z.ZodIssueCode.custom,
21
- message: 'Issuer URL must not contain a username or password',
22
- })
23
- return false
24
- }
25
-
26
- if (url.hash || url.search) {
27
- ctx.addIssue({
28
- code: z.ZodIssueCode.custom,
29
- message: 'Issuer URL must not contain a query or fragment',
30
- })
31
- return false
32
- }
33
-
34
- const canonicalValue = url.pathname === '/' ? url.origin : url.href
35
- if (value !== canonicalValue) {
36
- ctx.addIssue({
37
- code: z.ZodIssueCode.custom,
38
- message: 'Issuer URL must be in the canonical form',
39
- })
40
- return false
41
- }
42
-
43
- return true
44
- },
45
- )
46
-
47
- export type OAuthIssuerIdentifier = z.infer<typeof oauthIssuerIdentifierSchema>
@@ -1,8 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- export const oauthParResponseSchema = z.object({
4
- request_uri: z.string(),
5
- expires_in: z.number().int().positive(),
6
- })
7
-
8
- export type OAuthParResponse = z.infer<typeof oauthParResponseSchema>