@better-auth/oauth-provider 1.7.0-beta.4 → 1.7.0-beta.6
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/{client-assertion-DLMKVgoj.mjs → client-assertion-CctbJywV.mjs} +102 -87
- package/dist/client-resource.d.mts +31 -2
- package/dist/client-resource.mjs +45 -25
- package/dist/client.d.mts +1 -1
- package/dist/client.mjs +3 -13
- package/dist/index.d.mts +102 -17
- package/dist/index.mjs +1747 -1886
- package/dist/introspect-BXqKFUQZ.mjs +2115 -0
- package/dist/{oauth-Vt3lTNHX.d.mts → oauth-CAeemjD7.d.mts} +364 -175
- package/dist/{oauth-q7dn10NU.d.mts → oauth-CaXmZpoL.d.mts} +922 -33
- package/dist/resource-challenge-B-cqv4ur.mjs +63 -0
- package/dist/rolldown-runtime-wcPFST8Q.mjs +13 -0
- package/dist/signed-query-CFv2jNMT.mjs +44 -0
- package/dist/utils-Baq6atYN.mjs +764 -0
- package/dist/{version-nFnRm-a3.mjs → version-CUu3vBtU.mjs} +1 -1
- package/package.json +8 -9
- package/dist/mcp-CYnz-MXn.mjs +0 -56
- package/dist/utils-DKBWQ8fe.mjs +0 -492
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { isAPIError } from "better-auth/api";
|
|
2
|
+
import { APIError as APIError$1 } from "better-call";
|
|
3
|
+
import { DPOP_SIGNING_ALGORITHMS } from "better-auth/oauth2";
|
|
4
|
+
//#region src/resource-challenge.ts
|
|
5
|
+
const DPOP_CHALLENGE_ERRORS = new Set(["invalid_dpop_proof"]);
|
|
6
|
+
function quoteAuthParam(value) {
|
|
7
|
+
return value.replace(/[\r\n]+/g, " ").replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
8
|
+
}
|
|
9
|
+
function extractDpopError(error) {
|
|
10
|
+
const body = error.body;
|
|
11
|
+
return {
|
|
12
|
+
errorCode: typeof body?.error === "string" ? body.error : void 0,
|
|
13
|
+
description: typeof body?.error_description === "string" ? body.error_description : typeof body?.message === "string" ? body.message : error.message
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function isDpopChallengeError(error) {
|
|
17
|
+
const { errorCode, description } = extractDpopError(error);
|
|
18
|
+
return !!errorCode && (DPOP_CHALLENGE_ERRORS.has(errorCode) || errorCode === "invalid_token" && description.includes("DPoP"));
|
|
19
|
+
}
|
|
20
|
+
function buildDpopChallenge(error, opts) {
|
|
21
|
+
const { errorCode, description } = extractDpopError(error);
|
|
22
|
+
const algorithms = opts?.dpopSigningAlgorithms ?? DPOP_SIGNING_ALGORITHMS;
|
|
23
|
+
return [
|
|
24
|
+
`DPoP error="${quoteAuthParam(errorCode ?? "invalid_dpop_proof")}"`,
|
|
25
|
+
`error_description="${quoteAuthParam(description)}"`,
|
|
26
|
+
`algs="${quoteAuthParam(algorithms.join(" "))}"`
|
|
27
|
+
].join(", ");
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Raise an OAuth resource-server challenge for a failed access-token request.
|
|
31
|
+
*
|
|
32
|
+
* Missing/invalid bearer credentials are reported with RFC 6750 plus the RFC
|
|
33
|
+
* 9728 `resource_metadata` pointer. DPoP-bound-token failures are reported with
|
|
34
|
+
* RFC 9449's `DPoP` challenge so clients know which proof algorithms to use.
|
|
35
|
+
* Non-URL resources (for example a `urn:` or a client id) resolve their
|
|
36
|
+
* metadata URL through `resourceMetadataMappings`.
|
|
37
|
+
*
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
function raiseResourceServerChallenge(error, resource, opts) {
|
|
41
|
+
if (isAPIError(error) && error.status === "UNAUTHORIZED") {
|
|
42
|
+
if (isDpopChallengeError(error)) throw new APIError$1("UNAUTHORIZED", { message: error.message }, { "WWW-Authenticate": buildDpopChallenge(error, opts) });
|
|
43
|
+
const wwwAuthenticateValue = (Array.isArray(resource) ? resource : [resource]).map((value) => {
|
|
44
|
+
const url = URL.canParse?.(value) ? new URL(value) : null;
|
|
45
|
+
if (url && url.origin !== "null") {
|
|
46
|
+
const resourcePath = url.pathname.endsWith("/") ? url.pathname.slice(0, -1) : url.pathname;
|
|
47
|
+
let challenge = `Bearer resource_metadata="${url.origin}/.well-known/oauth-protected-resource${resourcePath}${url.search}"`;
|
|
48
|
+
if (opts?.scope) challenge += `, scope="${quoteAuthParam(opts.scope)}"`;
|
|
49
|
+
return challenge;
|
|
50
|
+
}
|
|
51
|
+
const resourceMetadata = opts?.resourceMetadataMappings?.[value];
|
|
52
|
+
if (!resourceMetadata) throw new APIError$1("INTERNAL_SERVER_ERROR", { message: `missing resource_metadata mapping for ${value}` });
|
|
53
|
+
let challenge = `Bearer resource_metadata="${resourceMetadata}"`;
|
|
54
|
+
if (opts?.scope) challenge += `, scope="${quoteAuthParam(opts.scope)}"`;
|
|
55
|
+
return challenge;
|
|
56
|
+
}).join(", ");
|
|
57
|
+
throw new APIError$1("UNAUTHORIZED", { message: error.message }, { "WWW-Authenticate": wwwAuthenticateValue });
|
|
58
|
+
}
|
|
59
|
+
if (error instanceof Error) throw error;
|
|
60
|
+
throw new Error(error);
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { raiseResourceServerChallenge as t };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { __exportAll as t };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region src/signed-query.ts
|
|
2
|
+
const signedQueryIssuedAtParam = "ba_iat";
|
|
3
|
+
const postLoginClearedParam = "ba_pl";
|
|
4
|
+
const signedQueryParameterNameParam = "ba_param";
|
|
5
|
+
function canonicalizeOAuthQueryParams(params) {
|
|
6
|
+
const canonicalParams = new URLSearchParams();
|
|
7
|
+
const entries = [...params.entries()].sort(([keyA, valueA], [keyB, valueB]) => {
|
|
8
|
+
if (keyA < keyB) return -1;
|
|
9
|
+
if (keyA > keyB) return 1;
|
|
10
|
+
if (valueA < valueB) return -1;
|
|
11
|
+
if (valueA > valueB) return 1;
|
|
12
|
+
return 0;
|
|
13
|
+
});
|
|
14
|
+
for (const [key, value] of entries) canonicalParams.append(key, value);
|
|
15
|
+
return canonicalParams;
|
|
16
|
+
}
|
|
17
|
+
function setSignedOAuthQueryParameterNames(params) {
|
|
18
|
+
params.delete(signedQueryParameterNameParam);
|
|
19
|
+
const signedParameterNames = [...new Set([...params.keys(), signedQueryParameterNameParam])].sort();
|
|
20
|
+
for (const parameterName of signedParameterNames) params.append(signedQueryParameterNameParam, parameterName);
|
|
21
|
+
}
|
|
22
|
+
function getSignedOAuthQueryParameterNames(params) {
|
|
23
|
+
const signedParameterNames = params.getAll(signedQueryParameterNameParam);
|
|
24
|
+
if (!signedParameterNames.length) return;
|
|
25
|
+
return new Set(signedParameterNames);
|
|
26
|
+
}
|
|
27
|
+
function buildSignedOAuthQuery(search) {
|
|
28
|
+
const params = new URLSearchParams(search);
|
|
29
|
+
if (!params.has("sig")) return;
|
|
30
|
+
const signedParameterNames = getSignedOAuthQueryParameterNames(params);
|
|
31
|
+
if (!signedParameterNames) return;
|
|
32
|
+
const signedParams = new URLSearchParams();
|
|
33
|
+
for (const [key, value] of params.entries()) if (key === "sig" || key === signedQueryParameterNameParam || signedParameterNames.has(key)) signedParams.append(key, value);
|
|
34
|
+
return signedParams.toString();
|
|
35
|
+
}
|
|
36
|
+
function getSignedQueryIssuedAt(oauthQuery) {
|
|
37
|
+
const raw = new URLSearchParams(oauthQuery).get(signedQueryIssuedAtParam);
|
|
38
|
+
if (!raw) return null;
|
|
39
|
+
const issuedAt = Number(raw);
|
|
40
|
+
if (!Number.isFinite(issuedAt) || issuedAt <= 0) return null;
|
|
41
|
+
return new Date(issuedAt);
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { setSignedOAuthQueryParameterNames as a, postLoginClearedParam as i, canonicalizeOAuthQueryParams as n, signedQueryIssuedAtParam as o, getSignedQueryIssuedAt as r, buildSignedOAuthQuery as t };
|