11import { NextResponse , type NextRequest } from "next/server.js" ;
22import * as jose from "jose" ;
33import * as oauth from "oauth4webapi" ;
4- import {
5- allowInsecureRequests ,
6- customFetch ,
7- protectedResourceRequest
8- } from "oauth4webapi" ;
94import * as client from "openid-client" ;
105
116import packageJson from "../../package.json" with { type : "json" } ;
@@ -79,6 +74,7 @@ import {
7974import { toSafeRedirect } from "../utils/url-helpers.js" ;
8075import { addCacheControlHeadersForSession } from "./cookies.js" ;
8176import {
77+ AccessTokenFactory ,
8278 Fetcher ,
8379 FetcherConfig ,
8480 FetcherHooks ,
@@ -691,7 +687,7 @@ export class AuthClient {
691687
692688 const [ completeConnectAccountError , connectedAccount ] =
693689 await this . completeConnectAccount ( {
694- accessToken : tokenSetResponse . tokenSet . accessToken ,
690+ tokenSet : tokenSetResponse . tokenSet ,
695691 authSession : transactionState . authSession ! ,
696692 connectCode : req . nextUrl . searchParams . get ( "connect_code" ) ! ,
697693 redirectUri : createRouteUrl (
@@ -1035,7 +1031,7 @@ export class AuthClient {
10351031 const { tokenSet, idTokenClaims } = getTokenSetResponse ;
10361032 const [ connectAccountError , connectAccountResponse ] =
10371033 await this . connectAccount ( {
1038- accessToken : tokenSet . accessToken ,
1034+ tokenSet : tokenSet ,
10391035 connection,
10401036 authorizationParams,
10411037 returnTo
@@ -1842,7 +1838,7 @@ export class AuthClient {
18421838 * The user will be redirected to authorize the connection.
18431839 */
18441840 async connectAccount (
1845- options : ConnectAccountOptions & { accessToken : string }
1841+ options : ConnectAccountOptions & { tokenSet : TokenSet }
18461842 ) : Promise < [ ConnectAccountError , null ] | [ null , NextResponse ] > {
18471843 const redirectUri = createRouteUrl ( this . routes . callback , this . appBaseUrl ) ;
18481844 let returnTo = this . signInReturnToPath ;
@@ -1871,7 +1867,7 @@ export class AuthClient {
18711867
18721868 const [ error , connectAccountResponse ] =
18731869 await this . createConnectAccountTicket ( {
1874- accessToken : options . accessToken ,
1870+ tokenSet : options . tokenSet ,
18751871 connection : options . connection ,
18761872 redirectUri : redirectUri . toString ( ) ,
18771873 state,
@@ -1910,38 +1906,37 @@ export class AuthClient {
19101906 this . issuer
19111907 ) ;
19121908
1909+ const fetcher = await this . fetcherFactory ( {
1910+ useDPoP : this . useDPoP ,
1911+ getAccessToken : async ( ) => ( {
1912+ accessToken : options . tokenSet . accessToken ,
1913+ expiresAt : options . tokenSet . expiresAt || 0 ,
1914+ scope : options . tokenSet . scope ,
1915+ token_type : options . tokenSet . token_type
1916+ } ) ,
1917+ fetch : this . fetch
1918+ } ) ;
1919+
19131920 const httpOptions = this . httpOptions ( ) ;
19141921 const headers = new Headers ( httpOptions . headers ) ;
19151922 headers . set ( "Content-Type" , "application/json" ) ;
19161923
1917- const requestBody = JSON . stringify ( {
1924+ const requestBody = {
19181925 connection : options . connection ,
19191926 redirect_uri : options . redirectUri ,
19201927 state : options . state ,
19211928 code_challenge : options . codeChallenge ,
19221929 code_challenge_method : options . codeChallengeMethod ,
19231930 authorization_params : options . authorizationParams
1924- } ) ;
1931+ } ;
19251932
1926- const res = await protectedResourceRequest (
1927- options . accessToken ,
1928- "POST" ,
1929- connectAccountUrl ,
1930- headers ,
1931- requestBody ,
1932- {
1933- ...httpOptions ,
1934- [ customFetch ] : ( url : string , requestOptions : any ) => {
1935- const tmpRequest = new Request ( url , requestOptions ) ;
1936- return this . fetch ( tmpRequest ) ;
1937- } ,
1938- [ allowInsecureRequests ] : this . allowInsecureRequests || false ,
1939- ...( this . useDPoP &&
1940- this . dpopKeyPair && {
1941- DPoP : oauth . DPoP ( this . clientMetadata , this . dpopKeyPair ! )
1942- } )
1943- }
1944- ) ;
1933+ const res = await fetcher . fetchWithAuth ( connectAccountUrl . toString ( ) , {
1934+ method : "POST" ,
1935+ headers : {
1936+ "Content-Type" : "application/json"
1937+ } ,
1938+ body : JSON . stringify ( requestBody )
1939+ } ) ;
19451940
19461941 if ( ! res . ok ) {
19471942 try {
@@ -1984,11 +1979,15 @@ export class AuthClient {
19841979 }
19851980 ] ;
19861981 } catch ( e : any ) {
1982+ let message =
1983+ "An unexpected error occurred while trying to initiate the connect account flow." ;
1984+ if ( e instanceof DPoPError ) {
1985+ message = e . message ;
1986+ }
19871987 return [
19881988 new ConnectAccountError ( {
19891989 code : ConnectAccountErrorCodes . FAILED_TO_INITIATE ,
1990- message :
1991- "An unexpected error occurred while trying to initiate the connect account flow."
1990+ message : message
19921991 } ) ,
19931992 null
19941993 ] ;
@@ -2008,32 +2007,31 @@ export class AuthClient {
20082007 const headers = new Headers ( httpOptions . headers ) ;
20092008 headers . set ( "Content-Type" , "application/json" ) ;
20102009
2011- const requestBody = JSON . stringify ( {
2010+ const fetcher = await this . fetcherFactory ( {
2011+ useDPoP : this . useDPoP ,
2012+ getAccessToken : async ( ) => ( {
2013+ accessToken : options . tokenSet . accessToken ,
2014+ expiresAt : options . tokenSet . expiresAt || 0 ,
2015+ scope : options . tokenSet . scope ,
2016+ token_type : options . tokenSet . token_type
2017+ } ) ,
2018+ fetch : this . fetch
2019+ } ) ;
2020+
2021+ const requestBody = {
20122022 auth_session : options . authSession ,
20132023 connect_code : options . connectCode ,
20142024 redirect_uri : options . redirectUri ,
20152025 code_verifier : options . codeVerifier
2016- } ) ;
2026+ } ;
20172027
2018- const res = await protectedResourceRequest (
2019- options . accessToken ,
2020- "POST" ,
2021- completeConnectAccountUrl ,
2022- headers ,
2023- requestBody ,
2024- {
2025- ...httpOptions ,
2026- [ customFetch ] : ( url : string , requestOptions : any ) => {
2027- const tmpRequest = new Request ( url , requestOptions ) ;
2028- return this . fetch ( tmpRequest ) ;
2029- } ,
2030- [ allowInsecureRequests ] : this . allowInsecureRequests || false ,
2031- ...( this . useDPoP &&
2032- this . dpopKeyPair && {
2033- DPoP : oauth . DPoP ( this . clientMetadata , this . dpopKeyPair ! )
2034- } )
2035- }
2036- ) ;
2028+ const res = await fetcher . fetchWithAuth ( completeConnectAccountUrl , {
2029+ method : "POST" ,
2030+ headers : {
2031+ "Content-Type" : "application/json"
2032+ } ,
2033+ body : JSON . stringify ( requestBody )
2034+ } ) ;
20372035
20382036 if ( ! res . ok ) {
20392037 try {
@@ -2172,19 +2170,6 @@ export class AuthClient {
21722170 throw discoveryError ;
21732171 }
21742172
2175- const defaultAccessTokenFactory = async (
2176- getAccessTokenOptions : GetAccessTokenOptions
2177- ) => {
2178- const [ error , getTokenSetResponse ] = await this . getTokenSet (
2179- options . session ,
2180- getAccessTokenOptions || { }
2181- ) ;
2182- if ( error ) {
2183- throw error ;
2184- }
2185- return getTokenSetResponse . tokenSet ;
2186- } ;
2187-
21882173 const fetcherConfig : FetcherConfig < TOutput > = {
21892174 // Fetcher-scoped DPoP handle and nonce management
21902175 dpopHandle :
@@ -2200,7 +2185,7 @@ export class AuthClient {
22002185 } ;
22012186
22022187 const fetcherHooks : FetcherHooks = {
2203- getAccessToken : defaultAccessTokenFactory ,
2188+ getAccessToken : options . getAccessToken ,
22042189 isDpopEnabled : ( ) => options . useDPoP ?? this . useDPoP ?? false
22052190 } ;
22062191
@@ -2234,5 +2219,5 @@ type GetTokenSetResponse = {
22342219 */
22352220export type FetcherFactoryOptions < TOutput extends Response > = {
22362221 useDPoP ?: boolean ;
2237- session : SessionData ;
2222+ getAccessToken : AccessTokenFactory ;
22382223} & FetcherMinimalConfig < TOutput > ;
0 commit comments