@better-auth/core 1.7.0-beta.5 → 1.7.0-beta.6

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.
Files changed (44) hide show
  1. package/dist/api/index.d.mts +44 -1
  2. package/dist/api/index.mjs +40 -1
  3. package/dist/context/global.mjs +1 -1
  4. package/dist/context/transaction.d.mts +7 -4
  5. package/dist/context/transaction.mjs +6 -3
  6. package/dist/db/adapter/factory.mjs +56 -30
  7. package/dist/db/adapter/index.d.mts +54 -10
  8. package/dist/db/adapter/types.d.mts +1 -1
  9. package/dist/db/type.d.mts +12 -7
  10. package/dist/instrumentation/tracer.mjs +1 -1
  11. package/dist/oauth2/dpop.d.mts +142 -0
  12. package/dist/oauth2/dpop.mjs +246 -0
  13. package/dist/oauth2/index.d.mts +3 -2
  14. package/dist/oauth2/index.mjs +3 -2
  15. package/dist/oauth2/verify.d.mts +74 -15
  16. package/dist/oauth2/verify.mjs +172 -20
  17. package/dist/social-providers/index.d.mts +1 -0
  18. package/dist/social-providers/microsoft-entra-id.d.mts +10 -0
  19. package/dist/social-providers/microsoft-entra-id.mjs +17 -2
  20. package/dist/social-providers/reddit.mjs +1 -1
  21. package/dist/social-providers/wechat.mjs +1 -1
  22. package/dist/types/context.d.mts +17 -0
  23. package/dist/types/init-options.d.mts +45 -5
  24. package/dist/types/plugin-client.d.mts +12 -2
  25. package/dist/utils/host.mjs +4 -0
  26. package/dist/utils/url.mjs +4 -3
  27. package/package.json +5 -5
  28. package/src/api/index.ts +82 -0
  29. package/src/context/transaction.ts +45 -12
  30. package/src/db/adapter/factory.ts +127 -72
  31. package/src/db/adapter/index.ts +54 -9
  32. package/src/db/adapter/types.ts +1 -0
  33. package/src/db/type.ts +12 -7
  34. package/src/oauth2/dpop.ts +568 -0
  35. package/src/oauth2/index.ts +44 -1
  36. package/src/oauth2/verify.ts +329 -66
  37. package/src/social-providers/microsoft-entra-id.ts +44 -1
  38. package/src/social-providers/reddit.ts +5 -1
  39. package/src/social-providers/wechat.ts +8 -1
  40. package/src/types/context.ts +18 -0
  41. package/src/types/init-options.ts +40 -8
  42. package/src/types/plugin-client.ts +16 -2
  43. package/src/utils/host.ts +15 -0
  44. package/src/utils/url.ts +10 -4
@@ -0,0 +1,568 @@
1
+ import type { JWK, JWTPayload } from "jose";
2
+ import {
3
+ base64url,
4
+ calculateJwkThumbprint,
5
+ decodeProtectedHeader,
6
+ importJWK,
7
+ jwtVerify,
8
+ } from "jose";
9
+
10
+ export const DPOP_AUTHORIZATION_SCHEME = "DPoP";
11
+ export const BEARER_AUTHORIZATION_SCHEME = "Bearer";
12
+ export const DPOP_PROOF_TYPE = "dpop+jwt";
13
+
14
+ export const DPOP_SIGNING_ALGORITHMS = [
15
+ "EdDSA",
16
+ "ES256",
17
+ "ES512",
18
+ "PS256",
19
+ "RS256",
20
+ ] as const;
21
+
22
+ const DEFAULT_DPOP_PROOF_MAX_AGE_SECONDS = 300;
23
+ const MAX_DPOP_JTI_LENGTH = 512;
24
+
25
+ const JWK_PRIVATE_FIELDS = new Set([
26
+ "d",
27
+ "p",
28
+ "q",
29
+ "dp",
30
+ "dq",
31
+ "qi",
32
+ "oth",
33
+ "k",
34
+ ]);
35
+
36
+ export type DpopSigningAlgorithm = (typeof DPOP_SIGNING_ALGORITHMS)[number];
37
+
38
+ export type AccessTokenAuthorizationScheme = "Bearer" | "DPoP" | "Unknown";
39
+
40
+ export interface AccessTokenAuthorization {
41
+ scheme: AccessTokenAuthorizationScheme;
42
+ token: string;
43
+ }
44
+
45
+ export type DpopProofErrorCode = "invalid_dpop_proof";
46
+
47
+ export type DpopProofError = Error & {
48
+ code: DpopProofErrorCode;
49
+ };
50
+
51
+ export interface DpopReplayReservation {
52
+ key: string;
53
+ expiresAt: Date;
54
+ now: Date;
55
+ }
56
+
57
+ export interface DpopReplayStore {
58
+ reserve: (reservation: DpopReplayReservation) => Promise<boolean> | boolean;
59
+ }
60
+
61
+ export function createInMemoryDpopReplayStore(): DpopReplayStore {
62
+ const reservations = new Map<string, number>();
63
+ return {
64
+ reserve({ key, expiresAt, now }) {
65
+ const nowMs = now.getTime();
66
+ for (const [storedKey, expiresAtMs] of reservations) {
67
+ if (expiresAtMs <= nowMs) {
68
+ reservations.delete(storedKey);
69
+ }
70
+ }
71
+ if (reservations.has(key)) return false;
72
+ reservations.set(key, expiresAt.getTime());
73
+ return true;
74
+ },
75
+ };
76
+ }
77
+
78
+ /**
79
+ * The single-use reservation capability a {@link createDpopReplayStore} needs:
80
+ * the auth context's `internalAdapter.reserveVerificationValue`. Kept structural
81
+ * so core does not depend on the adapter implementation.
82
+ */
83
+ export interface DpopReplayReservations {
84
+ reserveVerificationValue: (data: {
85
+ identifier: string;
86
+ value: string;
87
+ expiresAt: Date;
88
+ }) => Promise<boolean>;
89
+ }
90
+
91
+ /**
92
+ * Database-backed DPoP proof replay store built on the auth context's
93
+ * verification reservation primitive (`internalAdapter.reserveVerificationValue`),
94
+ * the same atomic single-use mechanism that guards SAML assertion ids and other
95
+ * one-time tokens. A replayed proof collides on the deterministic reservation id
96
+ * so `reserve` returns `false`, giving cross-instance anti-replay. Prefer this
97
+ * over {@link createInMemoryDpopReplayStore} for any multi-instance or serverless
98
+ * resource server. Requires database-backed verification storage; a
99
+ * secondary-storage-only deployment rejects the proof (fails closed).
100
+ */
101
+ export function createDpopReplayStore(
102
+ reservations: DpopReplayReservations,
103
+ ): DpopReplayStore {
104
+ return {
105
+ reserve: ({ key, expiresAt }) =>
106
+ reservations.reserveVerificationValue({
107
+ identifier: `dpop-proof:${key}`,
108
+ value: key,
109
+ expiresAt,
110
+ }),
111
+ };
112
+ }
113
+
114
+ export interface VerifyDpopProofOptions {
115
+ proofJwt: string;
116
+ method: string;
117
+ url: string;
118
+ accessToken?: string;
119
+ expectedJkt?: string;
120
+ requireAth?: boolean;
121
+ nowSeconds?: number;
122
+ proofMaxAgeSeconds?: number;
123
+ signingAlgorithms?: readonly string[];
124
+ replayStore?: DpopReplayStore;
125
+ }
126
+
127
+ export interface VerifiedDpopProof {
128
+ jwk: JWK;
129
+ jkt: string;
130
+ jti: string;
131
+ htm: string;
132
+ htu: string;
133
+ iat: number;
134
+ ath?: string;
135
+ replayKey: string;
136
+ expiresAt: Date;
137
+ }
138
+
139
+ export function createDpopProofError(
140
+ code: DpopProofErrorCode,
141
+ message: string,
142
+ ): DpopProofError {
143
+ return Object.assign(new Error(message), { code });
144
+ }
145
+
146
+ export function isDpopProofError(error: unknown): error is DpopProofError {
147
+ return (
148
+ error instanceof Error &&
149
+ "code" in error &&
150
+ error.code === "invalid_dpop_proof"
151
+ );
152
+ }
153
+
154
+ export function parseAccessTokenAuthorization(
155
+ authorization: string | null | undefined,
156
+ ): AccessTokenAuthorization | undefined {
157
+ if (!authorization) return undefined;
158
+ const value = authorization.trim();
159
+ if (!value) return undefined;
160
+ const match = /^([A-Za-z][A-Za-z0-9!#$%&'*+.^_`|~-]*)\s+(.+)$/.exec(value);
161
+ if (!match) {
162
+ return { scheme: "Unknown", token: value };
163
+ }
164
+ const scheme = match[1] ?? "";
165
+ const token = match[2]?.trim() ?? "";
166
+ if (scheme.toLowerCase() === "bearer") {
167
+ return { scheme: "Bearer", token };
168
+ }
169
+ if (scheme.toLowerCase() === "dpop") {
170
+ return { scheme: "DPoP", token };
171
+ }
172
+ return { scheme: "Unknown", token: value };
173
+ }
174
+
175
+ export function stripAccessTokenAuthorizationScheme(token: string): string {
176
+ return parseAccessTokenAuthorization(token)?.token ?? token;
177
+ }
178
+
179
+ export function normalizeDpopHtu(url: string): string {
180
+ const parsed = new URL(url);
181
+ // RFC 9449 §4.2: `htu` is the target URI without query and fragment parts.
182
+ // Reject a fragment rather than silently strip it, so a malformed proof
183
+ // fails fast instead of matching a request URL it does not actually name.
184
+ if (parsed.hash) {
185
+ throw new Error("DPoP proof htu must not contain a fragment");
186
+ }
187
+ return `${parsed.origin}${parsed.pathname}`;
188
+ }
189
+
190
+ export async function deriveDpopAth(accessToken: string): Promise<string> {
191
+ const digest = await crypto.subtle.digest(
192
+ "SHA-256",
193
+ new TextEncoder().encode(accessToken),
194
+ );
195
+ return base64url.encode(new Uint8Array(digest));
196
+ }
197
+
198
+ export async function deriveDpopJkt(jwk: JWK): Promise<string> {
199
+ return calculateJwkThumbprint(jwk, "sha256");
200
+ }
201
+
202
+ /**
203
+ * Extracts the DPoP key thumbprint from an RFC 7800 `cnf` confirmation. The
204
+ * input is untrusted (a JWT claim, a JSON column), so any shape other than an
205
+ * object carrying a non-empty string `jkt` (a primitive, an array, a different
206
+ * confirmation method such as mTLS `x5t#S256`) yields `undefined` instead of
207
+ * throwing.
208
+ */
209
+ export function getConfirmationJkt(confirmation: unknown): string | undefined {
210
+ if (
211
+ !confirmation ||
212
+ typeof confirmation !== "object" ||
213
+ Array.isArray(confirmation)
214
+ ) {
215
+ return undefined;
216
+ }
217
+ const jkt = (confirmation as Record<string, unknown>).jkt;
218
+ return typeof jkt === "string" && jkt.length > 0 ? jkt : undefined;
219
+ }
220
+
221
+ export function getDpopJktFromPayload(payload: JWTPayload): string | undefined {
222
+ return getConfirmationJkt(payload.cnf);
223
+ }
224
+
225
+ function getStringClaim(
226
+ payload: JWTPayload,
227
+ claim: string,
228
+ ): string | undefined {
229
+ const value = payload[claim];
230
+ return typeof value === "string" && value.length > 0 ? value : undefined;
231
+ }
232
+
233
+ function getNumberClaim(
234
+ payload: JWTPayload,
235
+ claim: string,
236
+ ): number | undefined {
237
+ const value = payload[claim];
238
+ return typeof value === "number" && Number.isFinite(value)
239
+ ? value
240
+ : undefined;
241
+ }
242
+
243
+ function assertSupportedDpopAlgorithm(
244
+ alg: string | undefined,
245
+ signingAlgorithms: readonly string[],
246
+ ) {
247
+ if (!alg || alg === "none" || alg.startsWith("HS")) {
248
+ throw createDpopProofError(
249
+ "invalid_dpop_proof",
250
+ "DPoP proof must use an asymmetric JWS algorithm",
251
+ );
252
+ }
253
+ if (!signingAlgorithms.includes(alg)) {
254
+ throw createDpopProofError(
255
+ "invalid_dpop_proof",
256
+ "DPoP proof uses an unsupported JWS algorithm",
257
+ );
258
+ }
259
+ }
260
+
261
+ function assertPublicJwk(jwk: JWK | undefined): asserts jwk is JWK {
262
+ if (!jwk || typeof jwk !== "object" || Array.isArray(jwk)) {
263
+ throw createDpopProofError(
264
+ "invalid_dpop_proof",
265
+ "DPoP proof header must include a public jwk",
266
+ );
267
+ }
268
+ if (jwk.kty === "oct") {
269
+ throw createDpopProofError(
270
+ "invalid_dpop_proof",
271
+ "DPoP proof jwk must be asymmetric",
272
+ );
273
+ }
274
+ for (const field of JWK_PRIVATE_FIELDS) {
275
+ if (field in jwk) {
276
+ throw createDpopProofError(
277
+ "invalid_dpop_proof",
278
+ "DPoP proof jwk must not contain private key material",
279
+ );
280
+ }
281
+ }
282
+ }
283
+
284
+ async function deriveDpopReplayKey(params: {
285
+ jkt: string;
286
+ htm: string;
287
+ htu: string;
288
+ jti: string;
289
+ }): Promise<string> {
290
+ const input = `${params.jkt}\n${params.htm}\n${params.htu}\n${params.jti}`;
291
+ const digest = await crypto.subtle.digest(
292
+ "SHA-256",
293
+ new TextEncoder().encode(input),
294
+ );
295
+ return base64url.encode(new Uint8Array(digest));
296
+ }
297
+
298
+ async function reserveDpopReplay(
299
+ replayStore: DpopReplayStore | undefined,
300
+ reservation: DpopReplayReservation,
301
+ ) {
302
+ if (!replayStore) return;
303
+ const reserved = await replayStore.reserve(reservation);
304
+ if (!reserved) {
305
+ throw createDpopProofError(
306
+ "invalid_dpop_proof",
307
+ "DPoP proof jti has already been used",
308
+ );
309
+ }
310
+ }
311
+
312
+ export async function verifyDpopProof({
313
+ proofJwt,
314
+ method,
315
+ url,
316
+ accessToken,
317
+ expectedJkt,
318
+ requireAth = false,
319
+ nowSeconds = Math.floor(Date.now() / 1000),
320
+ proofMaxAgeSeconds = DEFAULT_DPOP_PROOF_MAX_AGE_SECONDS,
321
+ signingAlgorithms = DPOP_SIGNING_ALGORITHMS,
322
+ replayStore,
323
+ }: VerifyDpopProofOptions): Promise<VerifiedDpopProof> {
324
+ if (!proofJwt || proofJwt.split(".").length !== 3) {
325
+ throw createDpopProofError(
326
+ "invalid_dpop_proof",
327
+ "DPoP proof must be a compact JWT",
328
+ );
329
+ }
330
+
331
+ let protectedHeader: ReturnType<typeof decodeProtectedHeader>;
332
+ try {
333
+ protectedHeader = decodeProtectedHeader(proofJwt);
334
+ } catch (error) {
335
+ throw createDpopProofError(
336
+ "invalid_dpop_proof",
337
+ error instanceof Error ? error.message : "DPoP proof header is invalid",
338
+ );
339
+ }
340
+ if (protectedHeader.typ !== DPOP_PROOF_TYPE) {
341
+ throw createDpopProofError(
342
+ "invalid_dpop_proof",
343
+ 'DPoP proof typ must be "dpop+jwt"',
344
+ );
345
+ }
346
+ assertSupportedDpopAlgorithm(protectedHeader.alg, signingAlgorithms);
347
+ assertPublicJwk(protectedHeader.jwk);
348
+
349
+ let payload: JWTPayload;
350
+ try {
351
+ // `importJWK` is inside the try: a structurally-valid header `jwk` can
352
+ // still fail to import (bad curve, malformed `x`/`y`), and that is bad
353
+ // client input, not a server error.
354
+ const publicKey = await importJWK(protectedHeader.jwk, protectedHeader.alg);
355
+ const verified = await jwtVerify(proofJwt, publicKey, {
356
+ typ: DPOP_PROOF_TYPE,
357
+ });
358
+ payload = verified.payload;
359
+ } catch (error) {
360
+ throw createDpopProofError(
361
+ "invalid_dpop_proof",
362
+ error instanceof Error
363
+ ? error.message
364
+ : "DPoP proof signature is invalid",
365
+ );
366
+ }
367
+
368
+ const htm = getStringClaim(payload, "htm");
369
+ const htu = getStringClaim(payload, "htu");
370
+ const jti = getStringClaim(payload, "jti");
371
+ const iat = getNumberClaim(payload, "iat");
372
+ if (!htm || !htu || !jti || iat === undefined) {
373
+ throw createDpopProofError(
374
+ "invalid_dpop_proof",
375
+ "DPoP proof must include htm, htu, jti, and iat claims",
376
+ );
377
+ }
378
+ if (jti.length > MAX_DPOP_JTI_LENGTH) {
379
+ throw createDpopProofError(
380
+ "invalid_dpop_proof",
381
+ "DPoP proof jti is too large",
382
+ );
383
+ }
384
+ if (htm.toUpperCase() !== method.toUpperCase()) {
385
+ throw createDpopProofError(
386
+ "invalid_dpop_proof",
387
+ "DPoP proof htm does not match the request method",
388
+ );
389
+ }
390
+ let normalizedHtu: string;
391
+ let proofHtu: string;
392
+ try {
393
+ normalizedHtu = normalizeDpopHtu(url);
394
+ proofHtu = normalizeDpopHtu(htu);
395
+ } catch (error) {
396
+ throw createDpopProofError(
397
+ "invalid_dpop_proof",
398
+ error instanceof Error ? error.message : "DPoP proof htu is invalid",
399
+ );
400
+ }
401
+ if (proofHtu !== normalizedHtu) {
402
+ throw createDpopProofError(
403
+ "invalid_dpop_proof",
404
+ "DPoP proof htu does not match the request URL",
405
+ );
406
+ }
407
+ if (iat > nowSeconds + 5 || nowSeconds - iat > proofMaxAgeSeconds) {
408
+ throw createDpopProofError(
409
+ "invalid_dpop_proof",
410
+ "DPoP proof iat is outside the accepted window",
411
+ );
412
+ }
413
+
414
+ const ath = getStringClaim(payload, "ath");
415
+ if (requireAth && !ath) {
416
+ throw createDpopProofError(
417
+ "invalid_dpop_proof",
418
+ "DPoP proof must include an ath claim",
419
+ );
420
+ }
421
+ if (accessToken !== undefined) {
422
+ const expectedAth = await deriveDpopAth(accessToken);
423
+ if (ath !== expectedAth) {
424
+ throw createDpopProofError(
425
+ "invalid_dpop_proof",
426
+ "DPoP proof ath does not match the access token",
427
+ );
428
+ }
429
+ }
430
+
431
+ const jkt = await deriveDpopJkt(protectedHeader.jwk);
432
+ if (expectedJkt !== undefined && jkt !== expectedJkt) {
433
+ throw createDpopProofError(
434
+ "invalid_dpop_proof",
435
+ "DPoP proof key does not match the bound token",
436
+ );
437
+ }
438
+
439
+ // Key the replay record on the canonical method and normalized URL that
440
+ // verification actually compared against, not the raw claim values. Otherwise
441
+ // the same `jti` could be reused with different `htm` casing or a different
442
+ // `htu` query string that normalizes equal, bypassing replay protection.
443
+ const replayKey = await deriveDpopReplayKey({
444
+ jkt,
445
+ htm: htm.toUpperCase(),
446
+ htu: normalizedHtu,
447
+ jti,
448
+ });
449
+ const expiresAt = new Date((iat + proofMaxAgeSeconds) * 1000);
450
+ await reserveDpopReplay(replayStore, {
451
+ key: replayKey,
452
+ expiresAt,
453
+ now: new Date(nowSeconds * 1000),
454
+ });
455
+
456
+ return {
457
+ jwk: protectedHeader.jwk,
458
+ jkt,
459
+ jti,
460
+ htm,
461
+ htu: normalizedHtu,
462
+ iat,
463
+ ath,
464
+ replayKey,
465
+ expiresAt,
466
+ };
467
+ }
468
+
469
+ export type DpopBindingErrorCode = "invalid_token" | "invalid_dpop_proof";
470
+
471
+ export type DpopBindingError = Error & {
472
+ code: DpopBindingErrorCode;
473
+ };
474
+
475
+ export function createDpopBindingError(
476
+ code: DpopBindingErrorCode,
477
+ message: string,
478
+ ): DpopBindingError {
479
+ return Object.assign(new Error(message), { code });
480
+ }
481
+
482
+ export function isDpopBindingError(error: unknown): error is DpopBindingError {
483
+ return (
484
+ error instanceof Error &&
485
+ "code" in error &&
486
+ (error.code === "invalid_token" || error.code === "invalid_dpop_proof")
487
+ );
488
+ }
489
+
490
+ export interface EnforceDpopBindingParams {
491
+ /** The already-verified access-token payload (from JWKS or introspection). */
492
+ payload: JWTPayload;
493
+ /** The parsed `Authorization` header (scheme + token). */
494
+ authorization: AccessTokenAuthorization;
495
+ /** The `DPoP` proof header value, if any. */
496
+ proofJwt: string | null | undefined;
497
+ method: string;
498
+ url: string;
499
+ replayStore?: DpopReplayStore;
500
+ proofMaxAgeSeconds?: number;
501
+ signingAlgorithms?: readonly string[];
502
+ }
503
+
504
+ /**
505
+ * Enforces the RFC 9449 §7.1 sender-constraint check for a resource request,
506
+ * given an access-token payload that has already been validated (by JWKS or
507
+ * introspection). This is the single source of truth for the
508
+ * "is the token DPoP-bound? then require the DPoP scheme, a proof, and a
509
+ * matching key" decision, shared by every resource-server entry point.
510
+ *
511
+ * Throws a {@link DpopBindingError} on any mismatch so callers map the
512
+ * `invalid_token` / `invalid_dpop_proof` code into their own transport. Returns
513
+ * normally for a valid bearer token (no `cnf.jkt`, no DPoP scheme).
514
+ */
515
+ export async function enforceDpopBinding({
516
+ payload,
517
+ authorization,
518
+ proofJwt,
519
+ method,
520
+ url,
521
+ replayStore,
522
+ proofMaxAgeSeconds,
523
+ signingAlgorithms,
524
+ }: EnforceDpopBindingParams): Promise<void> {
525
+ const dpopJkt = getDpopJktFromPayload(payload);
526
+
527
+ if (!dpopJkt) {
528
+ if (authorization.scheme === "DPoP") {
529
+ throw createDpopBindingError(
530
+ "invalid_token",
531
+ "DPoP authorization requires a DPoP-bound access token",
532
+ );
533
+ }
534
+ return;
535
+ }
536
+
537
+ if (authorization.scheme !== "DPoP") {
538
+ throw createDpopBindingError(
539
+ "invalid_token",
540
+ "DPoP-bound access token requires the DPoP authorization scheme",
541
+ );
542
+ }
543
+ if (!proofJwt) {
544
+ throw createDpopBindingError(
545
+ "invalid_dpop_proof",
546
+ "DPoP proof header is required",
547
+ );
548
+ }
549
+
550
+ try {
551
+ await verifyDpopProof({
552
+ proofJwt,
553
+ method,
554
+ url,
555
+ accessToken: authorization.token,
556
+ expectedJkt: dpopJkt,
557
+ requireAth: true,
558
+ proofMaxAgeSeconds,
559
+ signingAlgorithms,
560
+ replayStore,
561
+ });
562
+ } catch (error) {
563
+ if (isDpopProofError(error)) {
564
+ throw createDpopBindingError("invalid_dpop_proof", error.message);
565
+ }
566
+ throw error;
567
+ }
568
+ }
@@ -26,6 +26,42 @@ export {
26
26
  RESERVED_AUTHORIZATION_PARAMS,
27
27
  RESERVED_AUTHORIZATION_PARAMS_SET,
28
28
  } from "./create-authorization-url";
29
+ export type {
30
+ AccessTokenAuthorization,
31
+ AccessTokenAuthorizationScheme,
32
+ DpopBindingError,
33
+ DpopBindingErrorCode,
34
+ DpopProofError,
35
+ DpopProofErrorCode,
36
+ DpopReplayReservation,
37
+ DpopReplayReservations,
38
+ DpopReplayStore,
39
+ DpopSigningAlgorithm,
40
+ EnforceDpopBindingParams,
41
+ VerifiedDpopProof,
42
+ VerifyDpopProofOptions,
43
+ } from "./dpop";
44
+ export {
45
+ BEARER_AUTHORIZATION_SCHEME,
46
+ createDpopBindingError,
47
+ createDpopProofError,
48
+ createDpopReplayStore,
49
+ createInMemoryDpopReplayStore,
50
+ DPOP_AUTHORIZATION_SCHEME,
51
+ DPOP_PROOF_TYPE,
52
+ DPOP_SIGNING_ALGORITHMS,
53
+ deriveDpopAth,
54
+ deriveDpopJkt,
55
+ enforceDpopBinding,
56
+ getConfirmationJkt,
57
+ getDpopJktFromPayload,
58
+ isDpopBindingError,
59
+ isDpopProofError,
60
+ normalizeDpopHtu,
61
+ parseAccessTokenAuthorization,
62
+ stripAccessTokenAuthorizationScheme,
63
+ verifyDpopProof,
64
+ } from "./dpop";
29
65
  export type {
30
66
  AuthorizationURLResult,
31
67
  GrantAuthority,
@@ -64,9 +100,16 @@ export {
64
100
  validateAuthorizationCode,
65
101
  validateToken,
66
102
  } from "./validate-authorization-code";
103
+ export type {
104
+ ResourceRequestInput,
105
+ VerifyAccessTokenOptions,
106
+ VerifyAccessTokenRequestOptions,
107
+ } from "./verify";
67
108
  export {
68
109
  getJwks,
69
- verifyAccessToken,
110
+ requestToResourceInput,
111
+ verifyAccessTokenRequest,
112
+ verifyBearerToken,
70
113
  verifyJwsAccessToken,
71
114
  } from "./verify";
72
115
  export {