@better-auth/oauth-provider 1.7.0-beta.2 → 1.7.0-beta.4
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-CderPEmR.mjs → client-assertion-DLMKVgoj.mjs} +4 -4
- package/dist/client-resource.d.mts +13 -6
- package/dist/client-resource.mjs +2 -2
- package/dist/client.d.mts +1 -1
- package/dist/client.mjs +1 -1
- package/dist/index.d.mts +8 -7
- package/dist/index.mjs +397 -172
- package/dist/{oauth-DJcZ8MMZ.d.mts → oauth-Vt3lTNHX.d.mts} +79 -20
- package/dist/{oauth-CU79t-eG.d.mts → oauth-q7dn10NU.d.mts} +51 -10
- package/dist/{utils-Cx_XnD9i.mjs → utils-DKBWQ8fe.mjs} +69 -26
- package/dist/{version-CZxZ64qJ.mjs → version-nFnRm-a3.mjs} +1 -1
- package/package.json +6 -6
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { APIError } from "better-call";
|
|
2
|
+
import { decodeBasicCredentials } from "@better-auth/core/oauth2";
|
|
2
3
|
import { constantTimeEqual, makeSignature, symmetricDecrypt, symmetricEncrypt } from "better-auth/crypto";
|
|
3
4
|
import { BetterAuthError } from "@better-auth/core/error";
|
|
4
|
-
import {
|
|
5
|
+
import { base64Url } from "@better-auth/utils/base64";
|
|
5
6
|
import { createHash } from "@better-auth/utils/hash";
|
|
6
7
|
//#region src/utils/index.ts
|
|
7
8
|
var TTLCache = class {
|
|
@@ -74,6 +75,47 @@ function resolveSessionAuthTime(value) {
|
|
|
74
75
|
if (!nested || typeof nested !== "object") return;
|
|
75
76
|
return normalizeTimestampValue(nested.createdAt) ?? normalizeTimestampValue(nested.created_at);
|
|
76
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Normalizes OAuth resource values into a non-empty string array.
|
|
80
|
+
*/
|
|
81
|
+
function toResourceList(value) {
|
|
82
|
+
if (typeof value === "string") return [value];
|
|
83
|
+
if (!value?.length) return void 0;
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Normalizes audience values for JWT claims.
|
|
88
|
+
*/
|
|
89
|
+
function toAudienceClaim(audience) {
|
|
90
|
+
if (typeof audience === "string") return audience;
|
|
91
|
+
if (!audience?.length) return void 0;
|
|
92
|
+
return audience.length === 1 ? audience.at(0) : audience;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Checks the resource parameter, if provided,
|
|
96
|
+
* and returns either a valid audience or a tagged validation error.
|
|
97
|
+
*/
|
|
98
|
+
async function checkResource(ctx, opts, resource, scopes) {
|
|
99
|
+
const normalizedResource = toResourceList(resource);
|
|
100
|
+
const audience = normalizedResource ? [...normalizedResource] : void 0;
|
|
101
|
+
if (audience) {
|
|
102
|
+
const hasOpenId = scopes.includes("openid");
|
|
103
|
+
const baseUrl = ctx.context.baseURL;
|
|
104
|
+
const userInfoEndpoint = `${baseUrl}/oauth2/userinfo`;
|
|
105
|
+
if (hasOpenId && !audience.includes(userInfoEndpoint)) audience.push(userInfoEndpoint);
|
|
106
|
+
const filteredValidAudiences = opts.validAudiences?.filter((aud) => aud.length);
|
|
107
|
+
const validAudiences = new Set(filteredValidAudiences?.length ? filteredValidAudiences : [baseUrl]);
|
|
108
|
+
if (hasOpenId) validAudiences.add(userInfoEndpoint);
|
|
109
|
+
for (const aud of audience) if (!validAudiences.has(aud)) return {
|
|
110
|
+
success: false,
|
|
111
|
+
error: "invalid_resource"
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
success: true,
|
|
116
|
+
audience: toAudienceClaim(audience)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
77
119
|
const cachedTrustedClients = new TTLCache();
|
|
78
120
|
async function verifyOAuthQueryParams(oauth_query, secret) {
|
|
79
121
|
const queryParams = new URLSearchParams(oauth_query);
|
|
@@ -228,23 +270,20 @@ async function getStoredToken(storageMethod = "hashed", token, type) {
|
|
|
228
270
|
*
|
|
229
271
|
* @internal
|
|
230
272
|
*/
|
|
273
|
+
const BASIC_SCHEME_PREFIX = /^Basic +/i;
|
|
231
274
|
function basicToClientCredentials(authorization) {
|
|
232
|
-
if (
|
|
233
|
-
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
|
|
275
|
+
if (!BASIC_SCHEME_PREFIX.test(authorization)) return;
|
|
276
|
+
try {
|
|
277
|
+
const { clientId, clientSecret } = decodeBasicCredentials(authorization);
|
|
278
|
+
return {
|
|
279
|
+
client_id: clientId,
|
|
280
|
+
client_secret: clientSecret
|
|
281
|
+
};
|
|
282
|
+
} catch {
|
|
283
|
+
throw new APIError("BAD_REQUEST", {
|
|
241
284
|
error_description: "invalid authorization header format",
|
|
242
285
|
error: "invalid_client"
|
|
243
286
|
});
|
|
244
|
-
return {
|
|
245
|
-
client_id: id,
|
|
246
|
-
client_secret: secret
|
|
247
|
-
};
|
|
248
287
|
}
|
|
249
288
|
}
|
|
250
289
|
/**
|
|
@@ -324,7 +363,7 @@ async function extractClientCredentials(ctx, opts, expectedAudience) {
|
|
|
324
363
|
error_description: "client_assertion cannot be combined with client_secret or Basic auth",
|
|
325
364
|
error: "invalid_client"
|
|
326
365
|
});
|
|
327
|
-
const { verifyClientAssertion: verify } = await import("./client-assertion-
|
|
366
|
+
const { verifyClientAssertion: verify } = await import("./client-assertion-DLMKVgoj.mjs").then((n) => n.t);
|
|
328
367
|
const result = await verify(ctx, opts, body.client_assertion, body.client_assertion_type, body.client_id, expectedAudience);
|
|
329
368
|
return {
|
|
330
369
|
method: "private_key_jwt",
|
|
@@ -404,20 +443,24 @@ function searchParamsToQuery(params) {
|
|
|
404
443
|
}
|
|
405
444
|
return result;
|
|
406
445
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
446
|
+
const signedQueryIssuedAtParam = "ba_iat";
|
|
447
|
+
const postLoginClearedParam = "ba_pl";
|
|
448
|
+
function getSignedQueryIssuedAt(oauthQuery) {
|
|
449
|
+
const raw = new URLSearchParams(oauthQuery).get(signedQueryIssuedAtParam);
|
|
450
|
+
if (!raw) return null;
|
|
451
|
+
const issuedAt = Number(raw);
|
|
452
|
+
if (!Number.isFinite(issuedAt) || issuedAt <= 0) return null;
|
|
453
|
+
return new Date(issuedAt);
|
|
454
|
+
}
|
|
455
|
+
function removePromptFromQuery(query, prompt) {
|
|
456
|
+
const nextQuery = new URLSearchParams(query);
|
|
457
|
+
const prompts = nextQuery.get("prompt")?.split(" ");
|
|
415
458
|
const foundPrompt = prompts?.findIndex((v) => v === prompt) ?? -1;
|
|
416
459
|
if (foundPrompt >= 0) {
|
|
417
460
|
prompts?.splice(foundPrompt, 1);
|
|
418
|
-
prompts?.length ?
|
|
461
|
+
prompts?.length ? nextQuery.set("prompt", prompts.join(" ")) : nextQuery.delete("prompt");
|
|
419
462
|
}
|
|
420
|
-
return
|
|
463
|
+
return nextQuery;
|
|
421
464
|
}
|
|
422
465
|
var PKCERequirementErrors = /* @__PURE__ */ function(PKCERequirementErrors) {
|
|
423
466
|
PKCERequirementErrors["PUBLIC_CLIENT"] = "pkce is required for public clients";
|
|
@@ -446,4 +489,4 @@ function isPKCERequired(client, requestedScopes) {
|
|
|
446
489
|
return false;
|
|
447
490
|
}
|
|
448
491
|
//#endregion
|
|
449
|
-
export {
|
|
492
|
+
export { toAudienceClaim as C, verifyOAuthQueryParams as D, validateClientCredentials as E, storeToken as S, toResourceList as T, resolveSessionAuthTime as _, getClient as a, signedQueryIssuedAtParam as b, getSignedQueryIssuedAt as c, mergeDiscoveryMetadata as d, normalizeTimestampValue as f, removePromptFromQuery as g, postLoginClearedParam as h, extractClientCredentials as i, getStoredToken as l, parsePrompt as m, decryptStoredClientSecret as n, getJwtPlugin as o, parseClientMetadata as p, destructureCredentials as r, getOAuthProviderPlugin as s, checkResource as t, isPKCERequired as u, resolveSubjectIdentifier as v, toClientDiscoveryArray as w, storeClientSecret as x, searchParamsToQuery as y };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/oauth-provider",
|
|
3
|
-
"version": "1.7.0-beta.
|
|
3
|
+
"version": "1.7.0-beta.4",
|
|
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.7.0-beta.
|
|
68
|
-
"better-auth": "1.7.0-beta.
|
|
67
|
+
"@better-auth/core": "1.7.0-beta.4",
|
|
68
|
+
"better-auth": "1.7.0-beta.4"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"@better-auth/utils": "0.4.
|
|
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.7.0-beta.
|
|
75
|
-
"better-auth": "^1.7.0-beta.
|
|
74
|
+
"@better-auth/core": "^1.7.0-beta.4",
|
|
75
|
+
"better-auth": "^1.7.0-beta.4"
|
|
76
76
|
},
|
|
77
77
|
"scripts": {
|
|
78
78
|
"build": "tsdown",
|