@better-auth/oauth-provider 1.7.10 → 1.8.0-beta.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/{authorize-dkOG8GqZ.mjs → authorize-Dg976Ug0.mjs} +583 -433
- package/dist/client-resource.d.mts +2 -2
- package/dist/client-resource.mjs +2 -2
- package/dist/client.d.mts +1 -1
- package/dist/client.mjs +1 -1
- package/dist/index-DVydGHlT.d.mts +275 -0
- package/dist/index.d.mts +4 -203
- package/dist/index.mjs +196 -40
- package/dist/internal.d.mts +109 -22
- package/dist/internal.mjs +4 -2
- package/dist/{introspect-BVm_zFQC.mjs → introspect-DdmCPEHN.mjs} +294 -227
- package/dist/{oauth-DXiqbRzK.d.mts → oauth-CzT1PvAY.d.mts} +359 -13
- package/dist/{oauth-Cse_eZ6i.d.mts → oauth-DfH-ghKj.d.mts} +163 -87
- package/dist/{utils-DfMNRh3J.mjs → utils-D-CUrvd1.mjs} +287 -20
- package/dist/{version-aKfgWHzo.mjs → version-BwHks7Wg.mjs} +1 -1
- package/package.json +6 -6
- package/dist/client-jwks-DY2QBrsl.d.mts +0 -25
|
@@ -6,7 +6,146 @@ import { BetterAuthError } from "@better-auth/core/error";
|
|
|
6
6
|
import { CLIENT_ASSERTION_TYPE, decodeBasicCredentials } from "@better-auth/core/oauth2";
|
|
7
7
|
import { base64Url } from "@better-auth/utils/base64";
|
|
8
8
|
import { createHash } from "@better-auth/utils/hash";
|
|
9
|
-
|
|
9
|
+
//#region src/client-metadata.ts
|
|
10
|
+
const OAUTH_CLIENT_RECORD_FIELD_NAMES = Object.freeze(Object.keys({
|
|
11
|
+
clientId: true,
|
|
12
|
+
clientSecret: true,
|
|
13
|
+
clientDiscoveryId: true,
|
|
14
|
+
disabled: true,
|
|
15
|
+
scopes: true,
|
|
16
|
+
clientCredentialsScopes: true,
|
|
17
|
+
userId: true,
|
|
18
|
+
createdAt: true,
|
|
19
|
+
updatedAt: true,
|
|
20
|
+
expiresAt: true,
|
|
21
|
+
name: true,
|
|
22
|
+
uri: true,
|
|
23
|
+
icon: true,
|
|
24
|
+
contacts: true,
|
|
25
|
+
tos: true,
|
|
26
|
+
policy: true,
|
|
27
|
+
softwareId: true,
|
|
28
|
+
softwareVersion: true,
|
|
29
|
+
softwareStatement: true,
|
|
30
|
+
redirectUris: true,
|
|
31
|
+
postLogoutRedirectUris: true,
|
|
32
|
+
backchannelLogoutUri: true,
|
|
33
|
+
backchannelLogoutSessionRequired: true,
|
|
34
|
+
frontchannelLogoutUri: true,
|
|
35
|
+
frontchannelLogoutSessionRequired: true,
|
|
36
|
+
tokenEndpointAuthMethod: true,
|
|
37
|
+
grantTypes: true,
|
|
38
|
+
responseTypes: true,
|
|
39
|
+
applicationType: true,
|
|
40
|
+
jwks: true,
|
|
41
|
+
jwksUri: true,
|
|
42
|
+
requirePKCE: true,
|
|
43
|
+
dpopBoundAccessTokens: true,
|
|
44
|
+
skipConsent: true,
|
|
45
|
+
enableEndSession: true,
|
|
46
|
+
subjectType: true,
|
|
47
|
+
sectorIdentifier: true,
|
|
48
|
+
referenceId: true,
|
|
49
|
+
metadata: true
|
|
50
|
+
}));
|
|
51
|
+
/**
|
|
52
|
+
* Canonical wire fields emitted by schemaToOAuth. They are mapped explicitly
|
|
53
|
+
* and therefore must never also survive inside the opaque metadata envelope.
|
|
54
|
+
*/
|
|
55
|
+
const OAUTH_CLIENT_WIRE_FIELD_NAMES = [
|
|
56
|
+
"client_id",
|
|
57
|
+
"client_secret",
|
|
58
|
+
"client_secret_expires_at",
|
|
59
|
+
"scope",
|
|
60
|
+
"user_id",
|
|
61
|
+
"client_id_issued_at",
|
|
62
|
+
"client_name",
|
|
63
|
+
"client_uri",
|
|
64
|
+
"logo_uri",
|
|
65
|
+
"contacts",
|
|
66
|
+
"tos_uri",
|
|
67
|
+
"policy_uri",
|
|
68
|
+
"jwks",
|
|
69
|
+
"jwks_uri",
|
|
70
|
+
"software_id",
|
|
71
|
+
"software_version",
|
|
72
|
+
"software_statement",
|
|
73
|
+
"redirect_uris",
|
|
74
|
+
"post_logout_redirect_uris",
|
|
75
|
+
"backchannel_logout_uri",
|
|
76
|
+
"backchannel_logout_session_required",
|
|
77
|
+
"frontchannel_logout_uri",
|
|
78
|
+
"frontchannel_logout_session_required",
|
|
79
|
+
"token_endpoint_auth_method",
|
|
80
|
+
"grant_types",
|
|
81
|
+
"response_types",
|
|
82
|
+
"application_type",
|
|
83
|
+
"disabled",
|
|
84
|
+
"skip_consent",
|
|
85
|
+
"enable_end_session",
|
|
86
|
+
"require_pkce",
|
|
87
|
+
"dpop_bound_access_tokens",
|
|
88
|
+
"subject_type",
|
|
89
|
+
"reference_id"
|
|
90
|
+
];
|
|
91
|
+
const OPAQUE_METADATA_RESERVED_FIELDS = new Set([
|
|
92
|
+
...OAUTH_CLIENT_RECORD_FIELD_NAMES,
|
|
93
|
+
...OAUTH_CLIENT_WIRE_FIELD_NAMES,
|
|
94
|
+
"public",
|
|
95
|
+
"type",
|
|
96
|
+
"resources",
|
|
97
|
+
"client_credentials_scopes"
|
|
98
|
+
]);
|
|
99
|
+
const CIMD_FORBIDDEN_SERVER_FIELD_NAMES = new Set([
|
|
100
|
+
"disabled",
|
|
101
|
+
"client_secret",
|
|
102
|
+
"client_secret_expires_at",
|
|
103
|
+
"client_id_issued_at",
|
|
104
|
+
"skip_consent",
|
|
105
|
+
"enable_end_session",
|
|
106
|
+
"require_pkce",
|
|
107
|
+
"reference_id",
|
|
108
|
+
"user_id",
|
|
109
|
+
"resources",
|
|
110
|
+
"clientSecret",
|
|
111
|
+
"clientDiscoveryId",
|
|
112
|
+
"sectorIdentifier",
|
|
113
|
+
"skipConsent",
|
|
114
|
+
"enableEndSession",
|
|
115
|
+
"requirePKCE",
|
|
116
|
+
"referenceId",
|
|
117
|
+
"userId",
|
|
118
|
+
"clientId",
|
|
119
|
+
"applicationType",
|
|
120
|
+
"tokenEndpointAuthMethod",
|
|
121
|
+
"redirectUris",
|
|
122
|
+
"postLogoutRedirectUris",
|
|
123
|
+
"grantTypes",
|
|
124
|
+
"responseTypes",
|
|
125
|
+
"scopes",
|
|
126
|
+
"expiresAt",
|
|
127
|
+
"createdAt",
|
|
128
|
+
"updatedAt",
|
|
129
|
+
"softwareId",
|
|
130
|
+
"softwareVersion",
|
|
131
|
+
"softwareStatement",
|
|
132
|
+
"backchannelLogoutUri",
|
|
133
|
+
"backchannelLogoutSessionRequired",
|
|
134
|
+
"jwksUri",
|
|
135
|
+
"dpopBoundAccessTokens",
|
|
136
|
+
"subjectType"
|
|
137
|
+
]);
|
|
138
|
+
function isForbiddenCimdClientMetadataField(field) {
|
|
139
|
+
return CIMD_FORBIDDEN_SERVER_FIELD_NAMES.has(field);
|
|
140
|
+
}
|
|
141
|
+
function isReservedOAuthClientMetadataField(field) {
|
|
142
|
+
return OPAQUE_METADATA_RESERVED_FIELDS.has(field);
|
|
143
|
+
}
|
|
144
|
+
function stripReservedOAuthClientMetadataExtensions(metadata) {
|
|
145
|
+
if (!metadata) return void 0;
|
|
146
|
+
return Object.fromEntries(Object.entries(metadata).filter(([field]) => !OPAQUE_METADATA_RESERVED_FIELDS.has(field)));
|
|
147
|
+
}
|
|
148
|
+
//#endregion
|
|
10
149
|
//#region src/extensions.ts
|
|
11
150
|
const DEFAULT_GRANT_TYPES = [
|
|
12
151
|
"authorization_code",
|
|
@@ -71,11 +210,16 @@ function collectExtensionKeys(extension) {
|
|
|
71
210
|
}
|
|
72
211
|
const clientDiscoveryIds = (extension.clientDiscovery ? Array.isArray(extension.clientDiscovery) ? extension.clientDiscovery : [extension.clientDiscovery] : []).map((discovery) => discovery.id);
|
|
73
212
|
for (const clientDiscoveryId of clientDiscoveryIds) assertNonEmptyExtensionValue("client discovery id", clientDiscoveryId);
|
|
213
|
+
for (const field of extension.clientMetadata?.fields ?? []) {
|
|
214
|
+
assertNonEmptyExtensionValue("client metadata field", field);
|
|
215
|
+
if (isReservedOAuthClientMetadataField(field)) throw new BetterAuthError(`OAuth Provider extension client metadata field is reserved: ${field}`);
|
|
216
|
+
}
|
|
74
217
|
return {
|
|
75
218
|
grantTypes,
|
|
76
219
|
authMethods,
|
|
77
220
|
assertionTypes,
|
|
78
|
-
clientDiscoveryIds
|
|
221
|
+
clientDiscoveryIds,
|
|
222
|
+
interactionRequestParameters: Object.keys(extension.interactionRequests ?? {})
|
|
79
223
|
};
|
|
80
224
|
}
|
|
81
225
|
function assertNoDuplicateAcrossExtensions(label, values) {
|
|
@@ -98,6 +242,7 @@ function validateOAuthProviderExtensions(extensions) {
|
|
|
98
242
|
assertNoDuplicateAcrossExtensions("token_endpoint_auth_method", keys.flatMap((k) => k.authMethods));
|
|
99
243
|
assertNoDuplicateAcrossExtensions("client_assertion_type", keys.flatMap((k) => k.assertionTypes));
|
|
100
244
|
assertNoDuplicateAcrossExtensions("client discovery id", keys.flatMap((k) => k.clientDiscoveryIds));
|
|
245
|
+
assertNoDuplicateAcrossExtensions("interaction request parameter", keys.flatMap((k) => k.interactionRequestParameters));
|
|
101
246
|
}
|
|
102
247
|
function getOAuthProviderExtensions(opts) {
|
|
103
248
|
return opts.extensions ?? [];
|
|
@@ -154,6 +299,23 @@ function getExtensionGrantTypes(opts) {
|
|
|
154
299
|
function getSupportedGrantTypes(opts) {
|
|
155
300
|
return Array.from(new Set([...opts.grantTypes ?? DEFAULT_GRANT_TYPES, ...getExtensionGrantTypes(opts)]));
|
|
156
301
|
}
|
|
302
|
+
/**
|
|
303
|
+
* Finds the interaction request a query identifies, such as a device approval
|
|
304
|
+
* keyed by `user_code`. Authorization requests, which carry `response_type` or
|
|
305
|
+
* a pushed `request_uri`, never match.
|
|
306
|
+
*/
|
|
307
|
+
function getExtensionInteractionRequest(opts, query) {
|
|
308
|
+
const parameters = query;
|
|
309
|
+
if (parameters.response_type !== void 0 || parameters.request_uri !== void 0) return;
|
|
310
|
+
for (const extension of getOAuthProviderExtensions(opts)) for (const [parameter, handler] of Object.entries(extension.interactionRequests ?? {})) {
|
|
311
|
+
const value = parameters[parameter];
|
|
312
|
+
if (typeof value === "string" && value) return {
|
|
313
|
+
parameter,
|
|
314
|
+
handler,
|
|
315
|
+
value
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
}
|
|
157
319
|
function getExtensionGrantHandler(opts, grantType) {
|
|
158
320
|
for (const extension of getOAuthProviderExtensions(opts)) {
|
|
159
321
|
const handler = extension.grants?.[grantType];
|
|
@@ -231,6 +393,29 @@ function collectExtensionIdTokenClaims(opts, input) {
|
|
|
231
393
|
function collectExtensionUserInfoClaims(opts, input) {
|
|
232
394
|
return collectClaims(opts, (extension) => extension.claims?.userInfo?.(input));
|
|
233
395
|
}
|
|
396
|
+
/** Whether any extension declares client metadata fields or a validator. */
|
|
397
|
+
function hasExtensionClientMetadata(opts) {
|
|
398
|
+
return getOAuthProviderExtensions(opts).some((extension) => extension.clientMetadata);
|
|
399
|
+
}
|
|
400
|
+
/** Registration fields that extensions define, stored in the client's `metadata`. */
|
|
401
|
+
function getExtensionClientMetadataFields(opts) {
|
|
402
|
+
return new Set(getOAuthProviderExtensions(opts).flatMap((extension) => extension.clientMetadata?.fields ?? []));
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Runs every extension's client metadata validator, in registration order.
|
|
406
|
+
* Extensions read their fields from `metadata` only, so `metadata` and
|
|
407
|
+
* declared fields are removed from the client they receive; a metadata
|
|
408
|
+
* document carries declared fields at its top level.
|
|
409
|
+
*/
|
|
410
|
+
async function validateExtensionClientMetadata(opts, client, metadata) {
|
|
411
|
+
const { metadata: _metadata, ...coreClient } = client;
|
|
412
|
+
const extensionFields = getExtensionClientMetadataFields(opts);
|
|
413
|
+
const input = {
|
|
414
|
+
client: Object.fromEntries(Object.entries(coreClient).filter(([field]) => !extensionFields.has(field))),
|
|
415
|
+
metadata: stripReservedOAuthClientMetadataExtensions(metadata) ?? {}
|
|
416
|
+
};
|
|
417
|
+
for (const extension of getOAuthProviderExtensions(opts)) await extension.clientMetadata?.validate?.(input);
|
|
418
|
+
}
|
|
234
419
|
/**
|
|
235
420
|
* Whether any registered extension contributes UserInfo claims. Lets the
|
|
236
421
|
* UserInfo endpoint skip loading the client when nothing needs it.
|
|
@@ -295,21 +480,6 @@ const getJwtPlugin = (ctx) => {
|
|
|
295
480
|
if (!plugin) throw new BetterAuthError("jwt_config");
|
|
296
481
|
return plugin;
|
|
297
482
|
};
|
|
298
|
-
const joseInfrastructureErrorCodes = new Set([
|
|
299
|
-
errors.JWKSTimeout.code,
|
|
300
|
-
errors.JWKSInvalid.code,
|
|
301
|
-
errors.JWKSMultipleMatchingKeys.code
|
|
302
|
-
]);
|
|
303
|
-
/**
|
|
304
|
-
* Whether a JWT verification error comes from the token itself (malformed,
|
|
305
|
-
* bad signature, unsupported alg, unknown kid, failed claim checks), as
|
|
306
|
-
* opposed to a key set failure that should still surface as a server error.
|
|
307
|
-
*
|
|
308
|
-
* @internal
|
|
309
|
-
*/
|
|
310
|
-
function isInvalidJwtError(error) {
|
|
311
|
-
return error instanceof errors.JOSEError && !joseInfrastructureErrorCodes.has(error.code);
|
|
312
|
-
}
|
|
313
483
|
/**
|
|
314
484
|
* Normalizes timestamp-like values returned by adapters.
|
|
315
485
|
*
|
|
@@ -557,6 +727,53 @@ function throwInvalidAuthenticationRequest(errorDescription) {
|
|
|
557
727
|
});
|
|
558
728
|
}
|
|
559
729
|
/**
|
|
730
|
+
* Re-reads a request's raw `application/x-www-form-urlencoded` body, keeping
|
|
731
|
+
* every value of a repeated key. better-call's form-body parser keeps only the
|
|
732
|
+
* last one, so `resource=https://a&resource=https://b` reaches the handler as
|
|
733
|
+
* `{ resource: "https://b" }`. Query strings are unaffected: the router keeps
|
|
734
|
+
* repeated query keys as arrays.
|
|
735
|
+
*
|
|
736
|
+
* Returns `undefined` for other media types or an unreadable or empty body.
|
|
737
|
+
* The endpoint MUST set `cloneRequest: true`, because the body stream is read
|
|
738
|
+
* a second time.
|
|
739
|
+
*
|
|
740
|
+
* @internal
|
|
741
|
+
*/
|
|
742
|
+
async function readFormParams(request) {
|
|
743
|
+
if (!(request.headers.get("content-type")?.toLowerCase() ?? "").includes("application/x-www-form-urlencoded")) return;
|
|
744
|
+
let text;
|
|
745
|
+
try {
|
|
746
|
+
text = await request.clone().text();
|
|
747
|
+
} catch {
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
return text ? new URLSearchParams(text) : void 0;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Applies RFC 6749 §3.2 to a form body the parser collapsed to one value per
|
|
754
|
+
* key: a parameter sent without a value counts as omitted, and a parameter
|
|
755
|
+
* sent more than once is rejected with `invalid_request`. A name in
|
|
756
|
+
* `repeatable`, such as RFC 8707 `resource`, keeps every value as an array
|
|
757
|
+
* when it repeats. A value a `before` hook replaced is left as the hook set it.
|
|
758
|
+
*
|
|
759
|
+
* @internal
|
|
760
|
+
*/
|
|
761
|
+
function applyFormParams(params, body, repeatable = []) {
|
|
762
|
+
const merged = { ...body };
|
|
763
|
+
for (const name of new Set(params.keys())) {
|
|
764
|
+
const raw = params.getAll(name);
|
|
765
|
+
const values = raw.filter(Boolean);
|
|
766
|
+
if (values.length > 1 && !repeatable.includes(name)) throw new APIError("BAD_REQUEST", {
|
|
767
|
+
error: "invalid_request",
|
|
768
|
+
error_description: `${name} must not be repeated`
|
|
769
|
+
});
|
|
770
|
+
if (merged[name] !== raw.at(-1)) continue;
|
|
771
|
+
if (values.length === 0) delete merged[name];
|
|
772
|
+
else merged[name] = values.length === 1 ? values[0] : values;
|
|
773
|
+
}
|
|
774
|
+
return merged;
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
560
777
|
* Normalizes client identification and authentication parameters while
|
|
561
778
|
* enforcing RFC 6749 §2.3 and RFC 8628 §3.1 cardinality. Empty values are
|
|
562
779
|
* omitted. Client identification remains separate from authentication-method
|
|
@@ -635,6 +852,37 @@ function clientAllowsGrant(client, grantType) {
|
|
|
635
852
|
return allowedGrants.includes(grantType);
|
|
636
853
|
}
|
|
637
854
|
/**
|
|
855
|
+
* Throws an OAuth error response (RFC 6749 §5.2).
|
|
856
|
+
*
|
|
857
|
+
* @internal
|
|
858
|
+
*/
|
|
859
|
+
function tokenError(status, error, errorDescription) {
|
|
860
|
+
throw new APIError(status, {
|
|
861
|
+
error,
|
|
862
|
+
error_description: errorDescription
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Splits a space-delimited OAuth `scope` value (RFC 6749 §3.3).
|
|
867
|
+
*
|
|
868
|
+
* @internal
|
|
869
|
+
*/
|
|
870
|
+
function parseScopes(scope) {
|
|
871
|
+
const normalized = scope?.trim();
|
|
872
|
+
return normalized ? normalized.split(/\s+/) : [];
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Whether a stored consent covers every requested scope and resource. Shared by
|
|
876
|
+
* authorization and grants that need prior consent, so the coverage rule cannot
|
|
877
|
+
* drift between them. Each caller still chooses which consent rows to check.
|
|
878
|
+
*
|
|
879
|
+
* @internal
|
|
880
|
+
*/
|
|
881
|
+
function consentCovers(consent, scopes, resources) {
|
|
882
|
+
const consentedResources = consent.resources ?? [];
|
|
883
|
+
return scopes.every((scope) => consent.scopes.includes(scope)) && resources.every((resource) => consentedResources.includes(resource));
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
638
886
|
* Validates requested scopes against a registered client's allowed scopes.
|
|
639
887
|
*
|
|
640
888
|
* @internal
|
|
@@ -738,7 +986,7 @@ async function extractClientCredentials(ctx, opts, expectedAudience) {
|
|
|
738
986
|
confirmation: result.confirmation
|
|
739
987
|
};
|
|
740
988
|
}
|
|
741
|
-
const { verifyClientAssertion: verify } = await import("./authorize-
|
|
989
|
+
const { verifyClientAssertion: verify } = await import("./authorize-Dg976Ug0.mjs").then((n) => n.s);
|
|
742
990
|
return {
|
|
743
991
|
kind: "pre_verified",
|
|
744
992
|
method: "private_key_jwt",
|
|
@@ -787,12 +1035,31 @@ function parsePrompt(prompt) {
|
|
|
787
1035
|
return new Set(set);
|
|
788
1036
|
}
|
|
789
1037
|
/**
|
|
790
|
-
*
|
|
1038
|
+
* Derives the pairwise sector to store for a client.
|
|
1039
|
+
*
|
|
1040
|
+
* Only an `https` host identifies who controls a redirect URI, so clients
|
|
1041
|
+
* whose redirect URIs are all `https` share the sector of that host. Any app
|
|
1042
|
+
* can register a custom scheme, and any local process can listen on a
|
|
1043
|
+
* loopback port, so every other client gets a sector of its own. `/` cannot
|
|
1044
|
+
* appear in a URL host, so a client sector never equals a host sector.
|
|
1045
|
+
*
|
|
1046
|
+
* @see https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg
|
|
1047
|
+
* @internal
|
|
1048
|
+
*/
|
|
1049
|
+
function deriveSectorIdentifier(clientId, redirectUris) {
|
|
1050
|
+
const urls = (redirectUris ?? []).map((uri) => new URL(uri));
|
|
1051
|
+
const first = urls[0];
|
|
1052
|
+
return first && urls.every((url) => url.protocol === "https:") ? first.host : `client/${clientId}`;
|
|
1053
|
+
}
|
|
1054
|
+
/**
|
|
1055
|
+
* Returns the client's stored pairwise sector, or for a client created before
|
|
1056
|
+
* sectors were stored, the host of its first redirect URI.
|
|
791
1057
|
*
|
|
792
1058
|
* @see https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg
|
|
793
1059
|
* @internal
|
|
794
1060
|
*/
|
|
795
1061
|
function getSectorIdentifier(client) {
|
|
1062
|
+
if (client.sectorIdentifier) return client.sectorIdentifier;
|
|
796
1063
|
const uri = client.redirectUris?.[0];
|
|
797
1064
|
if (!uri) throw new BetterAuthError("Client has no redirect URIs for sector identifier");
|
|
798
1065
|
return new URL(uri).host;
|
|
@@ -920,4 +1187,4 @@ function isPKCERequired(client, request) {
|
|
|
920
1187
|
return false;
|
|
921
1188
|
}
|
|
922
1189
|
//#endregion
|
|
923
|
-
export {
|
|
1190
|
+
export { validateOAuthProviderExtensions as $, storeClientSecret as A, collectExtensionIdTokenClaims as B, parseScopes as C, resolveSessionAuthTime as D, removePromptFromQuery as E, validateClientCredentials as F, getExtensionGrantHandler as G, extendOAuthProvider as H, validateClientScopes as I, getSupportedGrantTypes as J, getExtensionInteractionRequest as K, verifyOAuthQueryParams as L, toAudienceClaim as M, toResourceList as N, resolveSubjectIdentifier as O, tokenError as P, validateExtensionClientMetadata as Q, applyOAuthProviderMetadataExtensions as R, parsePrompt as S, removeMaxAgeFromQuery as T, getClientDiscoveries as U, collectExtensionUserInfoClaims as V, getExtensionClientMetadataFields as W, hasUserInfoClaimExtension as X, hasExtensionClientMetadata as Y, isExtensionTokenEndpointAuthMethod as Z, mergeDiscoveryMetadata as _, decryptStoredClientSecret as a, parseBearerToken as b, extractClientCredentials as c, getConsentReferenceId as d, isForbiddenCimdClientMetadataField as et, getJwtPlugin as f, isSessionFreshForSignedQuery as g, isPKCERequired as h, consentCovers as i, storeToken as j, searchParamsToQuery as k, findConsent as l, getStoredToken as m, assertNotTrustedClient as n, deriveSectorIdentifier as o, getOAuthProviderPlugin as p, getSupportedAuthMethods as q, clientAllowsGrant as r, destructureCredentials as s, applyFormParams as t, stripReservedOAuthClientMetadataExtensions as tt, getClient as u, normalizeClientAuthenticationParameters as v, readFormParams as w, parseClientMetadata as x, normalizeTimestampValue as y, collectExtensionAccessTokenClaims as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/oauth-provider",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0-beta.1",
|
|
4
4
|
"description": "An oauth provider plugin for Better Auth",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -71,16 +71,16 @@
|
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"listhen": "^1.9.0",
|
|
73
73
|
"tsdown": "0.21.10",
|
|
74
|
-
"@better-auth/core": "1.
|
|
75
|
-
"@better-auth/memory-adapter": "1.
|
|
76
|
-
"better-auth": "1.
|
|
74
|
+
"@better-auth/core": "1.8.0-beta.1",
|
|
75
|
+
"@better-auth/memory-adapter": "1.8.0-beta.1",
|
|
76
|
+
"better-auth": "1.8.0-beta.1"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
79
|
"@better-auth/utils": "^0.4.2 || ^0.5.0",
|
|
80
80
|
"@better-fetch/fetch": "1.3.2",
|
|
81
81
|
"better-call": "1.4.2",
|
|
82
|
-
"@better-auth/core": "^1.
|
|
83
|
-
"better-auth": "^1.
|
|
82
|
+
"@better-auth/core": "^1.8.0-beta.1",
|
|
83
|
+
"better-auth": "^1.8.0-beta.1"
|
|
84
84
|
},
|
|
85
85
|
"scripts": {
|
|
86
86
|
"build": "tsdown",
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { o as OAuthClient } from "./oauth-DXiqbRzK.mjs";
|
|
2
|
-
import { JSONWebKeySet } from "jose";
|
|
3
|
-
|
|
4
|
-
//#region src/client-jwks.d.ts
|
|
5
|
-
/** A client's inline public JWK Set, as registration and key rotation accept it. */
|
|
6
|
-
type ClientJwks = NonNullable<OAuthClient["jwks"]>;
|
|
7
|
-
type PublicClientJwksValidationResult = {
|
|
8
|
-
valid: true;
|
|
9
|
-
jwks: JSONWebKeySet;
|
|
10
|
-
} | {
|
|
11
|
-
valid: false;
|
|
12
|
-
error: "jwks must be an RFC 7517 JWK Set object with a non-empty keys array" | "jwks must contain only public asymmetric keys" | "jwks keys must be supported public JWKs with required key parameters" | "jwks key alg must be supported for private_key_jwt and compatible with its key type and signing curve";
|
|
13
|
-
};
|
|
14
|
-
/**
|
|
15
|
-
* Validates an OAuth client's public asymmetric JWK set.
|
|
16
|
-
*
|
|
17
|
-
* This boundary accepts only the RFC 7517 `{ keys: [...] }` representation.
|
|
18
|
-
* It performs no I/O and returns the validated set for downstream JOSE
|
|
19
|
-
* verification.
|
|
20
|
-
*
|
|
21
|
-
* @internal
|
|
22
|
-
*/
|
|
23
|
-
declare function validatePublicClientJwks(input: unknown): PublicClientJwksValidationResult;
|
|
24
|
-
//#endregion
|
|
25
|
-
export { PublicClientJwksValidationResult as n, validatePublicClientJwks as r, ClientJwks as t };
|