@@ -13,6 +13,7 @@ import type {
1313  OAuth2GranterService , 
1414}  from  '../services/oAuth2Granters' ; 
1515import  type  {  LogService  }  from  'common-services' ; 
16+ import  {  CODE_CHALLENGE_METHODS  }  from  '../services/oAuth2CodeGranter' ; 
1617
1718/* Architecture Note #1: OAuth2 authorize 
1819This endpoint simply redirect the user to the authentication 
@@ -77,6 +78,29 @@ export const stateParameter: WhookAPIParameterDefinition = {
7778    } , 
7879  } , 
7980} ; 
81+ export  const  codeChallengeParameter : WhookAPIParameterDefinition  =  { 
82+   name : 'code_challenge' , 
83+   parameter : { 
84+     in : 'query' , 
85+     name : 'code_challenge' , 
86+     required : false , 
87+     schema : { 
88+       type : 'string' , 
89+     } , 
90+   } , 
91+ } ; 
92+ export  const  codeChallengeMethodParameter : WhookAPIParameterDefinition  =  { 
93+   name : 'code_challenge_method' , 
94+   parameter : { 
95+     in : 'query' , 
96+     name : 'code_challenge_method' , 
97+     required : false , 
98+     schema : { 
99+       type : 'string' , 
100+       enum : ( CODE_CHALLENGE_METHODS  as  unknown )  as  string [ ] , 
101+     } , 
102+   } , 
103+ } ; 
80104
81105export  const  definition : WhookAPIHandlerDefinition  =  { 
82106  method : 'get' , 
@@ -102,6 +126,12 @@ export const definition: WhookAPIHandlerDefinition = {
102126      { 
103127        $ref : `#/components/parameters/${ stateParameter . name }  , 
104128      } , 
129+       { 
130+         $ref : `#/components/parameters/${ codeChallengeParameter . name }  , 
131+       } , 
132+       { 
133+         $ref : `#/components/parameters/${ codeChallengeMethodParameter . name }  , 
134+       } , 
105135    ] , 
106136    responses : { 
107137      '302' : { 
@@ -131,13 +161,17 @@ async function getOAuth2Authorize(
131161    redirect_uri : demandedRedirectURI  =  '' , 
132162    scope : demandedScope  =  '' , 
133163    state, 
164+     code_challenge : codeChallenge  =  '' , 
165+     code_challenge_method : codeChallengeMethod  =  'plain' , 
134166    ...authorizeParameters 
135167  } : { 
136168    response_type : string ; 
137169    client_id : string ; 
138170    redirect_uri ?: string ; 
139171    scope ?: string ; 
140172    state : string ; 
173+     code_challenge ?: string ; 
174+     code_challenge_method ?: string ; 
141175  }  &  Record < string ,  unknown > , 
142176) : Promise < WhookResponse >  { 
143177  const  url  =  new  URL ( OAUTH2 . authenticateURL ) ; 
@@ -151,6 +185,15 @@ async function getOAuth2Authorize(
151185    if  ( ! granter )  { 
152186      throw  new  YError ( 'E_UNKNOWN_AUTHORIZER_TYPE' ,  responseType ) ; 
153187    } 
188+     if  ( responseType  ===  'code' )  { 
189+       if  ( ! codeChallenge )  { 
190+         if  ( OAUTH2 . forcePKCE )  { 
191+           throw  new  YError ( 'E_PKCE_REQUIRED' ,  responseType ) ; 
192+         } 
193+       } 
194+     }  else  if  ( codeChallenge )  { 
195+       throw  new  YError ( 'E_PKCE_NOT_SUPPORTED' ,  responseType ) ; 
196+     } 
154197
155198    const  { 
156199      applicationId, 
@@ -162,7 +205,15 @@ async function getOAuth2Authorize(
162205        redirectURI : demandedRedirectURI , 
163206        scope : demandedScope , 
164207      } , 
165-       camelCaseObjectProperties ( authorizeParameters ) , 
208+       camelCaseObjectProperties ( { 
209+         ...authorizeParameters , 
210+         ...( responseType  ===  'code' 
211+           ? { 
212+               codeChallenge, 
213+               codeChallengeMethod, 
214+             } 
215+           : { } ) , 
216+       } ) , 
166217    ) ; 
167218
168219    url . searchParams . set ( 'type' ,  responseType ) ; 
0 commit comments