@better-auth/oauth-provider 1.6.16 → 1.6.18

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.
@@ -1,5 +1,5 @@
1
- import { C as handleMcpErrors, a as getJwtPlugin, o as getOAuthProviderPlugin } from "./utils-BKGiA6QL.mjs";
2
- import { t as PACKAGE_VERSION } from "./version-BJguNh6q.mjs";
1
+ import { a as getJwtPlugin, b as handleMcpErrors, o as getOAuthProviderPlugin } from "./utils-B8pHZVEm.mjs";
2
+ import { t as PACKAGE_VERSION } from "./version-D8-vU8KW.mjs";
3
3
  import { verifyAccessToken } from "better-auth/oauth2";
4
4
  import { APIError } from "better-call";
5
5
  import { logger } from "@better-auth/core/env";
package/dist/client.mjs CHANGED
@@ -1,17 +1,6 @@
1
- import { t as PACKAGE_VERSION } from "./version-BJguNh6q.mjs";
1
+ import { n as buildSignedOAuthQuery, t as PACKAGE_VERSION } from "./version-D8-vU8KW.mjs";
2
2
  import { safeJSONParse } from "@better-auth/core/utils/json";
3
3
  //#region src/client.ts
4
- function parseSignedQuery(search) {
5
- const params = new URLSearchParams(search);
6
- if (params.has("sig")) {
7
- const signedParams = new URLSearchParams();
8
- for (const [key, value] of params.entries()) {
9
- signedParams.append(key, value);
10
- if (key === "sig") break;
11
- }
12
- return signedParams.toString();
13
- }
14
- }
15
4
  const oauthProviderClient = () => {
16
5
  return {
17
6
  id: "oauth-provider-client",
@@ -26,7 +15,7 @@ const oauthProviderClient = () => {
26
15
  if (body?.oauth_query) return;
27
16
  if (typeof window !== "undefined" && window?.location?.search && !(ctx.method === "GET" || ctx.method === "DELETE")) ctx.body = JSON.stringify({
28
17
  ...body,
29
- oauth_query: parseSignedQuery(window.location.search)
18
+ oauth_query: buildSignedOAuthQuery(window.location.search)
30
19
  });
31
20
  } }
32
21
  }],
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { S as verifyOAuthQueryParams, _ as searchParamsToQuery, a as getJwtPlugin, b as storeToken, c as getStoredToken, d as parseClientMetadata, f as parsePrompt, g as resolveSubjectIdentifier, h as resolveSessionAuthTime, i as getClient, l as isPKCERequired, m as removePromptFromQuery, n as clientAllowsGrant, p as postLoginClearedParam, r as decryptStoredClientSecret, s as getSignedQueryIssuedAt, t as basicToClientCredentials, u as normalizeTimestampValue, v as signedQueryIssuedAtParam, w as mcpHandler, x as validateClientCredentials, y as storeClientSecret } from "./utils-BKGiA6QL.mjs";
2
- import { t as PACKAGE_VERSION } from "./version-BJguNh6q.mjs";
1
+ import { _ as storeToken, a as getJwtPlugin, c as isPKCERequired, d as parsePrompt, f as removePromptFromQuery, g as storeClientSecret, h as searchParamsToQuery, i as getClient, l as normalizeTimestampValue, m as resolveSubjectIdentifier, n as clientAllowsGrant, p as resolveSessionAuthTime, r as decryptStoredClientSecret, s as getStoredToken, t as basicToClientCredentials, u as parseClientMetadata, v as validateClientCredentials, x as mcpHandler, y as verifyOAuthQueryParams } from "./utils-B8pHZVEm.mjs";
2
+ import { a as postLoginClearedParam, i as getSignedQueryIssuedAt, o as setSignedOAuthQueryParameterNames, r as canonicalizeOAuthQueryParams, s as signedQueryIssuedAtParam, t as PACKAGE_VERSION } from "./version-D8-vU8KW.mjs";
3
3
  import { APIError, createAuthEndpoint, createAuthMiddleware, dispatchAuthEndpoint, getOAuthState, getSessionFromCtx, sessionMiddleware } from "better-auth/api";
4
4
  import { generateCodeChallenge, getJwks, verifyJwsAccessToken } from "better-auth/oauth2";
5
5
  import { APIError as APIError$1 } from "better-call";
@@ -827,6 +827,7 @@ async function validateJwtAccessToken(ctx, opts, token, clientId) {
827
827
  jwksFetch: jwtPluginOptions?.jwks?.remoteUrl ? jwtPluginOptions.jwks.remoteUrl : async () => {
828
828
  return (await jwtPlugin?.endpoints.getJwks(ctx))?.response;
829
829
  },
830
+ jwksCacheKey: jwtPlugin,
830
831
  verifyOptions: {
831
832
  audience: opts.validAudiences ?? ctx.context.baseURL,
832
833
  issuer: jwtPluginOptions?.jwt?.issuer ?? ctx.context.baseURL
@@ -2268,6 +2269,7 @@ async function revokeJwtAccessToken(ctx, opts, token) {
2268
2269
  jwksFetch: jwtPluginOptions?.jwks?.remoteUrl ? jwtPluginOptions.jwks.remoteUrl : async () => {
2269
2270
  return (await jwtPlugin?.endpoints.getJwks(ctx))?.response;
2270
2271
  },
2272
+ jwksCacheKey: jwtPlugin,
2271
2273
  verifyOptions: {
2272
2274
  audience: opts.validAudiences ?? ctx.context.baseURL,
2273
2275
  issuer: jwtPluginOptions?.jwt?.issuer ?? ctx.context.baseURL
@@ -4023,10 +4025,12 @@ async function signParams(ctx, opts, flags) {
4023
4025
  const params = serializeAuthorizationQuery(ctx.query);
4024
4026
  params.set("exp", String(exp));
4025
4027
  params.set(signedQueryIssuedAtParam, String(issuedAt));
4028
+ params.delete("sig");
4026
4029
  params.delete(postLoginClearedParam);
4027
4030
  if (flags?.postLoginClearedForSession) params.set(postLoginClearedParam, flags.postLoginClearedForSession);
4028
- const signature = await makeSignature(params.toString(), ctx.context.secret);
4029
- params.append("sig", signature);
4031
+ setSignedOAuthQueryParameterNames(params);
4032
+ const signature = await makeSignature(canonicalizeOAuthQueryParams(params).toString(), ctx.context.secret);
4033
+ params.set("sig", signature);
4030
4034
  return params.toString();
4031
4035
  }
4032
4036
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { r as canonicalizeOAuthQueryParams } from "./version-D8-vU8KW.mjs";
1
2
  import { isAPIError } from "better-auth/api";
2
3
  import { verifyAccessToken } from "better-auth/oauth2";
3
4
  import { APIError as APIError$1 } from "better-call";
@@ -132,10 +133,11 @@ const cachedTrustedClients = new TTLCache();
132
133
  async function verifyOAuthQueryParams(oauth_query, secret) {
133
134
  const queryParams = new URLSearchParams(oauth_query);
134
135
  const sig = queryParams.get("sig");
136
+ const sigs = queryParams.getAll("sig");
135
137
  const exp = Number(queryParams.get("exp"));
136
138
  queryParams.delete("sig");
137
- const verifySig = await makeSignature(queryParams.toString(), secret);
138
- return !!sig && constantTimeEqual(sig, verifySig) && /* @__PURE__ */ new Date(exp * 1e3) >= /* @__PURE__ */ new Date();
139
+ const verifySig = await makeSignature(canonicalizeOAuthQueryParams(queryParams).toString(), secret);
140
+ return sigs.length === 1 && !!sig && constantTimeEqual(sig, verifySig) && /* @__PURE__ */ new Date(exp * 1e3) >= /* @__PURE__ */ new Date();
139
141
  }
140
142
  /**
141
143
  * Get a client by ID, checking trusted clients first, then database
@@ -390,15 +392,6 @@ function searchParamsToQuery(params) {
390
392
  }
391
393
  return result;
392
394
  }
393
- const signedQueryIssuedAtParam = "ba_iat";
394
- const postLoginClearedParam = "ba_pl";
395
- function getSignedQueryIssuedAt(oauthQuery) {
396
- const raw = new URLSearchParams(oauthQuery).get(signedQueryIssuedAtParam);
397
- if (!raw) return null;
398
- const issuedAt = Number(raw);
399
- if (!Number.isFinite(issuedAt) || issuedAt <= 0) return null;
400
- return new Date(issuedAt);
401
- }
402
395
  function removePromptFromQuery(query, prompt) {
403
396
  const nextQuery = new URLSearchParams(query);
404
397
  const prompts = nextQuery.get("prompt")?.split(" ");
@@ -436,4 +429,4 @@ function isPKCERequired(client, requestedScopes) {
436
429
  return false;
437
430
  }
438
431
  //#endregion
439
- export { handleMcpErrors as C, verifyOAuthQueryParams as S, searchParamsToQuery as _, getJwtPlugin as a, storeToken as b, getStoredToken as c, parseClientMetadata as d, parsePrompt as f, resolveSubjectIdentifier as g, resolveSessionAuthTime as h, getClient as i, isPKCERequired as l, removePromptFromQuery as m, clientAllowsGrant as n, getOAuthProviderPlugin as o, postLoginClearedParam as p, decryptStoredClientSecret as r, getSignedQueryIssuedAt as s, basicToClientCredentials as t, normalizeTimestampValue as u, signedQueryIssuedAtParam as v, mcpHandler as w, validateClientCredentials as x, storeClientSecret as y };
432
+ export { storeToken as _, getJwtPlugin as a, handleMcpErrors as b, isPKCERequired as c, parsePrompt as d, removePromptFromQuery as f, storeClientSecret as g, searchParamsToQuery as h, getClient as i, normalizeTimestampValue as l, resolveSubjectIdentifier as m, clientAllowsGrant as n, getOAuthProviderPlugin as o, resolveSessionAuthTime as p, decryptStoredClientSecret as r, getStoredToken as s, basicToClientCredentials as t, parseClientMetadata as u, validateClientCredentials as v, mcpHandler as x, verifyOAuthQueryParams as y };
@@ -0,0 +1,47 @@
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
+ //#region src/version.ts
45
+ const PACKAGE_VERSION = "1.6.18";
46
+ //#endregion
47
+ export { postLoginClearedParam as a, getSignedQueryIssuedAt as i, buildSignedOAuthQuery as n, setSignedOAuthQueryParameterNames as o, canonicalizeOAuthQueryParams as r, signedQueryIssuedAtParam as s, PACKAGE_VERSION as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/oauth-provider",
3
- "version": "1.6.16",
3
+ "version": "1.6.18",
4
4
  "description": "An oauth provider plugin for Better Auth",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -64,15 +64,15 @@
64
64
  "@modelcontextprotocol/sdk": "^1.27.1",
65
65
  "listhen": "^1.9.0",
66
66
  "tsdown": "0.21.1",
67
- "@better-auth/core": "1.6.16",
68
- "better-auth": "1.6.16"
67
+ "@better-auth/core": "1.6.18",
68
+ "better-auth": "1.6.18"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "@better-auth/utils": "0.4.1",
72
- "@better-fetch/fetch": "1.2.2",
72
+ "@better-fetch/fetch": "1.3.0",
73
73
  "better-call": "1.3.6",
74
- "@better-auth/core": "^1.6.16",
75
- "better-auth": "^1.6.16"
74
+ "@better-auth/core": "^1.6.18",
75
+ "better-auth": "^1.6.18"
76
76
  },
77
77
  "scripts": {
78
78
  "build": "tsdown",
@@ -1,5 +0,0 @@
1
- //#endregion
2
- //#region src/version.ts
3
- const PACKAGE_VERSION = "1.6.16";
4
- //#endregion
5
- export { PACKAGE_VERSION as t };