@better-auth/oauth-provider 1.6.12 → 1.6.13

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
1
  import { S as handleMcpErrors, a as getOAuthProviderPlugin, i as getJwtPlugin } from "./utils-DoYEeMrg.mjs";
2
- import { t as PACKAGE_VERSION } from "./version-DZ0lABPc.mjs";
2
+ import { t as PACKAGE_VERSION } from "./version-MLrabwrK.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,4 +1,4 @@
1
- import { t as PACKAGE_VERSION } from "./version-DZ0lABPc.mjs";
1
+ import { t as PACKAGE_VERSION } from "./version-MLrabwrK.mjs";
2
2
  import { safeJSONParse } from "@better-auth/core/utils/json";
3
3
  //#region src/client.ts
4
4
  function parseSignedQuery(search) {
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { C as mcpHandler, _ as signedQueryIssuedAtParam, b as validateClientCredentials, c as isPKCERequired, d as parsePrompt, f as postLoginClearedParam, g as searchParamsToQuery, h as resolveSubjectIdentifier, i as getJwtPlugin, l as normalizeTimestampValue, m as resolveSessionAuthTime, n as decryptStoredClientSecret, o as getSignedQueryIssuedAt, p as removePromptFromQuery, r as getClient, s as getStoredToken, t as basicToClientCredentials, u as parseClientMetadata, v as storeClientSecret, x as verifyOAuthQueryParams, y as storeToken } from "./utils-DoYEeMrg.mjs";
2
- import { t as PACKAGE_VERSION } from "./version-DZ0lABPc.mjs";
2
+ import { t as PACKAGE_VERSION } from "./version-MLrabwrK.mjs";
3
3
  import { APIError, createAuthEndpoint, createAuthMiddleware, 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";
@@ -14,6 +14,7 @@ import { mergeSchema } from "better-auth/db";
14
14
  import * as z from "zod";
15
15
  import { signJWT, toExpJWT } from "better-auth/plugins";
16
16
  import { SignJWT, compactVerify, createLocalJWKSet, decodeJwt } from "jose";
17
+ import { SafeUrlSchema } from "@better-auth/core/utils/redirect-uri";
17
18
  //#region src/consent.ts
18
19
  async function consentEndpoint(ctx, opts) {
19
20
  const oauthRequest = await oAuthState.get();
@@ -174,11 +175,6 @@ async function postLogin(ctx, opts) {
174
175
  }
175
176
  //#endregion
176
177
  //#region src/types/zod.ts
177
- const DANGEROUS_SCHEMES = [
178
- "javascript:",
179
- "data:",
180
- "vbscript:"
181
- ];
182
178
  /**
183
179
  * Runtime schema for OAuthAuthorizationQuery.
184
180
  * Uses passthrough to tolerate fields added by future extensions (PAR, FPA, etc.)
@@ -214,34 +210,6 @@ const verificationValueSchema = z.object({
214
210
  referenceId: z.string().optional(),
215
211
  authTime: z.number().optional()
216
212
  }).passthrough();
217
- /**
218
- * Reusable URL validation for OAuth redirect URIs.
219
- * - Blocks dangerous schemes (javascript:, data:, vbscript:)
220
- * - For http/https: requires HTTPS (HTTP allowed only for loopback hosts: 127.0.0.0/8, [::1], *.localhost per RFC 6761)
221
- * - Allows custom schemes for mobile apps (e.g., myapp://callback)
222
- */
223
- const SafeUrlSchema = z.url().superRefine((val, ctx) => {
224
- if (!URL.canParse(val)) {
225
- ctx.addIssue({
226
- code: "custom",
227
- message: "URL must be parseable",
228
- fatal: true
229
- });
230
- return z.NEVER;
231
- }
232
- const u = new URL(val);
233
- if (DANGEROUS_SCHEMES.includes(u.protocol)) {
234
- ctx.addIssue({
235
- code: "custom",
236
- message: "URL cannot use javascript:, data:, or vbscript: scheme"
237
- });
238
- return;
239
- }
240
- if (u.protocol === "http:" && !isLoopbackHost(u.host)) ctx.addIssue({
241
- code: "custom",
242
- message: "Redirect URI must use HTTPS (HTTP allowed only for loopback hosts)"
243
- });
244
- });
245
213
  //#endregion
246
214
  //#region src/userinfo.ts
247
215
  /**
@@ -1233,6 +1201,28 @@ const publicSessionMiddleware = (opts) => createAuthMiddleware(async (ctx) => {
1233
1201
  if (!await verifyOAuthQueryParams(query, ctx.context.secret)) throw new APIError("UNAUTHORIZED", { error: "invalid_signature" });
1234
1202
  });
1235
1203
  //#endregion
1204
+ //#region src/oauthClient/privileges.ts
1205
+ /**
1206
+ * Authorizes a client action against the configured `clientPrivileges` hook.
1207
+ *
1208
+ * This is the single authorization helper for every OAuth client mutation. The
1209
+ * create path enforces it at the shared creation chokepoint so that no
1210
+ * registration route can reach client persistence without it.
1211
+ *
1212
+ * @throws APIError UNAUTHORIZED when there is no session or the hook denies the action.
1213
+ * @throws APIError BAD_REQUEST when the request carries no headers.
1214
+ */
1215
+ async function assertClientPrivileges(ctx, session, opts, action) {
1216
+ if (!session) throw new APIError("UNAUTHORIZED");
1217
+ if (!ctx.headers) throw new APIError("BAD_REQUEST");
1218
+ if (opts.clientPrivileges && !await opts.clientPrivileges({
1219
+ headers: ctx.headers,
1220
+ action,
1221
+ session: session.session,
1222
+ user: session.user
1223
+ })) throw new APIError("UNAUTHORIZED");
1224
+ }
1225
+ //#endregion
1236
1226
  //#region src/register.ts
1237
1227
  /**
1238
1228
  * Resolves the auth method and type for unauthenticated DCR.
@@ -1327,6 +1317,9 @@ async function checkOAuthClient(client, opts, settings) {
1327
1317
  async function createOAuthClientEndpoint(ctx, opts, settings) {
1328
1318
  const body = ctx.body;
1329
1319
  const session = await getSessionFromCtx(ctx);
1320
+ if (settings.isRegister) {
1321
+ if (session) await assertClientPrivileges(ctx, session, opts, "create");
1322
+ } else await assertClientPrivileges(ctx, session, opts, "create");
1330
1323
  const isPublic = body.token_endpoint_auth_method === "none";
1331
1324
  await checkOAuthClient(ctx.body, opts, settings);
1332
1325
  const clientId = opts.generateClientId?.() || generateRandomString(32, "a-z", "A-Z");
@@ -1658,16 +1651,6 @@ async function rotateClientSecretEndpoint(ctx, opts) {
1658
1651
  clientSecret: (opts.prefix?.clientSecret ?? "") + clientSecret
1659
1652
  });
1660
1653
  }
1661
- async function assertClientPrivileges(ctx, session, opts, action) {
1662
- if (!session) throw new APIError("UNAUTHORIZED");
1663
- if (!ctx.headers) throw new APIError("BAD_REQUEST");
1664
- if (opts.clientPrivileges && !await opts.clientPrivileges({
1665
- headers: ctx.headers,
1666
- action,
1667
- session: session.session,
1668
- user: session.user
1669
- })) throw new APIError("UNAUTHORIZED");
1670
- }
1671
1654
  //#endregion
1672
1655
  //#region src/oauthClient/index.ts
1673
1656
  const adminCreateOAuthClient = (opts) => createAuthEndpoint("/admin/oauth2/create-client", {
@@ -1850,7 +1833,6 @@ const adminCreateOAuthClient = (opts) => createAuthEndpoint("/admin/oauth2/creat
1850
1833
  }
1851
1834
  }
1852
1835
  }, async (ctx) => {
1853
- await assertClientPrivileges(ctx, await getSessionFromCtx(ctx), opts, "create");
1854
1836
  return createOAuthClientEndpoint(ctx, opts, { isRegister: false });
1855
1837
  });
1856
1838
  const createOAuthClient = (opts) => createAuthEndpoint("/oauth2/create-client", {
@@ -2020,7 +2002,6 @@ const createOAuthClient = (opts) => createAuthEndpoint("/oauth2/create-client",
2020
2002
  } }
2021
2003
  } }
2022
2004
  }, async (ctx) => {
2023
- await assertClientPrivileges(ctx, await getSessionFromCtx(ctx), opts, "create");
2024
2005
  return createOAuthClientEndpoint(ctx, opts, { isRegister: false });
2025
2006
  });
2026
2007
  const getOAuthClient = (opts) => createAuthEndpoint("/oauth2/get-client", {
@@ -1,5 +1,5 @@
1
1
  //#endregion
2
2
  //#region src/version.ts
3
- const PACKAGE_VERSION = "1.6.12";
3
+ const PACKAGE_VERSION = "1.6.13";
4
4
  //#endregion
5
5
  export { 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.12",
3
+ "version": "1.6.13",
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.12",
68
- "better-auth": "1.6.12"
67
+ "@better-auth/core": "1.6.13",
68
+ "better-auth": "1.6.13"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "@better-auth/utils": "0.4.1",
72
72
  "@better-fetch/fetch": "1.1.21",
73
73
  "better-call": "1.3.5",
74
- "@better-auth/core": "^1.6.12",
75
- "better-auth": "^1.6.12"
74
+ "@better-auth/core": "^1.6.13",
75
+ "better-auth": "^1.6.13"
76
76
  },
77
77
  "scripts": {
78
78
  "build": "tsdown",