@atcute/oauth-types 0.1.1 → 1.0.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.
- package/README.md +6 -5
- package/dist/build-client-metadata.d.ts +5 -320
- package/dist/build-client-metadata.d.ts.map +1 -1
- package/dist/build-client-metadata.js +3 -2
- package/dist/build-client-metadata.js.map +1 -1
- package/dist/index.d.ts +31 -31
- package/dist/schemas/atcute-client-shared.d.ts +8 -0
- package/dist/schemas/atcute-client-shared.d.ts.map +1 -0
- package/dist/schemas/atcute-client-shared.js +15 -0
- package/dist/schemas/atcute-client-shared.js.map +1 -0
- package/dist/schemas/atcute-confidential-client-metadata.d.ts +228 -4
- package/dist/schemas/atcute-confidential-client-metadata.d.ts.map +1 -1
- package/dist/schemas/atcute-confidential-client-metadata.js +48 -88
- package/dist/schemas/atcute-confidential-client-metadata.js.map +1 -1
- package/dist/schemas/atcute-public-client-metadata.d.ts +75 -35
- package/dist/schemas/atcute-public-client-metadata.d.ts.map +1 -1
- package/dist/schemas/atcute-public-client-metadata.js +25 -110
- package/dist/schemas/atcute-public-client-metadata.js.map +1 -1
- package/dist/schemas/atproto-authorization-server-metadata.d.ts +786 -4
- package/dist/schemas/atproto-authorization-server-metadata.d.ts.map +1 -1
- package/dist/schemas/atproto-authorization-server-metadata.js +2 -18
- package/dist/schemas/atproto-authorization-server-metadata.js.map +1 -1
- package/dist/schemas/atproto-oauth-scope.d.ts +3 -3
- package/dist/schemas/atproto-oauth-scope.d.ts.map +1 -1
- package/dist/schemas/atproto-oauth-scope.js +2 -2
- package/dist/schemas/atproto-oauth-scope.js.map +1 -1
- package/dist/schemas/atproto-oauth-token-response.d.ts +17 -17
- package/dist/schemas/atproto-oauth-token-response.d.ts.map +1 -1
- package/dist/schemas/atproto-oauth-token-response.js +6 -6
- package/dist/schemas/atproto-oauth-token-response.js.map +1 -1
- package/dist/schemas/atproto-protected-resource-metadata.d.ts +100 -4
- package/dist/schemas/atproto-protected-resource-metadata.d.ts.map +1 -1
- package/dist/schemas/atproto-protected-resource-metadata.js +2 -11
- package/dist/schemas/atproto-protected-resource-metadata.js.map +1 -1
- package/dist/schemas/jwk.d.ts +4289 -42
- package/dist/schemas/jwk.d.ts.map +1 -1
- package/dist/schemas/jwk.js +58 -91
- package/dist/schemas/jwk.js.map +1 -1
- package/dist/schemas/jwks.d.ts +87 -42
- package/dist/schemas/jwks.d.ts.map +1 -1
- package/dist/schemas/jwks.js +13 -29
- package/dist/schemas/jwks.js.map +1 -1
- package/dist/schemas/oauth-authorization-details.d.ts +18 -18
- package/dist/schemas/oauth-authorization-details.d.ts.map +1 -1
- package/dist/schemas/oauth-authorization-details.js +7 -7
- package/dist/schemas/oauth-authorization-details.js.map +1 -1
- package/dist/schemas/oauth-authorization-server-metadata.d.ts +462 -48
- package/dist/schemas/oauth-authorization-server-metadata.d.ts.map +1 -1
- package/dist/schemas/oauth-authorization-server-metadata.js +46 -65
- package/dist/schemas/oauth-authorization-server-metadata.js.map +1 -1
- package/dist/schemas/oauth-client-id-discoverable.d.ts +2 -2
- package/dist/schemas/oauth-client-id-discoverable.d.ts.map +1 -1
- package/dist/schemas/oauth-client-id-discoverable.js +20 -22
- package/dist/schemas/oauth-client-id-discoverable.js.map +1 -1
- package/dist/schemas/oauth-client-id.d.ts +3 -3
- package/dist/schemas/oauth-client-id.d.ts.map +1 -1
- package/dist/schemas/oauth-client-id.js +2 -2
- package/dist/schemas/oauth-client-id.js.map +1 -1
- package/dist/schemas/oauth-client-metadata.d.ts +73 -51
- package/dist/schemas/oauth-client-metadata.d.ts.map +1 -1
- package/dist/schemas/oauth-client-metadata.js +33 -40
- package/dist/schemas/oauth-client-metadata.js.map +1 -1
- package/dist/schemas/oauth-code-challenge-method.d.ts +3 -3
- package/dist/schemas/oauth-code-challenge-method.d.ts.map +1 -1
- package/dist/schemas/oauth-code-challenge-method.js +2 -2
- package/dist/schemas/oauth-code-challenge-method.js.map +1 -1
- package/dist/schemas/oauth-endpoint-auth-method.d.ts +3 -3
- package/dist/schemas/oauth-endpoint-auth-method.d.ts.map +1 -1
- package/dist/schemas/oauth-endpoint-auth-method.js +10 -2
- package/dist/schemas/oauth-endpoint-auth-method.js.map +1 -1
- package/dist/schemas/oauth-grant-type.d.ts +3 -3
- package/dist/schemas/oauth-grant-type.d.ts.map +1 -1
- package/dist/schemas/oauth-grant-type.js +10 -3
- package/dist/schemas/oauth-grant-type.js.map +1 -1
- package/dist/schemas/oauth-issuer-identifier.d.ts +3 -3
- package/dist/schemas/oauth-issuer-identifier.d.ts.map +1 -1
- package/dist/schemas/oauth-issuer-identifier.js +16 -9
- package/dist/schemas/oauth-issuer-identifier.js.map +1 -1
- package/dist/schemas/oauth-par-response.d.ts +5 -5
- package/dist/schemas/oauth-par-response.d.ts.map +1 -1
- package/dist/schemas/oauth-par-response.js +3 -3
- package/dist/schemas/oauth-par-response.js.map +1 -1
- package/dist/schemas/oauth-prompt.d.ts +3 -3
- package/dist/schemas/oauth-prompt.d.ts.map +1 -1
- package/dist/schemas/oauth-prompt.js +2 -2
- package/dist/schemas/oauth-prompt.js.map +1 -1
- package/dist/schemas/oauth-protected-resource-metadata.d.ts +88 -16
- package/dist/schemas/oauth-protected-resource-metadata.d.ts.map +1 -1
- package/dist/schemas/oauth-protected-resource-metadata.js +14 -26
- package/dist/schemas/oauth-protected-resource-metadata.js.map +1 -1
- package/dist/schemas/oauth-redirect-uri.d.ts +5 -5
- package/dist/schemas/oauth-redirect-uri.d.ts.map +1 -1
- package/dist/schemas/oauth-redirect-uri.js +3 -16
- package/dist/schemas/oauth-redirect-uri.js.map +1 -1
- package/dist/schemas/oauth-response-mode.d.ts +3 -3
- package/dist/schemas/oauth-response-mode.d.ts.map +1 -1
- package/dist/schemas/oauth-response-mode.js +2 -2
- package/dist/schemas/oauth-response-mode.js.map +1 -1
- package/dist/schemas/oauth-response-type.d.ts +3 -3
- package/dist/schemas/oauth-response-type.d.ts.map +1 -1
- package/dist/schemas/oauth-response-type.js +13 -7
- package/dist/schemas/oauth-response-type.js.map +1 -1
- package/dist/schemas/oauth-scope.d.ts +3 -3
- package/dist/schemas/oauth-scope.d.ts.map +1 -1
- package/dist/schemas/oauth-scope.js +2 -2
- package/dist/schemas/oauth-scope.js.map +1 -1
- package/dist/schemas/oauth-token-response.d.ts +17 -17
- package/dist/schemas/oauth-token-response.d.ts.map +1 -1
- package/dist/schemas/oauth-token-response.js +7 -7
- package/dist/schemas/oauth-token-response.js.map +1 -1
- package/dist/schemas/oauth-token-type.d.ts +3 -3
- package/dist/schemas/oauth-token-type.d.ts.map +1 -1
- package/dist/schemas/oauth-token-type.js +8 -7
- package/dist/schemas/oauth-token-type.js.map +1 -1
- package/dist/schemas/uri.d.ts +7 -7
- package/dist/schemas/uri.d.ts.map +1 -1
- package/dist/schemas/uri.js +44 -44
- package/dist/schemas/uri.js.map +1 -1
- package/dist/schemas/utils.d.ts.map +1 -1
- package/dist/schemas/utils.js.map +1 -1
- package/dist/scope.d.ts.map +1 -1
- package/dist/scope.js.map +1 -1
- package/lib/build-client-metadata.ts +9 -7
- package/lib/index.ts +31 -31
- package/lib/schemas/atcute-client-shared.ts +25 -0
- package/lib/schemas/atcute-confidential-client-metadata.ts +81 -111
- package/lib/schemas/atcute-public-client-metadata.ts +70 -166
- package/lib/schemas/atproto-authorization-server-metadata.ts +22 -23
- package/lib/schemas/atproto-oauth-scope.ts +8 -5
- package/lib/schemas/atproto-oauth-token-response.ts +10 -9
- package/lib/schemas/atproto-protected-resource-metadata.ts +15 -15
- package/lib/schemas/jwk.ts +104 -120
- package/lib/schemas/jwks.ts +28 -40
- package/lib/schemas/oauth-authorization-details.ts +10 -10
- package/lib/schemas/oauth-authorization-server-metadata.ts +72 -74
- package/lib/schemas/oauth-client-id-discoverable.ts +43 -48
- package/lib/schemas/oauth-client-id.ts +3 -3
- package/lib/schemas/oauth-client-metadata.ts +45 -49
- package/lib/schemas/oauth-code-challenge-method.ts +3 -3
- package/lib/schemas/oauth-endpoint-auth-method.ts +11 -11
- package/lib/schemas/oauth-grant-type.ts +11 -11
- package/lib/schemas/oauth-issuer-identifier.ts +35 -27
- package/lib/schemas/oauth-par-response.ts +4 -4
- package/lib/schemas/oauth-prompt.ts +3 -9
- package/lib/schemas/oauth-protected-resource-metadata.ts +26 -35
- package/lib/schemas/oauth-redirect-uri.ts +15 -23
- package/lib/schemas/oauth-response-mode.ts +3 -7
- package/lib/schemas/oauth-response-type.ts +12 -12
- package/lib/schemas/oauth-scope.ts +3 -3
- package/lib/schemas/oauth-token-response.ts +10 -10
- package/lib/schemas/oauth-token-type.ts +16 -12
- package/lib/schemas/uri.ts +89 -76
- package/package.json +9 -8
|
@@ -1,66 +1,30 @@
|
|
|
1
|
-
import * as v from '
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import { oauthClientIdDiscoverableSchema } from './oauth-client-id-discoverable.
|
|
5
|
-
import { loopbackRedirectUriSchema, oauthRedirectUriSchema } from './oauth-redirect-uri.
|
|
6
|
-
import { nonLocalWebUriSchema,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const scopes = input.split(/\s+/);
|
|
16
|
-
|
|
17
|
-
for (let i = 0, len = scopes.length; i < len; i++) {
|
|
18
|
-
const aka = scopes[i];
|
|
19
|
-
|
|
20
|
-
for (let j = 0; j < i; j++) {
|
|
21
|
-
if (aka === scopes[j]) {
|
|
22
|
-
return v.err(`duplicate "${aka}" scope`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return v.ok(input);
|
|
28
|
-
}),
|
|
29
|
-
v.array(singleScopeSchema).chain((input) => {
|
|
30
|
-
if (!input.includes('atproto')) {
|
|
31
|
-
input = ['atproto', ...input];
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
|
|
3
|
+
import { scopeSchema } from './atcute-client-shared.ts';
|
|
4
|
+
import { oauthClientIdDiscoverableSchema } from './oauth-client-id-discoverable.ts';
|
|
5
|
+
import { loopbackRedirectUriSchema, oauthRedirectUriSchema } from './oauth-redirect-uri.ts';
|
|
6
|
+
import { nonLocalWebUriSchema, webUriSchema } from './uri.ts';
|
|
7
|
+
|
|
8
|
+
const redirectUrisSchema = v.pipe(
|
|
9
|
+
v.array(oauthRedirectUriSchema),
|
|
10
|
+
v.minLength(1, `must have at least one redirect URI`),
|
|
11
|
+
v.checkItems((uri) => {
|
|
12
|
+
// private-use URIs don't have URL-style credentials
|
|
13
|
+
if (!uri.includes('://')) {
|
|
14
|
+
return true;
|
|
32
15
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
for (let j = 0; j < i; j++) {
|
|
38
|
-
if (aka === input[j]) {
|
|
39
|
-
return v.err(`duplicate "${aka}" scope`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return v.ok(input);
|
|
45
|
-
}),
|
|
16
|
+
const url = new URL(uri);
|
|
17
|
+
return !url.username && !url.password;
|
|
18
|
+
}, `redirect URI must not contain credentials`),
|
|
46
19
|
);
|
|
47
20
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
const url = new URL(uri);
|
|
58
|
-
if (url.username || url.password) {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return true;
|
|
63
|
-
}, `redirect URIs must not contain credentials`);
|
|
21
|
+
const loopbackRedirectUrisSchema = v.pipe(
|
|
22
|
+
redirectUrisSchema,
|
|
23
|
+
v.checkItems(
|
|
24
|
+
(uri) => v.is(loopbackRedirectUriSchema, uri),
|
|
25
|
+
`loopback clients require loopback redirect URIs (127.0.0.1 or [::1])`,
|
|
26
|
+
),
|
|
27
|
+
);
|
|
64
28
|
|
|
65
29
|
/**
|
|
66
30
|
* user-facing client metadata for configuring a loopback public OAuth client.
|
|
@@ -69,48 +33,24 @@ const redirectUrisSchema = v
|
|
|
69
33
|
* `http://localhost` as the client_id origin, which is built automatically
|
|
70
34
|
* from the redirect_uris and scope.
|
|
71
35
|
*/
|
|
72
|
-
export const loopbackClientMetadataSchema = v
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
client_id: v.undefined().optional(),
|
|
36
|
+
export const loopbackClientMetadataSchema = v.looseObject({
|
|
37
|
+
/** must not be provided for loopback clients */
|
|
38
|
+
client_id: v.optional(v.undefined()),
|
|
76
39
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
40
|
+
/**
|
|
41
|
+
* redirect URIs for authorization responses.
|
|
42
|
+
*
|
|
43
|
+
* must be loopback IP addresses (127.0.0.1 or [::1]).
|
|
44
|
+
* per RFC 8252, port numbers are ignored during redirect URI matching,
|
|
45
|
+
* allowing ephemeral ports.
|
|
46
|
+
*/
|
|
47
|
+
redirect_uris: loopbackRedirectUrisSchema,
|
|
85
48
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
.chain((input) => {
|
|
90
|
-
// validate all redirect URIs are loopback
|
|
91
|
-
for (let i = 0; i < input.redirect_uris.length; i++) {
|
|
92
|
-
const uri = input.redirect_uris[i];
|
|
93
|
-
const result = loopbackRedirectUriSchema.try(uri, { mode: 'strict' });
|
|
94
|
-
if (!result.ok) {
|
|
95
|
-
return v.err({
|
|
96
|
-
message: `loopback clients require loopback redirect URIs (127.0.0.1 or [::1]): ${result.message}`,
|
|
97
|
-
path: ['redirect_uris', i],
|
|
98
|
-
});
|
|
99
|
-
}
|
|
49
|
+
/** OAuth scope (must include "atproto") */
|
|
50
|
+
scope: scopeSchema,
|
|
51
|
+
});
|
|
100
52
|
|
|
101
|
-
|
|
102
|
-
if (!isLoopbackHost(url.hostname) || url.hostname === 'localhost') {
|
|
103
|
-
return v.err({
|
|
104
|
-
message: `loopback redirect URIs must use 127.0.0.1 or [::1], not ${url.hostname}`,
|
|
105
|
-
path: ['redirect_uris', i],
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return v.ok(input);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
export type LoopbackClientMetadata = v.Infer<typeof loopbackClientMetadataSchema>;
|
|
53
|
+
export type LoopbackClientMetadata = v.InferOutput<typeof loopbackClientMetadataSchema>;
|
|
114
54
|
|
|
115
55
|
/**
|
|
116
56
|
* user-facing client metadata for configuring a discoverable public OAuth client.
|
|
@@ -118,70 +58,34 @@ export type LoopbackClientMetadata = v.Infer<typeof loopbackClientMetadataSchema
|
|
|
118
58
|
* discoverable public clients have an HTTPS client_id URL where metadata is hosted,
|
|
119
59
|
* but don't use a keyset (token_endpoint_auth_method: 'none').
|
|
120
60
|
*/
|
|
121
|
-
export const discoverablePublicClientMetadataSchema = v
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// validate redirect URIs are HTTPS, loopback, or private-use
|
|
150
|
-
for (let i = 0; i < input.redirect_uris.length; i++) {
|
|
151
|
-
const uri = input.redirect_uris[i];
|
|
152
|
-
|
|
153
|
-
// private-use URIs are allowed
|
|
154
|
-
if (!uri.includes('://')) {
|
|
155
|
-
const result = privateUseUriSchema.try(uri, { mode: 'strict' });
|
|
156
|
-
if (!result.ok) {
|
|
157
|
-
return v.err({
|
|
158
|
-
message: `invalid redirect URI: ${result.message}`,
|
|
159
|
-
path: ['redirect_uris', i],
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
continue;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const url = new URL(uri);
|
|
166
|
-
|
|
167
|
-
// loopback http URIs are allowed for native apps
|
|
168
|
-
if (url.protocol === 'http:' && isLoopbackHost(url.hostname)) {
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// otherwise must be https
|
|
173
|
-
if (url.protocol !== 'https:') {
|
|
174
|
-
return v.err({
|
|
175
|
-
message: `redirect URI must use https:, http: loopback, or private-use scheme`,
|
|
176
|
-
path: ['redirect_uris', i],
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return v.ok(input);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
export type DiscoverablePublicClientMetadata = v.Infer<typeof discoverablePublicClientMetadataSchema>;
|
|
61
|
+
export const discoverablePublicClientMetadataSchema = v.looseObject({
|
|
62
|
+
/** discoverable HTTPS client_id URL */
|
|
63
|
+
client_id: oauthClientIdDiscoverableSchema,
|
|
64
|
+
|
|
65
|
+
/** redirect URIs for authorization responses */
|
|
66
|
+
redirect_uris: redirectUrisSchema,
|
|
67
|
+
|
|
68
|
+
/** OAuth scope (must include "atproto") */
|
|
69
|
+
scope: scopeSchema,
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* application type - defaults to 'web'.
|
|
73
|
+
*/
|
|
74
|
+
application_type: v.optional(v.picklist(['web', 'native'])),
|
|
75
|
+
|
|
76
|
+
/** optional client homepage */
|
|
77
|
+
client_uri: v.optional(webUriSchema),
|
|
78
|
+
/** optional display name */
|
|
79
|
+
client_name: v.optional(v.string()),
|
|
80
|
+
/** optional policy url */
|
|
81
|
+
policy_uri: v.optional(nonLocalWebUriSchema),
|
|
82
|
+
/** optional terms of service url */
|
|
83
|
+
tos_uri: v.optional(nonLocalWebUriSchema),
|
|
84
|
+
/** optional logo url */
|
|
85
|
+
logo_uri: v.optional(nonLocalWebUriSchema),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export type DiscoverablePublicClientMetadata = v.InferOutput<typeof discoverablePublicClientMetadataSchema>;
|
|
185
89
|
|
|
186
90
|
/**
|
|
187
91
|
* user-facing client metadata for configuring a public OAuth client.
|
|
@@ -189,9 +93,9 @@ export type DiscoverablePublicClientMetadata = v.Infer<typeof discoverablePublic
|
|
|
189
93
|
* - if `client_id` is omitted: loopback client (for localhost dev / CLI tools)
|
|
190
94
|
* - if `client_id` is provided: discoverable public client (HTTPS URL)
|
|
191
95
|
*/
|
|
192
|
-
export const publicClientMetadataSchema = v.union(
|
|
96
|
+
export const publicClientMetadataSchema = v.union([
|
|
193
97
|
loopbackClientMetadataSchema,
|
|
194
98
|
discoverablePublicClientMetadataSchema,
|
|
195
|
-
);
|
|
99
|
+
]);
|
|
196
100
|
|
|
197
|
-
export type PublicClientMetadata = v.
|
|
101
|
+
export type PublicClientMetadata = v.InferOutput<typeof publicClientMetadataSchema>;
|
|
@@ -1,32 +1,31 @@
|
|
|
1
|
-
import * as v from '
|
|
1
|
+
import * as v from 'valibot';
|
|
2
2
|
|
|
3
|
-
import { oauthAuthorizationServerMetadataValidator } from './oauth-authorization-server-metadata.
|
|
3
|
+
import { oauthAuthorizationServerMetadataValidator } from './oauth-authorization-server-metadata.ts';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* AT Protocol authorization server metadata with required fields and assertions.
|
|
7
7
|
*
|
|
8
8
|
* @see {@link https://atproto.com/specs/oauth}
|
|
9
9
|
*/
|
|
10
|
-
export const atprotoAuthorizationServerMetadataValidator =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return v.ok(data as typeof data & { pushed_authorization_request_endpoint: string });
|
|
29
|
-
},
|
|
10
|
+
export const atprotoAuthorizationServerMetadataValidator = v.pipe(
|
|
11
|
+
oauthAuthorizationServerMetadataValidator,
|
|
12
|
+
v.forward(
|
|
13
|
+
v.check(
|
|
14
|
+
(data) => data.client_id_metadata_document_supported === true,
|
|
15
|
+
`atproto requires client_id_metadata_document_supported to be true`,
|
|
16
|
+
),
|
|
17
|
+
['client_id_metadata_document_supported'],
|
|
18
|
+
),
|
|
19
|
+
v.forward(
|
|
20
|
+
v.check(
|
|
21
|
+
(data) => !!data.pushed_authorization_request_endpoint,
|
|
22
|
+
`atproto requires pushed_authorization_request_endpoint to be true`,
|
|
23
|
+
),
|
|
24
|
+
['pushed_authorization_request_endpoint'],
|
|
25
|
+
),
|
|
26
|
+
v.transform((data) => data as typeof data & { pushed_authorization_request_endpoint: string }),
|
|
30
27
|
);
|
|
31
28
|
|
|
32
|
-
export type AtprotoAuthorizationServerMetadata = v.
|
|
29
|
+
export type AtprotoAuthorizationServerMetadata = v.InferOutput<
|
|
30
|
+
typeof atprotoAuthorizationServerMetadataValidator
|
|
31
|
+
>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as v from '
|
|
1
|
+
import * as v from 'valibot';
|
|
2
2
|
|
|
3
|
-
import { isOAuthScope } from './oauth-scope.
|
|
4
|
-
import { isSpaceSeparatedValue } from './utils.
|
|
3
|
+
import { isOAuthScope } from './oauth-scope.ts';
|
|
4
|
+
import { isSpaceSeparatedValue } from './utils.ts';
|
|
5
5
|
|
|
6
6
|
export const ATPROTO_SCOPE_VALUE = 'atproto';
|
|
7
7
|
|
|
@@ -10,9 +10,12 @@ const isAtprotoOAuthScope = (input: string): boolean => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
/** atproto OAuth scope (must include "atproto") */
|
|
13
|
-
export const atprotoOAuthScopeSchema = v.
|
|
13
|
+
export const atprotoOAuthScopeSchema = v.pipe(
|
|
14
|
+
v.string(),
|
|
15
|
+
v.check(isAtprotoOAuthScope, `invalid atproto OAuth scope`),
|
|
16
|
+
);
|
|
14
17
|
|
|
15
|
-
export type AtprotoOAuthScope = v.
|
|
18
|
+
export type AtprotoOAuthScope = v.InferOutput<typeof atprotoOAuthScopeSchema>;
|
|
16
19
|
|
|
17
20
|
/** default scope is for reading identity (did) only */
|
|
18
21
|
export const DEFAULT_ATPROTO_OAUTH_SCOPE: AtprotoOAuthScope = ATPROTO_SCOPE_VALUE;
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { isAtprotoDid } from '@atcute/identity';
|
|
2
|
+
import type { Did } from '@atcute/lexicons/syntax';
|
|
2
3
|
|
|
3
|
-
import * as v from '
|
|
4
|
+
import * as v from 'valibot';
|
|
4
5
|
|
|
5
|
-
import { atprotoOAuthScopeSchema } from './atproto-oauth-scope.
|
|
6
|
-
import { oauthAuthorizationDetailsSchema } from './oauth-authorization-details.
|
|
6
|
+
import { atprotoOAuthScopeSchema } from './atproto-oauth-scope.ts';
|
|
7
|
+
import { oauthAuthorizationDetailsSchema } from './oauth-authorization-details.ts';
|
|
7
8
|
|
|
8
|
-
export const atprotoOAuthTokenResponseSchema = v.
|
|
9
|
+
export const atprotoOAuthTokenResponseSchema = v.looseObject({
|
|
9
10
|
access_token: v.string(),
|
|
10
11
|
token_type: v.literal('DPoP'),
|
|
11
|
-
sub: v.
|
|
12
|
+
sub: v.custom<Did>(isAtprotoDid, `must be a did:plc or did:web`),
|
|
12
13
|
scope: atprotoOAuthScopeSchema,
|
|
13
|
-
refresh_token: v.
|
|
14
|
-
expires_in: v.
|
|
14
|
+
refresh_token: v.optional(v.string()),
|
|
15
|
+
expires_in: v.optional(v.number()),
|
|
15
16
|
// https://datatracker.ietf.org/doc/html/rfc9396#name-enriched-authorization-deta
|
|
16
|
-
authorization_details:
|
|
17
|
+
authorization_details: v.optional(oauthAuthorizationDetailsSchema),
|
|
17
18
|
// OpenID is not compatible with atproto identities
|
|
18
19
|
});
|
|
19
20
|
|
|
20
|
-
export type AtprotoOAuthTokenResponse = v.
|
|
21
|
+
export type AtprotoOAuthTokenResponse = v.InferOutput<typeof atprotoOAuthTokenResponseSchema>;
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import * as v from '
|
|
1
|
+
import * as v from 'valibot';
|
|
2
2
|
|
|
3
|
-
import { oauthProtectedResourceMetadataValidator } from './oauth-protected-resource-metadata.
|
|
3
|
+
import { oauthProtectedResourceMetadataValidator } from './oauth-protected-resource-metadata.ts';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* AT Protocol protected resource metadata with required fields.
|
|
7
7
|
*
|
|
8
8
|
* @see {@link https://atproto.com/specs/oauth}
|
|
9
9
|
*/
|
|
10
|
-
export const atprotoProtectedResourceMetadataValidator =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return v.ok(data as typeof data & { authorization_servers: [string] });
|
|
21
|
-
},
|
|
10
|
+
export const atprotoProtectedResourceMetadataValidator = v.pipe(
|
|
11
|
+
oauthProtectedResourceMetadataValidator,
|
|
12
|
+
v.forward(
|
|
13
|
+
v.check(
|
|
14
|
+
(data) => data.authorization_servers?.length === 1,
|
|
15
|
+
`atproto requires exactly one authorization server`,
|
|
16
|
+
),
|
|
17
|
+
['authorization_servers'],
|
|
18
|
+
),
|
|
19
|
+
v.transform((data) => data as typeof data & { authorization_servers: [string] }),
|
|
22
20
|
);
|
|
23
21
|
|
|
24
|
-
export type AtprotoProtectedResourceMetadata = v.
|
|
22
|
+
export type AtprotoProtectedResourceMetadata = v.InferOutput<
|
|
23
|
+
typeof atprotoProtectedResourceMetadataValidator
|
|
24
|
+
>;
|