66from urllib .parse import parse_qsl
77from urllib .parse import urlparse
88
9- import nacl .hash
10- from nacl .encoding import URLSafeBase64Encoder
119from jwkest import jws
1210from oic import rndstr
1311from oic .exception import MessageException
2321from oic .oic .message import RefreshAccessTokenRequest
2422from oic .oic .message import RegistrationRequest
2523from oic .oic .message import RegistrationResponse
24+ from oic .extension .provider import Provider as OICProviderExtensions
2625
2726from .message import AuthorizationRequest
2827from .message import AccessTokenRequest
@@ -330,23 +329,6 @@ def handle_token_request(self, request_body, # type: str
330329 raise InvalidTokenRequest ('grant_type \' {}\' unknown' .format (token_request ['grant_type' ]), token_request ,
331330 oauth_error = 'unsupported_grant_type' )
332331
333- def _compute_code_challenge (self ,
334- code_verifier # type: str
335- ):
336- # type: (...) -> str
337- """
338- Given a code verifier compute the code_challenge. This code_challenge is computed as defined (https://datatracker.ietf.org/doc/html/rfc7636#section-4.2):
339-
340- code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))).
341-
342- This shows that the SHA256 of the ascii encoded code_verifier is URLSafe base64 encoded. We have adjusted the encoding to the ISO_8859_1 encoding,
343- conform to the AppAuth SDK for Android and IOS. Moreover, we remove the base64 padding (=).
344-
345- :param code_verifier: the code verifier to transform to the Code Challenge
346- """
347- verifier_hash = nacl .hash .sha256 (code_verifier .encode ('ISO_8859_1' ), encoder = URLSafeBase64Encoder )
348- return verifier_hash .decode ().replace ('=' , '' )
349-
350332 def _PKCE_verify (self ,
351333 token_request , # type: AccessTokenRequest
352334 authentication_request # type: AuthorizationRequest
@@ -368,12 +350,10 @@ def _PKCE_verify(self,
368350 raise InvalidTokenRequest ("A code_challenge and code_verifier have been supplied"
369351 "but missing code_challenge_method in authentication_request" , token_request )
370352
371- code_challenge_method = authentication_request ['code_challenge_method' ]
372- if code_challenge_method == 'plain' :
373- return authentication_request ['code_challenge' ] == token_request ['code_verifier' ]
374-
375- code_challenge = self ._compute_code_challenge (token_request ['code_verifier' ])
376- return code_challenge == authentication_request ['code_challenge' ]
353+ # OIC Provider extension returns either a boolean or Response object containing an error. To support
354+ # stricter typing guidelines, return if True. Error handling support should be in encapsulating function.
355+ return OICProviderExtensions .verify_code_challenge (token_request ['code_verifier' ],
356+ authentication_request ['code_challenge' ], authentication_request ['code_challenge_method' ]) == True
377357
378358 def _verify_code_exchange_req (self ,
379359 token_request , # type: AccessTokenRequest
0 commit comments