@better-auth/oauth-provider 1.6.0-beta.0 → 1.6.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/client-resource.d.mts +1 -1
- package/dist/client-resource.mjs +1 -1
- package/dist/client.d.mts +1 -1
- package/dist/client.mjs +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +49 -10
- package/dist/oauth-CYgzO8Am.d.mts +2081 -0
- package/dist/{oauth-4vgZlF-I.d.mts → oauth-Cc0nzj5Q.d.mts} +19 -2
- package/dist/{version-DevbO3Yy.mjs → version-xqVKoocI.mjs} +1 -1
- package/package.json +6 -6
- package/dist/oauth-CEoJtL3Y.d.mts +0 -1879
package/dist/client-resource.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as getJwtPlugin, o as getOAuthProviderPlugin, v as handleMcpErrors } from "./utils-sQ4gYeh3.mjs";
|
|
2
|
-
import { t as PACKAGE_VERSION } from "./version-
|
|
2
|
+
import { t as PACKAGE_VERSION } from "./version-xqVKoocI.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.d.mts
CHANGED
package/dist/client.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { _ as Awaitable, a as ResourceServerMetadata, c as OAuthConsent, d as OAuthRefreshToken, f as Prompt, g as VerificationValue, h as StoreTokenType, i as OIDCMetadata, l as OAuthOpaqueAccessToken, m as Scope, n as GrantType, o as AuthorizePrompt, p as SchemaClient, r as OAuthClient, s as OAuthAuthorizationQuery, t as AuthServerMetadata, u as OAuthOptions } from "./oauth-
|
|
2
|
-
import { n as oauthProvider, t as getOAuthProviderState } from "./oauth-
|
|
1
|
+
import { _ as Awaitable, a as ResourceServerMetadata, c as OAuthConsent, d as OAuthRefreshToken, f as Prompt, g as VerificationValue, h as StoreTokenType, i as OIDCMetadata, l as OAuthOpaqueAccessToken, m as Scope, n as GrantType, o as AuthorizePrompt, p as SchemaClient, r as OAuthClient, s as OAuthAuthorizationQuery, t as AuthServerMetadata, u as OAuthOptions } from "./oauth-Cc0nzj5Q.mjs";
|
|
2
|
+
import { n as oauthProvider, t as getOAuthProviderState } from "./oauth-CYgzO8Am.mjs";
|
|
3
3
|
import { verifyAccessToken } from "better-auth/oauth2";
|
|
4
4
|
import { JWSAlgorithms, JwtOptions } from "better-auth/plugins";
|
|
5
5
|
import { JWTPayload } from "jose";
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _ as verifyOAuthQueryParams, a as getJwtPlugin, c as isPKCERequired, d as parsePrompt, f as resolveSessionAuthTime, g as validateClientCredentials, h as storeToken, i as getClient, l as normalizeTimestampValue, m as storeClientSecret, n as decryptStoredClientSecret, p as resolveSubjectIdentifier, r as deleteFromPrompt, s as getStoredToken, t as basicToClientCredentials, u as parseClientMetadata, y as mcpHandler } from "./utils-sQ4gYeh3.mjs";
|
|
2
|
-
import { t as PACKAGE_VERSION } from "./version-
|
|
2
|
+
import { t as PACKAGE_VERSION } from "./version-xqVKoocI.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";
|
|
@@ -474,7 +474,7 @@ async function checkVerificationValue(ctx, opts, code, client_id, redirect_uri)
|
|
|
474
474
|
error: "invalid_user"
|
|
475
475
|
});
|
|
476
476
|
if (verificationValue.query?.redirect_uri && verificationValue.query?.redirect_uri !== redirect_uri) throw new APIError("BAD_REQUEST", {
|
|
477
|
-
error_description: "
|
|
477
|
+
error_description: "redirect_uri mismatch",
|
|
478
478
|
error: "invalid_request"
|
|
479
479
|
});
|
|
480
480
|
return verificationValue;
|
|
@@ -1172,6 +1172,10 @@ async function checkOAuthClient(client, opts, settings) {
|
|
|
1172
1172
|
error: "invalid_client_metadata",
|
|
1173
1173
|
error_description: `pkce is required for registered clients.`
|
|
1174
1174
|
});
|
|
1175
|
+
if (settings?.isRegister && client.skip_consent) throw new APIError("BAD_REQUEST", {
|
|
1176
|
+
error: "invalid_client_metadata",
|
|
1177
|
+
error_description: "skip_consent cannot be set during dynamic client registration"
|
|
1178
|
+
});
|
|
1175
1179
|
}
|
|
1176
1180
|
async function createOAuthClientEndpoint(ctx, opts, settings) {
|
|
1177
1181
|
const body = ctx.body;
|
|
@@ -2805,11 +2809,12 @@ const oauthProvider = (options) => {
|
|
|
2805
2809
|
oauth2Authorize: createAuthEndpoint("/oauth2/authorize", {
|
|
2806
2810
|
method: "GET",
|
|
2807
2811
|
query: z.object({
|
|
2808
|
-
response_type: z.enum(["code"]),
|
|
2812
|
+
response_type: z.enum(["code"]).optional(),
|
|
2809
2813
|
client_id: z.string(),
|
|
2810
2814
|
redirect_uri: SafeUrlSchema.optional(),
|
|
2811
2815
|
scope: z.string().optional(),
|
|
2812
2816
|
state: z.string().optional(),
|
|
2817
|
+
request_uri: z.string().optional(),
|
|
2813
2818
|
code_challenge: z.string().optional(),
|
|
2814
2819
|
code_challenge_method: z.enum(["S256"]).optional(),
|
|
2815
2820
|
nonce: z.string().optional(),
|
|
@@ -2829,7 +2834,7 @@ const oauthProvider = (options) => {
|
|
|
2829
2834
|
{
|
|
2830
2835
|
name: "response_type",
|
|
2831
2836
|
in: "query",
|
|
2832
|
-
required:
|
|
2837
|
+
required: false,
|
|
2833
2838
|
schema: { type: "string" },
|
|
2834
2839
|
description: "OAuth2 response type (e.g., 'code')"
|
|
2835
2840
|
},
|
|
@@ -2864,6 +2869,13 @@ const oauthProvider = (options) => {
|
|
|
2864
2869
|
schema: { type: "string" },
|
|
2865
2870
|
description: "OAuth2 state parameter"
|
|
2866
2871
|
},
|
|
2872
|
+
{
|
|
2873
|
+
name: "request_uri",
|
|
2874
|
+
in: "query",
|
|
2875
|
+
required: false,
|
|
2876
|
+
schema: { type: "string" },
|
|
2877
|
+
description: "Pushed Authorization Request URI referencing stored parameters"
|
|
2878
|
+
},
|
|
2867
2879
|
{
|
|
2868
2880
|
name: "code_challenge",
|
|
2869
2881
|
in: "query",
|
|
@@ -3436,7 +3448,8 @@ const oauthProvider = (options) => {
|
|
|
3436
3448
|
"native",
|
|
3437
3449
|
"user-agent-based"
|
|
3438
3450
|
]).optional(),
|
|
3439
|
-
subject_type: z.enum(["public", "pairwise"]).optional()
|
|
3451
|
+
subject_type: z.enum(["public", "pairwise"]).optional(),
|
|
3452
|
+
skip_consent: z.boolean().optional()
|
|
3440
3453
|
}),
|
|
3441
3454
|
metadata: { openapi: {
|
|
3442
3455
|
description: "Register an OAuth2 application",
|
|
@@ -3698,8 +3711,21 @@ async function authorizeEndpoint(ctx, opts, settings) {
|
|
|
3698
3711
|
error_description: "request not found",
|
|
3699
3712
|
error: "invalid_request"
|
|
3700
3713
|
});
|
|
3701
|
-
|
|
3702
|
-
|
|
3714
|
+
let query = ctx.query;
|
|
3715
|
+
if (query.request_uri) {
|
|
3716
|
+
if (!opts.requestUriResolver) return handleRedirect(ctx, getErrorURL(ctx, "invalid_request_uri", "request_uri not supported"));
|
|
3717
|
+
const resolvedParams = await opts.requestUriResolver({
|
|
3718
|
+
requestUri: query.request_uri,
|
|
3719
|
+
clientId: query.client_id ?? "",
|
|
3720
|
+
ctx
|
|
3721
|
+
});
|
|
3722
|
+
if (!resolvedParams) return handleRedirect(ctx, getErrorURL(ctx, "invalid_request_uri", "request_uri is invalid or expired"));
|
|
3723
|
+
const urlClientId = query.client_id;
|
|
3724
|
+
query = resolvedParams;
|
|
3725
|
+
if (urlClientId) query.client_id = urlClientId;
|
|
3726
|
+
}
|
|
3727
|
+
ctx.query = query;
|
|
3728
|
+
await oAuthState.set({ query: serializeAuthorizationQuery(query).toString() });
|
|
3703
3729
|
if (!query.client_id) return handleRedirect(ctx, getErrorURL(ctx, "invalid_client", "client_id is required"));
|
|
3704
3730
|
if (!query.response_type) return handleRedirect(ctx, getErrorURL(ctx, "invalid_request", "response_type is required"));
|
|
3705
3731
|
const promptSet = ctx.query?.prompt ? parsePrompt(ctx.query?.prompt) : void 0;
|
|
@@ -3709,7 +3735,15 @@ async function authorizeEndpoint(ctx, opts, settings) {
|
|
|
3709
3735
|
const client = await getClient(ctx, opts, query.client_id);
|
|
3710
3736
|
if (!client) return handleRedirect(ctx, getErrorURL(ctx, "invalid_client", "client_id is required"));
|
|
3711
3737
|
if (client.disabled) return handleRedirect(ctx, getErrorURL(ctx, "client_disabled", "client is disabled"));
|
|
3712
|
-
if (!client.redirectUris?.find((url) =>
|
|
3738
|
+
if (!client.redirectUris?.find((url) => {
|
|
3739
|
+
if (url === query.redirect_uri) return true;
|
|
3740
|
+
try {
|
|
3741
|
+
const registered = new URL(url);
|
|
3742
|
+
const requested = new URL(query.redirect_uri);
|
|
3743
|
+
if ((registered.hostname === "127.0.0.1" || registered.hostname === "[::1]") && registered.hostname === requested.hostname && registered.pathname === requested.pathname && registered.protocol === requested.protocol && registered.search === requested.search) return true;
|
|
3744
|
+
} catch {}
|
|
3745
|
+
return false;
|
|
3746
|
+
}) || !query.redirect_uri) return handleRedirect(ctx, getErrorURL(ctx, "invalid_redirect", "invalid redirect uri"));
|
|
3713
3747
|
let requestedScopes = query.scope?.split(" ").filter((s) => s);
|
|
3714
3748
|
if (requestedScopes) {
|
|
3715
3749
|
const validScopes = new Set(client.scopes ?? opts.scopes);
|
|
@@ -3814,6 +3848,11 @@ async function authorizeEndpoint(ctx, opts, settings) {
|
|
|
3814
3848
|
referenceId
|
|
3815
3849
|
});
|
|
3816
3850
|
}
|
|
3851
|
+
function serializeAuthorizationQuery(query) {
|
|
3852
|
+
const params = new URLSearchParams();
|
|
3853
|
+
for (const [key, value] of Object.entries(query)) if (value != null) params.set(key, String(value));
|
|
3854
|
+
return params;
|
|
3855
|
+
}
|
|
3817
3856
|
async function redirectWithAuthorizationCode(ctx, opts, verificationValue) {
|
|
3818
3857
|
const code = generateRandomString(32, "a-z", "A-Z", "0-9");
|
|
3819
3858
|
const iat = Math.floor(Date.now() / 1e3);
|
|
@@ -3824,7 +3863,7 @@ async function redirectWithAuthorizationCode(ctx, opts, verificationValue) {
|
|
|
3824
3863
|
expiresAt: /* @__PURE__ */ new Date(exp * 1e3),
|
|
3825
3864
|
value: JSON.stringify({
|
|
3826
3865
|
type: "authorization_code",
|
|
3827
|
-
query:
|
|
3866
|
+
query: verificationValue.query,
|
|
3828
3867
|
userId: verificationValue.userId,
|
|
3829
3868
|
sessionId: verificationValue?.sessionId,
|
|
3830
3869
|
referenceId: verificationValue.referenceId,
|
|
@@ -3854,7 +3893,7 @@ async function redirectWithPromptCode(ctx, opts, type, page) {
|
|
|
3854
3893
|
}
|
|
3855
3894
|
async function signParams(ctx, opts) {
|
|
3856
3895
|
const exp = Math.floor(Date.now() / 1e3) + (opts.codeExpiresIn ?? 600);
|
|
3857
|
-
const params =
|
|
3896
|
+
const params = serializeAuthorizationQuery(ctx.query);
|
|
3858
3897
|
params.set("exp", String(exp));
|
|
3859
3898
|
const signature = await makeSignature(params.toString(), ctx.context.secret);
|
|
3860
3899
|
params.append("sig", signature);
|