@atproto/oauth-types 0.1.1 → 0.1.2-rc.1
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/dist/atproto-loopback-client-metadata.d.ts.map +1 -1
- package/dist/atproto-loopback-client-metadata.js +9 -3
- package/dist/atproto-loopback-client-metadata.js.map +1 -1
- package/dist/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +17 -1
- package/dist/constants.js.map +1 -1
- package/dist/oauth-issuer-identifier.d.ts.map +1 -1
- package/dist/oauth-issuer-identifier.js +10 -14
- package/dist/oauth-issuer-identifier.js.map +1 -1
- package/dist/util.d.ts +1 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +10 -1
- package/dist/util.js.map +1 -1
- package/package.json +1 -1
- package/src/atproto-loopback-client-metadata.ts +11 -4
- package/src/constants.ts +16 -0
- package/src/oauth-issuer-identifier.ts +10 -14
- package/src/util.ts +8 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atproto-loopback-client-metadata.d.ts","sourceRoot":"","sources":["../src/atproto-loopback-client-metadata.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AAGrE,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,GACf,wBAAwB,
|
|
1
|
+
{"version":3,"file":"atproto-loopback-client-metadata.d.ts","sourceRoot":"","sources":["../src/atproto-loopback-client-metadata.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AAGrE,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,GACf,wBAAwB,CA8B1B"}
|
|
@@ -8,15 +8,21 @@ function atprotoLoopbackClientMetadata(clientId) {
|
|
|
8
8
|
throw new TypeError(`Invalid loopback client ID ${clientId}`);
|
|
9
9
|
}
|
|
10
10
|
const { origin, pathname, searchParams } = (0, oauth_client_id_url_js_1.parseOAuthClientIdUrl)(clientId);
|
|
11
|
+
for (const name of searchParams.keys()) {
|
|
12
|
+
if (name !== 'redirect_uri') {
|
|
13
|
+
throw new TypeError(`Invalid query parameter ${name} in client ID`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const redirectUris = searchParams.getAll('redirect_uri');
|
|
11
17
|
return {
|
|
12
18
|
client_id: clientId,
|
|
13
19
|
client_name: 'Loopback client',
|
|
14
20
|
response_types: ['code id_token', 'code'],
|
|
15
21
|
grant_types: ['authorization_code', 'implicit', 'refresh_token'],
|
|
16
22
|
scope: 'openid profile offline_access',
|
|
17
|
-
redirect_uris:
|
|
18
|
-
?
|
|
19
|
-
: ['127.0.0.1', '[::1]'].map((ip) => Object.assign(new URL(pathname, origin), { hostname: ip }).href),
|
|
23
|
+
redirect_uris: (redirectUris.length
|
|
24
|
+
? redirectUris
|
|
25
|
+
: ['127.0.0.1', '[::1]'].map((ip) => Object.assign(new URL(pathname, origin), { hostname: ip }).href)),
|
|
20
26
|
token_endpoint_auth_method: 'none',
|
|
21
27
|
application_type: 'native',
|
|
22
28
|
dpop_bound_access_tokens: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atproto-loopback-client-metadata.js","sourceRoot":"","sources":["../src/atproto-loopback-client-metadata.ts"],"names":[],"mappings":";;;AAAA,+EAAuE;AAEvE,qEAAgE;AAEhE,SAAgB,6BAA6B,CAC3C,QAAgB;IAEhB,IAAI,CAAC,IAAA,qDAAuB,EAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,SAAS,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAA;IAC/D,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAA,8CAAqB,EAAC,QAAQ,CAAC,CAAA;IAE1E,OAAO;QACL,SAAS,EAAE,QAAQ;QACnB,WAAW,EAAE,iBAAiB;QAC9B,cAAc,EAAE,CAAC,eAAe,EAAE,MAAM,CAAC;QACzC,WAAW,EAAE,CAAC,oBAAoB,EAAE,UAAU,EAAE,eAAe,CAAC;QAChE,KAAK,EAAE,+BAA+B;QACtC,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"atproto-loopback-client-metadata.js","sourceRoot":"","sources":["../src/atproto-loopback-client-metadata.ts"],"names":[],"mappings":";;;AAAA,+EAAuE;AAEvE,qEAAgE;AAEhE,SAAgB,6BAA6B,CAC3C,QAAgB;IAEhB,IAAI,CAAC,IAAA,qDAAuB,EAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,SAAS,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAA;IAC/D,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAA,8CAAqB,EAAC,QAAQ,CAAC,CAAA;IAE1E,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;YAC5B,MAAM,IAAI,SAAS,CAAC,2BAA2B,IAAI,eAAe,CAAC,CAAA;QACrE,CAAC;IACH,CAAC;IACD,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;IAExD,OAAO;QACL,SAAS,EAAE,QAAQ;QACnB,WAAW,EAAE,iBAAiB;QAC9B,cAAc,EAAE,CAAC,eAAe,EAAE,MAAM,CAAC;QACzC,WAAW,EAAE,CAAC,oBAAoB,EAAE,UAAU,EAAE,eAAe,CAAC;QAChE,KAAK,EAAE,+BAA+B;QACtC,aAAa,EAAE,CAAC,YAAY,CAAC,MAAM;YACjC,CAAC,CAAC,YAAY;YACd,CAAC,CAAE,CAAC,WAAW,EAAE,OAAO,CAAW,CAAC,GAAG,CACnC,CAAC,EAAE,EAAE,EAAE,CACL,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAClE,CAA0B;QAC/B,0BAA0B,EAAE,MAAM;QAClC,gBAAgB,EAAE,QAAQ;QAC1B,wBAAwB,EAAE,IAAI;KAC/B,CAAA;AACH,CAAC;AAhCD,sEAgCC"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
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 declare const ALLOW_UNSECURE_ORIGINS: boolean;
|
|
1
7
|
export declare const CLIENT_ASSERTION_TYPE_JWT_BEARER = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
|
|
2
8
|
export declare const OAUTH_AUTHENTICATED_ENDPOINT_NAMES: readonly ["token", "revocation", "introspection", "pushed_authorization_request"];
|
|
3
9
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gCAAgC,2DACa,CAAA;AAE1D,eAAO,MAAM,kCAAkC,mFAKrC,CAAA"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,SAS/B,CAAA;AAEJ,eAAO,MAAM,gCAAgC,2DACa,CAAA;AAE1D,eAAO,MAAM,kCAAkC,mFAKrC,CAAA"}
|
package/dist/constants.js
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OAUTH_AUTHENTICATED_ENDPOINT_NAMES = exports.CLIENT_ASSERTION_TYPE_JWT_BEARER = void 0;
|
|
3
|
+
exports.OAUTH_AUTHENTICATED_ENDPOINT_NAMES = exports.CLIENT_ASSERTION_TYPE_JWT_BEARER = exports.ALLOW_UNSECURE_ORIGINS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* A variable that allows to determine if unsecure origins should be allowed
|
|
6
|
+
* in OAuth related URI's. This variable is only set to `true` when NODE_ENV
|
|
7
|
+
* is either `development` or `test`.
|
|
8
|
+
*/
|
|
9
|
+
exports.ALLOW_UNSECURE_ORIGINS = (() => {
|
|
10
|
+
// try/catch to support running in a browser, including when process.env is
|
|
11
|
+
// shimmed (e.g. by webpack)
|
|
12
|
+
try {
|
|
13
|
+
const env = process.env.NODE_ENV;
|
|
14
|
+
return env === 'development' || env === 'test';
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
})();
|
|
4
20
|
exports.CLIENT_ASSERTION_TYPE_JWT_BEARER = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer';
|
|
5
21
|
exports.OAUTH_AUTHENTICATED_ENDPOINT_NAMES = [
|
|
6
22
|
'token',
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACU,QAAA,sBAAsB,GAAG,CAAC,GAAG,EAAE;IAC1C,2EAA2E;IAC3E,4BAA4B;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAA;QAChC,OAAO,GAAG,KAAK,aAAa,IAAI,GAAG,KAAK,MAAM,CAAA;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC,CAAC,EAAE,CAAA;AAES,QAAA,gCAAgC,GAC3C,wDAAwD,CAAA;AAE7C,QAAA,kCAAkC,GAAG;IAChD,OAAO;IACP,YAAY;IACZ,eAAe;IACf,8BAA8B;CACtB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-issuer-identifier.d.ts","sourceRoot":"","sources":["../src/oauth-issuer-identifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"oauth-issuer-identifier.d.ts","sourceRoot":"","sources":["../src/oauth-issuer-identifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,eAAO,MAAM,2BAA2B,2CAoDpC,CAAA"}
|
|
@@ -2,20 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.oauthIssuerIdentifierSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const ALLOW_INSECURE = (() => {
|
|
8
|
-
try {
|
|
9
|
-
const env = process.env.NODE_ENV;
|
|
10
|
-
return env === 'development' || env === 'test';
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
})();
|
|
5
|
+
const constants_js_1 = require("./constants.js");
|
|
6
|
+
const util_js_1 = require("./util.js");
|
|
16
7
|
exports.oauthIssuerIdentifierSchema = zod_1.z
|
|
17
8
|
.string()
|
|
18
|
-
.url()
|
|
19
9
|
.superRefine((value, ctx) => {
|
|
20
10
|
// Validate the issuer (MIX-UP attacks)
|
|
21
11
|
if (value.endsWith('/')) {
|
|
@@ -24,9 +14,15 @@ exports.oauthIssuerIdentifierSchema = zod_1.z
|
|
|
24
14
|
message: 'Issuer URL must not end with a slash',
|
|
25
15
|
});
|
|
26
16
|
}
|
|
27
|
-
const url =
|
|
17
|
+
const url = (0, util_js_1.safeUrl)(value);
|
|
18
|
+
if (!url) {
|
|
19
|
+
return ctx.addIssue({
|
|
20
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
21
|
+
message: 'Invalid url',
|
|
22
|
+
});
|
|
23
|
+
}
|
|
28
24
|
if (url.protocol !== 'https:') {
|
|
29
|
-
if (
|
|
25
|
+
if (constants_js_1.ALLOW_UNSECURE_ORIGINS && url.protocol === 'http:') {
|
|
30
26
|
// We'll allow HTTP in development mode
|
|
31
27
|
}
|
|
32
28
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-issuer-identifier.js","sourceRoot":"","sources":["../src/oauth-issuer-identifier.ts"],"names":[],"mappings":";;;AAAA,6BAAuB;
|
|
1
|
+
{"version":3,"file":"oauth-issuer-identifier.js","sourceRoot":"","sources":["../src/oauth-issuer-identifier.ts"],"names":[],"mappings":";;;AAAA,6BAAuB;AACvB,iDAAuD;AACvD,uCAAmC;AAEtB,QAAA,2BAA2B,GAAG,OAAC;KACzC,MAAM,EAAE;KACR,WAAW,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAC1B,uCAAuC;IAEvC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;YAC3B,OAAO,EAAE,sCAAsC;SAChD,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,IAAA,iBAAO,EAAC,KAAK,CAAC,CAAA;IAC1B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,GAAG,CAAC,QAAQ,CAAC;YAClB,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;YAC3B,OAAO,EAAE,aAAa;SACvB,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,qCAAsB,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACvD,uCAAuC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,OAAO,EAAE,6BAA6B;aACvC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjC,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;YAC3B,OAAO,EAAE,oDAAoD;SAC9D,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QAC3B,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;YAC3B,OAAO,EAAE,iDAAiD;SAC3D,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAA;IACnE,IAAI,KAAK,KAAK,cAAc,EAAE,CAAC;QAC7B,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM;YAC3B,OAAO,EAAE,0CAA0C;SACpD,CAAC,CAAA;IACJ,CAAC;AACH,CAAC,CAAC,CAAA"}
|
package/dist/util.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ export declare function isIP(hostname: string): boolean;
|
|
|
2
2
|
export type LoopbackHost = 'localhost' | '127.0.0.1' | '[::1]';
|
|
3
3
|
export declare function isLoopbackHost(host: unknown): host is LoopbackHost;
|
|
4
4
|
export declare function isLoopbackUrl(input: URL | string): boolean;
|
|
5
|
+
export declare function safeUrl(input: URL | string): URL | null;
|
|
5
6
|
//# sourceMappingURL=util.d.ts.map
|
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,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"}
|
|
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;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,GAAG,GAAG,GAAG,IAAI,CAMvD"}
|
package/dist/util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isLoopbackUrl = exports.isLoopbackHost = exports.isIP = void 0;
|
|
3
|
+
exports.safeUrl = exports.isLoopbackUrl = exports.isLoopbackHost = exports.isIP = void 0;
|
|
4
4
|
function isIP(hostname) {
|
|
5
5
|
// IPv4
|
|
6
6
|
if (hostname.match(/^\d+\.\d+\.\d+\.\d+$/))
|
|
@@ -20,4 +20,13 @@ function isLoopbackUrl(input) {
|
|
|
20
20
|
return isLoopbackHost(url.hostname);
|
|
21
21
|
}
|
|
22
22
|
exports.isLoopbackUrl = isLoopbackUrl;
|
|
23
|
+
function safeUrl(input) {
|
|
24
|
+
try {
|
|
25
|
+
return new URL(input);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.safeUrl = safeUrl;
|
|
23
32
|
//# 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":";;;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"}
|
|
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;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;AAND,0BAMC"}
|
package/package.json
CHANGED
|
@@ -11,18 +11,25 @@ export function atprotoLoopbackClientMetadata(
|
|
|
11
11
|
|
|
12
12
|
const { origin, pathname, searchParams } = parseOAuthClientIdUrl(clientId)
|
|
13
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')
|
|
20
|
+
|
|
14
21
|
return {
|
|
15
22
|
client_id: clientId,
|
|
16
23
|
client_name: 'Loopback client',
|
|
17
24
|
response_types: ['code id_token', 'code'],
|
|
18
25
|
grant_types: ['authorization_code', 'implicit', 'refresh_token'],
|
|
19
26
|
scope: 'openid profile offline_access',
|
|
20
|
-
redirect_uris:
|
|
21
|
-
?
|
|
22
|
-
: (['127.0.0.1', '[::1]'].map(
|
|
27
|
+
redirect_uris: (redirectUris.length
|
|
28
|
+
? redirectUris
|
|
29
|
+
: (['127.0.0.1', '[::1]'] as const).map(
|
|
23
30
|
(ip) =>
|
|
24
31
|
Object.assign(new URL(pathname, origin), { hostname: ip }).href,
|
|
25
|
-
) as [string, ...string[]]
|
|
32
|
+
)) as [string, ...string[]],
|
|
26
33
|
token_endpoint_auth_method: 'none',
|
|
27
34
|
application_type: 'native',
|
|
28
35
|
dpop_bound_access_tokens: true,
|
package/src/constants.ts
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
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
|
+
|
|
1
17
|
export const CLIENT_ASSERTION_TYPE_JWT_BEARER =
|
|
2
18
|
'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
|
|
3
19
|
|
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// shimmed (e.g. by webpack)
|
|
5
|
-
const ALLOW_INSECURE = (() => {
|
|
6
|
-
try {
|
|
7
|
-
const env = process.env.NODE_ENV
|
|
8
|
-
return env === 'development' || env === 'test'
|
|
9
|
-
} catch {
|
|
10
|
-
return false
|
|
11
|
-
}
|
|
12
|
-
})()
|
|
2
|
+
import { ALLOW_UNSECURE_ORIGINS } from './constants.js'
|
|
3
|
+
import { safeUrl } from './util.js'
|
|
13
4
|
|
|
14
5
|
export const oauthIssuerIdentifierSchema = z
|
|
15
6
|
.string()
|
|
16
|
-
.url()
|
|
17
7
|
.superRefine((value, ctx) => {
|
|
18
8
|
// Validate the issuer (MIX-UP attacks)
|
|
19
9
|
|
|
@@ -24,10 +14,16 @@ export const oauthIssuerIdentifierSchema = z
|
|
|
24
14
|
})
|
|
25
15
|
}
|
|
26
16
|
|
|
27
|
-
const url =
|
|
17
|
+
const url = safeUrl(value)
|
|
18
|
+
if (!url) {
|
|
19
|
+
return ctx.addIssue({
|
|
20
|
+
code: z.ZodIssueCode.custom,
|
|
21
|
+
message: 'Invalid url',
|
|
22
|
+
})
|
|
23
|
+
}
|
|
28
24
|
|
|
29
25
|
if (url.protocol !== 'https:') {
|
|
30
|
-
if (
|
|
26
|
+
if (ALLOW_UNSECURE_ORIGINS && url.protocol === 'http:') {
|
|
31
27
|
// We'll allow HTTP in development mode
|
|
32
28
|
} else {
|
|
33
29
|
ctx.addIssue({
|
package/src/util.ts
CHANGED
|
@@ -18,3 +18,11 @@ export function isLoopbackUrl(input: URL | string): boolean {
|
|
|
18
18
|
const url = typeof input === 'string' ? new URL(input) : input
|
|
19
19
|
return isLoopbackHost(url.hostname)
|
|
20
20
|
}
|
|
21
|
+
|
|
22
|
+
export function safeUrl(input: URL | string): URL | null {
|
|
23
|
+
try {
|
|
24
|
+
return new URL(input)
|
|
25
|
+
} catch {
|
|
26
|
+
return null
|
|
27
|
+
}
|
|
28
|
+
}
|