@atproto/oauth-types 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +44 -0
- package/dist/atproto-loopback-client-metadata.d.ts.map +1 -1
- package/dist/atproto-loopback-client-metadata.js +4 -16
- package/dist/atproto-loopback-client-metadata.js.map +1 -1
- package/dist/constants.d.ts +0 -6
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -17
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +18 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -5
- package/dist/index.js.map +1 -1
- package/dist/oauth-access-token.d.ts +4 -0
- package/dist/oauth-access-token.d.ts.map +1 -0
- package/dist/oauth-access-token.js +6 -0
- package/dist/oauth-access-token.js.map +1 -0
- package/dist/oauth-authorization-code-grant-token-request.d.ts +20 -0
- package/dist/oauth-authorization-code-grant-token-request.d.ts.map +1 -0
- package/dist/oauth-authorization-code-grant-token-request.js +17 -0
- package/dist/oauth-authorization-code-grant-token-request.js.map +1 -0
- package/dist/oauth-authorization-request-jar.d.ts +16 -0
- package/dist/oauth-authorization-request-jar.d.ts.map +1 -0
- package/dist/oauth-authorization-request-jar.js +15 -0
- package/dist/oauth-authorization-request-jar.js.map +1 -0
- package/dist/oauth-authorization-request-par.d.ts +122 -0
- package/dist/oauth-authorization-request-par.d.ts.map +1 -0
- package/dist/oauth-authorization-request-par.js +11 -0
- package/dist/oauth-authorization-request-par.js.map +1 -0
- package/dist/{oauth-authentication-request-parameters.d.ts → oauth-authorization-request-parameters.d.ts} +18 -18
- package/dist/oauth-authorization-request-parameters.d.ts.map +1 -0
- package/dist/{oauth-authentication-request-parameters.js → oauth-authorization-request-parameters.js} +16 -17
- package/dist/oauth-authorization-request-parameters.js.map +1 -0
- package/dist/oauth-authorization-request-query.d.ts +128 -0
- package/dist/oauth-authorization-request-query.d.ts.map +1 -0
- package/dist/oauth-authorization-request-query.js +13 -0
- package/dist/oauth-authorization-request-query.js.map +1 -0
- package/dist/oauth-authorization-request-uri.d.ts +10 -0
- package/dist/oauth-authorization-request-uri.d.ts.map +1 -0
- package/dist/oauth-authorization-request-uri.js +9 -0
- package/dist/oauth-authorization-request-uri.js.map +1 -0
- package/dist/oauth-authorization-server-metadata.d.ts +16 -16
- package/dist/oauth-authorization-server-metadata.d.ts.map +1 -1
- package/dist/oauth-authorization-server-metadata.js +5 -1
- package/dist/oauth-authorization-server-metadata.js.map +1 -1
- package/dist/oauth-client-credentials-grant-token-request.d.ts +10 -0
- package/dist/oauth-client-credentials-grant-token-request.d.ts.map +1 -0
- package/dist/oauth-client-credentials-grant-token-request.js +8 -0
- package/dist/oauth-client-credentials-grant-token-request.js.map +1 -0
- package/dist/oauth-client-credentials.d.ts +18 -2
- package/dist/oauth-client-credentials.d.ts.map +1 -1
- package/dist/oauth-client-credentials.js +8 -2
- package/dist/oauth-client-credentials.js.map +1 -1
- package/dist/oauth-client-id-discoverable.d.ts +3 -2
- package/dist/oauth-client-id-discoverable.d.ts.map +1 -1
- package/dist/oauth-client-id-discoverable.js +22 -20
- package/dist/oauth-client-id-discoverable.js.map +1 -1
- package/dist/oauth-client-id-loopback.d.ts +10 -3
- package/dist/oauth-client-id-loopback.d.ts.map +1 -1
- package/dist/oauth-client-id-loopback.js +59 -23
- package/dist/oauth-client-id-loopback.js.map +1 -1
- package/dist/oauth-client-metadata.d.ts +91 -91
- package/dist/oauth-client-metadata.d.ts.map +1 -1
- package/dist/oauth-client-metadata.js +2 -1
- package/dist/oauth-client-metadata.js.map +1 -1
- package/dist/oauth-code-challenge-method.d.ts +3 -0
- package/dist/oauth-code-challenge-method.d.ts.map +1 -0
- package/dist/oauth-code-challenge-method.js +6 -0
- package/dist/oauth-code-challenge-method.js.map +1 -0
- package/dist/oauth-introspection-response.d.ts +20 -0
- package/dist/oauth-introspection-response.d.ts.map +1 -0
- package/dist/oauth-introspection-response.js +3 -0
- package/dist/oauth-introspection-response.js.map +1 -0
- package/dist/oauth-issuer-identifier.d.ts +2 -1
- package/dist/oauth-issuer-identifier.d.ts.map +1 -1
- package/dist/oauth-issuer-identifier.js +13 -12
- package/dist/oauth-issuer-identifier.js.map +1 -1
- package/dist/oauth-par-response.d.ts +3 -0
- package/dist/oauth-par-response.d.ts.map +1 -1
- package/dist/oauth-par-response.js +1 -0
- package/dist/oauth-par-response.js.map +1 -1
- package/dist/oauth-password-grant-token-request.d.ts +16 -0
- package/dist/oauth-password-grant-token-request.d.ts.map +1 -0
- package/dist/oauth-password-grant-token-request.js +10 -0
- package/dist/oauth-password-grant-token-request.js.map +1 -0
- package/dist/oauth-protected-resource-metadata.d.ts +2 -2
- package/dist/oauth-refresh-token-grant-token-request.d.ts +13 -0
- package/dist/oauth-refresh-token-grant-token-request.d.ts.map +1 -0
- package/dist/oauth-refresh-token-grant-token-request.js +10 -0
- package/dist/oauth-refresh-token-grant-token-request.js.map +1 -0
- package/dist/oauth-refresh-token.d.ts +4 -0
- package/dist/oauth-refresh-token.d.ts.map +1 -0
- package/dist/oauth-refresh-token.js +6 -0
- package/dist/oauth-refresh-token.js.map +1 -0
- package/dist/oauth-request-uri.d.ts +4 -0
- package/dist/oauth-request-uri.d.ts.map +1 -0
- package/dist/oauth-request-uri.js +6 -0
- package/dist/oauth-request-uri.js.map +1 -0
- package/dist/oauth-scope.d.ts +10 -0
- package/dist/oauth-scope.d.ts.map +1 -0
- package/dist/oauth-scope.js +16 -0
- package/dist/oauth-scope.js.map +1 -0
- package/dist/oauth-token-identification.d.ts +13 -0
- package/dist/oauth-token-identification.d.ts.map +1 -0
- package/dist/oauth-token-identification.js +11 -0
- package/dist/oauth-token-identification.js.map +1 -0
- package/dist/oauth-token-request.d.ts +46 -0
- package/dist/oauth-token-request.d.ts.map +1 -0
- package/dist/oauth-token-request.js +15 -0
- package/dist/oauth-token-request.js.map +1 -0
- package/dist/oauth-token-response.d.ts +3 -6
- package/dist/oauth-token-response.d.ts.map +1 -1
- package/dist/oauth-token-response.js +4 -2
- package/dist/oauth-token-response.js.map +1 -1
- package/dist/util.d.ts +2 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +36 -6
- package/dist/util.js.map +1 -1
- package/package.json +2 -2
- package/src/atproto-loopback-client-metadata.ts +7 -20
- package/src/constants.ts +0 -16
- package/src/index.ts +18 -5
- package/src/oauth-access-token.ts +4 -0
- package/src/oauth-authorization-code-grant-token-request.ts +18 -0
- package/src/oauth-authorization-request-jar.ts +16 -0
- package/src/oauth-authorization-request-par.ts +13 -0
- package/src/{oauth-authentication-request-parameters.ts → oauth-authorization-request-parameters.ts} +21 -22
- package/src/oauth-authorization-request-query.ts +15 -0
- package/src/oauth-authorization-request-uri.ts +11 -0
- package/src/oauth-authorization-server-metadata.ts +5 -1
- package/src/oauth-client-credentials-grant-token-request.ts +9 -0
- package/src/oauth-client-credentials.ts +21 -1
- package/src/oauth-client-id-discoverable.ts +29 -26
- package/src/oauth-client-id-loopback.ts +78 -30
- package/src/oauth-client-metadata.ts +2 -1
- package/src/oauth-code-challenge-method.ts +3 -0
- package/src/oauth-introspection-response.ts +23 -0
- package/src/oauth-issuer-identifier.ts +17 -12
- package/src/oauth-par-response.ts +1 -0
- package/src/oauth-password-grant-token-request.ts +11 -0
- package/src/oauth-refresh-token-grant-token-request.ts +11 -0
- package/src/oauth-refresh-token.ts +4 -0
- package/src/oauth-request-uri.ts +5 -0
- package/src/oauth-scope.ts +15 -0
- package/src/oauth-token-identification.ts +12 -0
- package/src/oauth-token-request.ts +14 -0
- package/src/oauth-token-response.ts +4 -2
- package/src/util.ts +41 -1
- package/tsconfig.build.tsbuildinfo +1 -0
- package/dist/access-token.d.ts +0 -4
- package/dist/access-token.d.ts.map +0 -1
- package/dist/access-token.js +0 -6
- package/dist/access-token.js.map +0 -1
- package/dist/oauth-authentication-request-parameters.d.ts.map +0 -1
- package/dist/oauth-authentication-request-parameters.js.map +0 -1
- package/dist/oauth-client-id-url.d.ts +0 -3
- package/dist/oauth-client-id-url.d.ts.map +0 -1
- package/dist/oauth-client-id-url.js +0 -21
- package/dist/oauth-client-id-url.js.map +0 -1
- package/dist/oauth-client-identification.d.ts +0 -31
- package/dist/oauth-client-identification.d.ts.map +0 -1
- package/dist/oauth-client-identification.js +0 -12
- package/dist/oauth-client-identification.js.map +0 -1
- package/src/access-token.ts +0 -4
- package/src/oauth-client-id-url.ts +0 -25
- package/src/oauth-client-identification.ts +0 -14
package/dist/util.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,wBAAgB,
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,WAQ5C;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;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,GAAG,GAAG,GAAG,IAAI,CAMvD;AAED,wBAAgB,cAAc,CAAC,GAAG,KAAA,OAsCjC"}
|
package/dist/util.js
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
4
|
-
|
3
|
+
exports.isHostnameIP = isHostnameIP;
|
4
|
+
exports.isLoopbackHost = isLoopbackHost;
|
5
|
+
exports.isLoopbackUrl = isLoopbackUrl;
|
6
|
+
exports.safeUrl = safeUrl;
|
7
|
+
exports.extractUrlPath = extractUrlPath;
|
8
|
+
function isHostnameIP(hostname) {
|
5
9
|
// IPv4
|
6
10
|
if (hostname.match(/^\d+\.\d+\.\d+\.\d+$/))
|
7
11
|
return true;
|
@@ -10,16 +14,13 @@ function isIP(hostname) {
|
|
10
14
|
return true;
|
11
15
|
return false;
|
12
16
|
}
|
13
|
-
exports.isIP = isIP;
|
14
17
|
function isLoopbackHost(host) {
|
15
18
|
return host === 'localhost' || host === '127.0.0.1' || host === '[::1]';
|
16
19
|
}
|
17
|
-
exports.isLoopbackHost = isLoopbackHost;
|
18
20
|
function isLoopbackUrl(input) {
|
19
21
|
const url = typeof input === 'string' ? new URL(input) : input;
|
20
22
|
return isLoopbackHost(url.hostname);
|
21
23
|
}
|
22
|
-
exports.isLoopbackUrl = isLoopbackUrl;
|
23
24
|
function safeUrl(input) {
|
24
25
|
try {
|
25
26
|
return new URL(input);
|
@@ -28,5 +29,34 @@ function safeUrl(input) {
|
|
28
29
|
return null;
|
29
30
|
}
|
30
31
|
}
|
31
|
-
|
32
|
+
function extractUrlPath(url) {
|
33
|
+
// Extracts the path from a URL, without relying on the URL constructor
|
34
|
+
// (because it normalizes the URL)
|
35
|
+
const endOfProtocol = url.startsWith('https://')
|
36
|
+
? 8
|
37
|
+
: url.startsWith('http://')
|
38
|
+
? 7
|
39
|
+
: -1;
|
40
|
+
if (endOfProtocol === -1) {
|
41
|
+
throw new TypeError('URL must use the "https:" or "http:" protocol');
|
42
|
+
}
|
43
|
+
const hashIdx = url.indexOf('#', endOfProtocol);
|
44
|
+
const questionIdx = url.indexOf('?', endOfProtocol);
|
45
|
+
const queryStrIdx = questionIdx !== -1 && (hashIdx === -1 || questionIdx < hashIdx)
|
46
|
+
? questionIdx
|
47
|
+
: -1;
|
48
|
+
const pathEnd = hashIdx === -1
|
49
|
+
? queryStrIdx === -1
|
50
|
+
? url.length
|
51
|
+
: queryStrIdx
|
52
|
+
: queryStrIdx === -1
|
53
|
+
? hashIdx
|
54
|
+
: Math.min(hashIdx, queryStrIdx);
|
55
|
+
const slashIdx = url.indexOf('/', endOfProtocol);
|
56
|
+
const pathStart = slashIdx === -1 || slashIdx > pathEnd ? pathEnd : slashIdx;
|
57
|
+
if (endOfProtocol === pathStart) {
|
58
|
+
throw new TypeError('URL must contain a host');
|
59
|
+
}
|
60
|
+
return url.substring(pathStart, pathEnd);
|
61
|
+
}
|
32
62
|
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAAA,oCAQC;AAID,wCAEC;AAED,sCAGC;AAED,0BAMC;AAED,wCAsCC;AAnED,SAAgB,YAAY,CAAC,QAAgB;IAC3C,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;AAID,SAAgB,cAAc,CAAC,IAAa;IAC1C,OAAO,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,OAAO,CAAA;AACzE,CAAC;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;AAED,SAAgB,OAAO,CAAC,KAAmB;IACzC,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,SAAgB,cAAc,CAAC,GAAG;IAChC,uEAAuE;IACvE,kCAAkC;IAClC,MAAM,aAAa,GAAG,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC;QAC9C,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;YACzB,CAAC,CAAC,CAAC;YACH,CAAC,CAAC,CAAC,CAAC,CAAA;IACR,IAAI,aAAa,KAAK,CAAC,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC,CAAA;IACtE,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,CAAA;IAC/C,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,CAAA;IAEnD,MAAM,WAAW,GACf,WAAW,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,CAAC,IAAI,WAAW,GAAG,OAAO,CAAC;QAC7D,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,CAAC,CAAC,CAAA;IAER,MAAM,OAAO,GACX,OAAO,KAAK,CAAC,CAAC;QACZ,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC;YAClB,CAAC,CAAC,GAAG,CAAC,MAAM;YACZ,CAAC,CAAC,WAAW;QACf,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC;YAClB,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;IAEtC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,CAAA;IAEhD,MAAM,SAAS,GAAG,QAAQ,KAAK,CAAC,CAAC,IAAI,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAA;IAE5E,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,IAAI,SAAS,CAAC,yBAAyB,CAAC,CAAA;IAChD,CAAC;IAED,OAAO,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;AAC1C,CAAC"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@atproto/oauth-types",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.2.0",
|
4
4
|
"license": "MIT",
|
5
5
|
"description": "OAuth typing & validation library",
|
6
6
|
"keywords": [
|
@@ -29,7 +29,7 @@
|
|
29
29
|
"@atproto/jwk": "0.1.1"
|
30
30
|
},
|
31
31
|
"devDependencies": {
|
32
|
-
"typescript": "^5.
|
32
|
+
"typescript": "^5.6.3"
|
33
33
|
},
|
34
34
|
"scripts": {
|
35
35
|
"build": "tsc --build tsconfig.build.json"
|
@@ -1,34 +1,21 @@
|
|
1
|
-
import {
|
1
|
+
import { parseOAuthLoopbackClientId } from './oauth-client-id-loopback.js'
|
2
2
|
import { OAuthClientMetadataInput } from './oauth-client-metadata.js'
|
3
|
-
import { parseOAuthClientIdUrl } from './oauth-client-id-url.js'
|
4
3
|
|
5
4
|
export function atprotoLoopbackClientMetadata(
|
6
5
|
clientId: string,
|
7
6
|
): OAuthClientMetadataInput {
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
const { origin, pathname, searchParams } = parseOAuthClientIdUrl(clientId)
|
13
|
-
|
14
|
-
for (const name of searchParams.keys()) {
|
15
|
-
if (name !== 'redirect_uri') {
|
16
|
-
throw new TypeError(`Invalid query parameter ${name} in client ID`)
|
17
|
-
}
|
18
|
-
}
|
19
|
-
const redirectUris = searchParams.getAll('redirect_uri')
|
7
|
+
const {
|
8
|
+
scope = 'atproto',
|
9
|
+
redirect_uris = [`http://127.0.0.1/`, `http://[::1]/`],
|
10
|
+
} = parseOAuthLoopbackClientId(clientId)
|
20
11
|
|
21
12
|
return {
|
22
13
|
client_id: clientId,
|
14
|
+
scope,
|
15
|
+
redirect_uris,
|
23
16
|
client_name: 'Loopback client',
|
24
17
|
response_types: ['code'],
|
25
18
|
grant_types: ['authorization_code', 'refresh_token'],
|
26
|
-
redirect_uris: (redirectUris.length
|
27
|
-
? redirectUris
|
28
|
-
: (['127.0.0.1', '[::1]'] as const).map(
|
29
|
-
(ip) =>
|
30
|
-
Object.assign(new URL(pathname, origin), { hostname: ip }).href,
|
31
|
-
)) as [string, ...string[]],
|
32
19
|
token_endpoint_auth_method: 'none',
|
33
20
|
application_type: 'native',
|
34
21
|
dpop_bound_access_tokens: true,
|
package/src/constants.ts
CHANGED
@@ -1,18 +1,2 @@
|
|
1
|
-
/**
|
2
|
-
* A variable that allows to determine if unsecure origins should be allowed
|
3
|
-
* in OAuth related URI's. This variable is only set to `true` when NODE_ENV
|
4
|
-
* is either `development` or `test`.
|
5
|
-
*/
|
6
|
-
export const ALLOW_UNSECURE_ORIGINS = (() => {
|
7
|
-
// try/catch to support running in a browser, including when process.env is
|
8
|
-
// shimmed (e.g. by webpack)
|
9
|
-
try {
|
10
|
-
const env = process.env.NODE_ENV
|
11
|
-
return env === 'development' || env === 'test'
|
12
|
-
} catch {
|
13
|
-
return false
|
14
|
-
}
|
15
|
-
})()
|
16
|
-
|
17
1
|
export const CLIENT_ASSERTION_TYPE_JWT_BEARER =
|
18
2
|
'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
|
package/src/index.ts
CHANGED
@@ -1,25 +1,38 @@
|
|
1
1
|
export * from './constants.js'
|
2
2
|
export * from './util.js'
|
3
3
|
|
4
|
-
export * from './access-token.js'
|
5
4
|
export * from './atproto-loopback-client-metadata.js'
|
6
|
-
export * from './oauth-
|
7
|
-
export * from './oauth-
|
8
|
-
export * from './oauth-authentication-request-parameters.js'
|
5
|
+
export * from './oauth-access-token.js'
|
6
|
+
export * from './oauth-authorization-code-grant-token-request.js'
|
9
7
|
export * from './oauth-authorization-details.js'
|
8
|
+
export * from './oauth-authorization-request-jar.js'
|
9
|
+
export * from './oauth-authorization-request-par.js'
|
10
|
+
export * from './oauth-authorization-request-parameters.js'
|
11
|
+
export * from './oauth-authorization-request-query.js'
|
12
|
+
export * from './oauth-authorization-request-uri.js'
|
10
13
|
export * from './oauth-authorization-server-metadata.js'
|
14
|
+
export * from './oauth-client-credentials-grant-token-request.js'
|
11
15
|
export * from './oauth-client-credentials.js'
|
16
|
+
export * from './oauth-client-id-discoverable.js'
|
17
|
+
export * from './oauth-client-id-loopback.js'
|
12
18
|
export * from './oauth-client-id.js'
|
13
|
-
export * from './oauth-client-identification.js'
|
14
19
|
export * from './oauth-client-metadata.js'
|
15
20
|
export * from './oauth-endpoint-auth-method.js'
|
16
21
|
export * from './oauth-endpoint-name.js'
|
17
22
|
export * from './oauth-grant-type.js'
|
23
|
+
export * from './oauth-introspection-response.js'
|
18
24
|
export * from './oauth-issuer-identifier.js'
|
19
25
|
export * from './oauth-par-response.js'
|
26
|
+
export * from './oauth-password-grant-token-request.js'
|
20
27
|
export * from './oauth-protected-resource-metadata.js'
|
28
|
+
export * from './oauth-refresh-token-grant-token-request.js'
|
29
|
+
export * from './oauth-refresh-token.js'
|
30
|
+
export * from './oauth-request-uri.js'
|
21
31
|
export * from './oauth-response-mode.js'
|
22
32
|
export * from './oauth-response-type.js'
|
33
|
+
export * from './oauth-scope.js'
|
34
|
+
export * from './oauth-token-identification.js'
|
35
|
+
export * from './oauth-token-request.js'
|
23
36
|
export * from './oauth-token-response.js'
|
24
37
|
export * from './oauth-token-type.js'
|
25
38
|
export * from './oidc-claims-parameter.js'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { z } from 'zod'
|
2
|
+
|
3
|
+
export const oauthAuthorizationCodeGrantTokenRequestSchema = z.object({
|
4
|
+
grant_type: z.literal('authorization_code'),
|
5
|
+
code: z.string().min(1),
|
6
|
+
redirect_uri: z.string().url(),
|
7
|
+
/** @see {@link https://datatracker.ietf.org/doc/html/rfc7636#section-4.1} */
|
8
|
+
code_verifier: z
|
9
|
+
.string()
|
10
|
+
.min(43)
|
11
|
+
.max(128)
|
12
|
+
.regex(/^[a-zA-Z0-9-._~]+$/)
|
13
|
+
.optional(),
|
14
|
+
})
|
15
|
+
|
16
|
+
export type OAuthAuthorizationCodeGrantTokenRequest = z.infer<
|
17
|
+
typeof oauthAuthorizationCodeGrantTokenRequestSchema
|
18
|
+
>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { signedJwtSchema, unsignedJwtSchema } from '@atproto/jwk'
|
2
|
+
import { z } from 'zod'
|
3
|
+
|
4
|
+
export const oauthAuthorizationRequestJarSchema = z.object({
|
5
|
+
/**
|
6
|
+
* AuthorizationRequest inside a JWT:
|
7
|
+
* - "iat" is required and **MUST** be less than one minute
|
8
|
+
*
|
9
|
+
* @see {@link https://datatracker.ietf.org/doc/html/rfc9101}
|
10
|
+
*/
|
11
|
+
request: z.union([signedJwtSchema, unsignedJwtSchema]),
|
12
|
+
})
|
13
|
+
|
14
|
+
export type OAuthAuthorizationRequestJar = z.infer<
|
15
|
+
typeof oauthAuthorizationRequestJarSchema
|
16
|
+
>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { z } from 'zod'
|
2
|
+
|
3
|
+
import { oauthAuthorizationRequestJarSchema } from './oauth-authorization-request-jar.js'
|
4
|
+
import { oauthAuthorizationRequestParametersSchema } from './oauth-authorization-request-parameters.js'
|
5
|
+
|
6
|
+
export const oauthAuthorizationRequestParSchema = z.union([
|
7
|
+
oauthAuthorizationRequestParametersSchema,
|
8
|
+
oauthAuthorizationRequestJarSchema,
|
9
|
+
])
|
10
|
+
|
11
|
+
export type OAuthAuthorizationRequestPar = z.infer<
|
12
|
+
typeof oauthAuthorizationRequestParSchema
|
13
|
+
>
|
package/src/{oauth-authentication-request-parameters.ts → oauth-authorization-request-parameters.ts}
RENAMED
@@ -3,7 +3,9 @@ import { z } from 'zod'
|
|
3
3
|
|
4
4
|
import { oauthAuthorizationDetailsSchema } from './oauth-authorization-details.js'
|
5
5
|
import { oauthClientIdSchema } from './oauth-client-id.js'
|
6
|
+
import { oauthCodeChallengeMethodSchema } from './oauth-code-challenge-method.js'
|
6
7
|
import { oauthResponseTypeSchema } from './oauth-response-type.js'
|
8
|
+
import { oauthScopeSchema } from './oauth-scope.js'
|
7
9
|
import { oidcClaimsParameterSchema } from './oidc-claims-parameter.js'
|
8
10
|
import { oidcClaimsPropertiesSchema } from './oidc-claims-properties.js'
|
9
11
|
import { oidcEntityTypeSchema } from './oidc-entity-type.js'
|
@@ -11,35 +13,32 @@ import { oidcEntityTypeSchema } from './oidc-entity-type.js'
|
|
11
13
|
/**
|
12
14
|
* @see {@link https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest | OIDC}
|
13
15
|
*/
|
14
|
-
export const
|
16
|
+
export const oauthAuthorizationRequestParametersSchema = z.object({
|
15
17
|
client_id: oauthClientIdSchema,
|
16
|
-
|
17
18
|
state: z.string().optional(),
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
redirect_uri: z.string().url().optional(),
|
20
|
+
scope: oauthScopeSchema.optional(),
|
21
21
|
response_type: oauthResponseTypeSchema,
|
22
22
|
|
23
|
-
// Default depend on response_type
|
24
|
-
response_mode: z.enum(['query', 'fragment', 'form_post']).optional(),
|
25
|
-
|
26
23
|
// PKCE
|
24
|
+
|
27
25
|
code_challenge: z.string().optional(),
|
28
|
-
code_challenge_method:
|
26
|
+
code_challenge_method: oauthCodeChallengeMethodSchema
|
27
|
+
.default('S256')
|
28
|
+
.optional(),
|
29
29
|
|
30
|
-
|
30
|
+
// DPOP
|
31
31
|
|
32
|
-
// https://datatracker.ietf.org/doc/html/
|
33
|
-
|
34
|
-
// scope-token = 1*( %x21 / %x23-5B / %x5D-7E )
|
35
|
-
// = Basically most ASCII characters except backslash and double quote
|
36
|
-
scope: z
|
37
|
-
.string()
|
38
|
-
.regex(/^[!\x23-\x5B\x5D-\x7E]+( [!\x23-\x5B\x5D-\x7E]+)*$/)
|
39
|
-
.optional(),
|
32
|
+
// https://datatracker.ietf.org/doc/html/rfc9449#section-12.3
|
33
|
+
dpop_jkt: z.string().optional(),
|
40
34
|
|
41
35
|
// OIDC
|
42
36
|
|
37
|
+
// Default depend on response_type
|
38
|
+
response_mode: z.enum(['query', 'fragment', 'form_post']).optional(),
|
39
|
+
|
40
|
+
nonce: z.string().optional(),
|
41
|
+
|
43
42
|
// Specifies the allowable elapsed time in seconds since the last time the
|
44
43
|
// End-User was actively authenticated by the OP. If the elapsed time is
|
45
44
|
// greater than this value, the OP MUST attempt to actively re-authenticate
|
@@ -74,7 +73,7 @@ export const oauthAuthenticationRequestParametersSchema = z.object({
|
|
74
73
|
id_token_hint: signedJwtSchema.optional(),
|
75
74
|
|
76
75
|
// Type of UI the AS is displayed on
|
77
|
-
display: z.enum(['page', 'popup', 'touch']).optional(),
|
76
|
+
display: z.enum(['page', 'popup', 'touch', 'wap']).optional(),
|
78
77
|
|
79
78
|
/**
|
80
79
|
* - "none" will only be allowed if the user already allowed the client on the same device
|
@@ -89,8 +88,8 @@ export const oauthAuthenticationRequestParametersSchema = z.object({
|
|
89
88
|
})
|
90
89
|
|
91
90
|
/**
|
92
|
-
* @see {
|
91
|
+
* @see {oauthAuthorizationRequestParametersSchema}
|
93
92
|
*/
|
94
|
-
export type
|
95
|
-
typeof
|
93
|
+
export type OAuthAuthorizationRequestParameters = z.infer<
|
94
|
+
typeof oauthAuthorizationRequestParametersSchema
|
96
95
|
>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { z } from 'zod'
|
2
|
+
|
3
|
+
import { oauthAuthorizationRequestJarSchema } from './oauth-authorization-request-jar.js'
|
4
|
+
import { oauthAuthorizationRequestParametersSchema } from './oauth-authorization-request-parameters.js'
|
5
|
+
import { oauthAuthorizationRequestUriSchema } from './oauth-authorization-request-uri.js'
|
6
|
+
|
7
|
+
export const oauthAuthorizationRequestQuerySchema = z.union([
|
8
|
+
oauthAuthorizationRequestParametersSchema,
|
9
|
+
oauthAuthorizationRequestJarSchema,
|
10
|
+
oauthAuthorizationRequestUriSchema,
|
11
|
+
])
|
12
|
+
|
13
|
+
export type OAuthAuthorizationRequestQuery = z.infer<
|
14
|
+
typeof oauthAuthorizationRequestQuerySchema
|
15
|
+
>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { z } from 'zod'
|
2
|
+
|
3
|
+
import { oauthRequestUriSchema } from './oauth-request-uri.js'
|
4
|
+
|
5
|
+
export const oauthAuthorizationRequestUriSchema = z.object({
|
6
|
+
request_uri: oauthRequestUriSchema,
|
7
|
+
})
|
8
|
+
|
9
|
+
export type OAuthAuthorizationRequestUri = z.infer<
|
10
|
+
typeof oauthAuthorizationRequestUriSchema
|
11
|
+
>
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { z } from 'zod'
|
2
2
|
|
3
|
+
import { oauthCodeChallengeMethodSchema } from './oauth-code-challenge-method.js'
|
3
4
|
import { oauthIssuerIdentifierSchema } from './oauth-issuer-identifier.js'
|
4
5
|
|
5
6
|
/**
|
@@ -19,7 +20,10 @@ export const oauthAuthorizationServerMetadataSchema = z.object({
|
|
19
20
|
response_types_supported: z.array(z.string()).optional(),
|
20
21
|
response_modes_supported: z.array(z.string()).optional(),
|
21
22
|
grant_types_supported: z.array(z.string()).optional(),
|
22
|
-
code_challenge_methods_supported: z
|
23
|
+
code_challenge_methods_supported: z
|
24
|
+
.array(oauthCodeChallengeMethodSchema)
|
25
|
+
.min(1)
|
26
|
+
.optional(),
|
23
27
|
ui_locales_supported: z.array(z.string()).optional(),
|
24
28
|
id_token_signing_alg_values_supported: z.array(z.string()).optional(),
|
25
29
|
display_values_supported: z.array(z.string()).optional(),
|
@@ -0,0 +1,9 @@
|
|
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
|
+
>
|
@@ -14,19 +14,39 @@ export const oauthClientCredentialsJwtBearerSchema = z.object({
|
|
14
14
|
* - The JWT MAY contain a "jti" (JWT ID) claim that provides a unique identifier for the token.
|
15
15
|
* - Note that the authorization server may reject JWTs with an "exp" claim value that is unreasonably far in the future.
|
16
16
|
*
|
17
|
-
* @see {@link https://datatracker.ietf.org/doc/html/
|
17
|
+
* @see {@link https://datatracker.ietf.org/doc/html/rfc7523#section-3}
|
18
18
|
*/
|
19
19
|
client_assertion: signedJwtSchema,
|
20
20
|
})
|
21
21
|
|
22
|
+
export type OAuthClientCredentialsJwtBearer = z.infer<
|
23
|
+
typeof oauthClientCredentialsJwtBearerSchema
|
24
|
+
>
|
25
|
+
|
22
26
|
export const oauthClientCredentialsSecretPostSchema = z.object({
|
23
27
|
client_id: oauthClientIdSchema,
|
24
28
|
client_secret: z.string(),
|
25
29
|
})
|
26
30
|
|
31
|
+
export type OAuthClientCredentialsSecretPost = z.infer<
|
32
|
+
typeof oauthClientCredentialsSecretPostSchema
|
33
|
+
>
|
34
|
+
|
35
|
+
export const oauthClientCredentialsNoneSchema = z.object({
|
36
|
+
client_id: oauthClientIdSchema,
|
37
|
+
})
|
38
|
+
|
39
|
+
export type OAuthClientCredentialsNone = z.infer<
|
40
|
+
typeof oauthClientCredentialsNoneSchema
|
41
|
+
>
|
42
|
+
|
43
|
+
//
|
44
|
+
|
27
45
|
export const oauthClientCredentialsSchema = z.union([
|
28
46
|
oauthClientCredentialsJwtBearerSchema,
|
29
47
|
oauthClientCredentialsSecretPostSchema,
|
48
|
+
// Must be last since it is less specific
|
49
|
+
oauthClientCredentialsNoneSchema,
|
30
50
|
])
|
31
51
|
|
32
52
|
export type OAuthClientCredentials = z.infer<
|
@@ -1,15 +1,14 @@
|
|
1
|
-
import { parseOAuthClientIdUrl } from './oauth-client-id-url.js'
|
2
1
|
import { OAuthClientId } from './oauth-client-id.js'
|
3
|
-
import {
|
2
|
+
import { extractUrlPath, isHostnameIP } from './util.js'
|
4
3
|
|
5
4
|
/**
|
6
5
|
* @see {@link https://drafts.aaronpk.com/draft-parecki-oauth-client-id-metadata-document/draft-parecki-oauth-client-id-metadata-document.html}
|
7
6
|
*/
|
8
7
|
export type OAuthClientIdDiscoverable = OAuthClientId & `https://${string}`
|
9
8
|
|
10
|
-
export function isOAuthClientIdDiscoverable
|
11
|
-
clientId:
|
12
|
-
): clientId is
|
9
|
+
export function isOAuthClientIdDiscoverable(
|
10
|
+
clientId: string,
|
11
|
+
): clientId is OAuthClientIdDiscoverable {
|
13
12
|
try {
|
14
13
|
parseOAuthDiscoverableClientId(clientId)
|
15
14
|
return true
|
@@ -18,48 +17,52 @@ export function isOAuthClientIdDiscoverable<C extends OAuthClientId>(
|
|
18
17
|
}
|
19
18
|
}
|
20
19
|
|
21
|
-
export function
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
export function assertOAuthDiscoverableClientId(
|
21
|
+
value: string,
|
22
|
+
): asserts value is OAuthClientIdDiscoverable {
|
23
|
+
void parseOAuthDiscoverableClientId(value)
|
24
|
+
}
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
}
|
26
|
+
export function parseOAuthDiscoverableClientId(clientId: string): URL {
|
27
|
+
const url = new URL(clientId)
|
29
28
|
|
30
29
|
if (url.protocol !== 'https:') {
|
31
30
|
throw new TypeError('ClientID must use the "https:" protocol')
|
32
31
|
}
|
33
32
|
|
33
|
+
if (url.username || url.password) {
|
34
|
+
throw new TypeError('ClientID must not contain credentials')
|
35
|
+
}
|
36
|
+
|
34
37
|
if (url.hash) {
|
35
38
|
throw new TypeError('ClientID must not contain a fragment')
|
36
39
|
}
|
37
40
|
|
38
|
-
if (url.
|
39
|
-
throw new TypeError('ClientID must not
|
41
|
+
if (url.hostname === 'localhost') {
|
42
|
+
throw new TypeError('ClientID hostname must not be "localhost"')
|
40
43
|
}
|
41
44
|
|
42
45
|
if (url.pathname === '/') {
|
43
46
|
throw new TypeError(
|
44
|
-
'ClientID must contain a path (e.g. "/client-metadata")',
|
47
|
+
'ClientID must contain a path component (e.g. "/client-metadata.json")',
|
45
48
|
)
|
46
49
|
}
|
47
50
|
|
48
|
-
if (url.pathname
|
49
|
-
throw new TypeError('ClientID must not end with a trailing slash')
|
51
|
+
if (url.pathname.endsWith('/')) {
|
52
|
+
throw new TypeError('ClientID path must not end with a trailing slash')
|
50
53
|
}
|
51
54
|
|
52
|
-
if (url.
|
53
|
-
throw new TypeError(
|
54
|
-
`ClientID must not contain any double slashes in its path`,
|
55
|
-
)
|
55
|
+
if (isHostnameIP(url.hostname)) {
|
56
|
+
throw new TypeError('ClientID hostname must not be an IP address')
|
56
57
|
}
|
57
58
|
|
58
|
-
//
|
59
|
-
//
|
60
|
-
|
61
|
-
if (
|
62
|
-
throw new TypeError(
|
59
|
+
// URL constructor normalizes the URL, so we extract the path manually to
|
60
|
+
// avoid normalization, then compare it to the normalized path to ensure
|
61
|
+
// that the URL does not contain path traversal or other unexpected characters
|
62
|
+
if (extractUrlPath(clientId) !== url.pathname) {
|
63
|
+
throw new TypeError(
|
64
|
+
`ClientID must be in canonical form ("${url.href}", got "${clientId}")`,
|
65
|
+
)
|
63
66
|
}
|
64
67
|
|
65
68
|
return url
|