@atproto/oauth-types 0.1.1 → 0.1.2-rc.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|