@@ -287,6 +287,8 @@ def auth_url(
287287 scope : str = "email" ,
288288 state : str = "" ,
289289 nonce : str = "" ,
290+ code_challenge : str | None = None ,
291+ code_challenge_method : str | None = None ,
290292 ) -> str :
291293 """
292294 Get authorization URL endpoint.
@@ -299,6 +301,10 @@ def auth_url(
299301 :type state: str
300302 :param nonce: Associates a Client session with an ID Token to mitigate replay attacks
301303 :type nonce: str
304+ :param code_challenge: PKCE code challenge
305+ :type code_challenge: str
306+ :param code_challenge_method: PKCE code challenge method
307+ :type code_challenge_method: str
302308 :returns: Authorization URL Full Build
303309 :rtype: str
304310 """
@@ -310,7 +316,12 @@ def auth_url(
310316 "state" : state ,
311317 "nonce" : nonce ,
312318 }
313- return URL_AUTH .format (** params_path )
319+ url = URL_AUTH .format (** params_path )
320+ if code_challenge :
321+ url += f"&code_challenge={ code_challenge } "
322+ if code_challenge_method :
323+ url += f"&code_challenge_method={ code_challenge_method } "
324+ return url
314325
315326 def token (
316327 self ,
@@ -321,6 +332,7 @@ def token(
321332 redirect_uri : str = "" ,
322333 totp : int | None = None ,
323334 scope : str = "openid" ,
335+ code_verifier : str | None = None ,
324336 ** extra : dict ,
325337 ) -> dict :
326338 """
@@ -347,6 +359,8 @@ def token(
347359 :type totp: int
348360 :param scope: Scope, defaults to openid
349361 :type scope: str
362+ :param code_verifier: PKCE code verifier
363+ :type code_verifier: str
350364 :param extra: Additional extra arguments
351365 :type extra: dict
352366 :returns: Keycloak token
@@ -362,6 +376,8 @@ def token(
362376 "redirect_uri" : redirect_uri ,
363377 "scope" : scope ,
364378 }
379+ if code_verifier :
380+ payload ["code_verifier" ] = code_verifier
365381 if extra :
366382 payload .update (extra )
367383
@@ -1033,6 +1049,8 @@ async def a_auth_url(
10331049 scope : str = "email" ,
10341050 state : str = "" ,
10351051 nonce : str = "" ,
1052+ code_challenge : str | None = None ,
1053+ code_challenge_method : str | None = None ,
10361054 ) -> str :
10371055 """
10381056 Get authorization URL endpoint asynchronously.
@@ -1045,6 +1063,10 @@ async def a_auth_url(
10451063 :type state: str
10461064 :param nonce: Associates a Client session with an ID Token to mitigate replay attacks
10471065 :type nonce: str
1066+ :param code_challenge: PKCE code challenge
1067+ :type code_challenge: str
1068+ :param code_challenge_method: PKCE code challenge method
1069+ :type code_challenge_method: str
10481070 :returns: Authorization URL Full Build
10491071 :rtype: str
10501072 """
@@ -1056,7 +1078,12 @@ async def a_auth_url(
10561078 "state" : state ,
10571079 "nonce" : nonce ,
10581080 }
1059- return URL_AUTH .format (** params_path )
1081+ url = URL_AUTH .format (** params_path )
1082+ if code_challenge :
1083+ url += f"&code_challenge={ code_challenge } "
1084+ if code_challenge_method :
1085+ url += f"&code_challenge_method={ code_challenge_method } "
1086+ return url
10601087
10611088 async def a_token (
10621089 self ,
@@ -1067,6 +1094,7 @@ async def a_token(
10671094 redirect_uri : str = "" ,
10681095 totp : int | None = None ,
10691096 scope : str = "openid" ,
1097+ code_verifier : str | None = None ,
10701098 ** extra : dict ,
10711099 ) -> dict :
10721100 """
@@ -1093,6 +1121,8 @@ async def a_token(
10931121 :type totp: int
10941122 :param scope: Scope, defaults to openid
10951123 :type scope: str
1124+ :param code_verifier: PKCE code verifier
1125+ :type code_verifier: str
10961126 :param extra: Additional extra arguments
10971127 :type extra: dict
10981128 :returns: Keycloak token
@@ -1108,6 +1138,8 @@ async def a_token(
11081138 "redirect_uri" : redirect_uri ,
11091139 "scope" : scope ,
11101140 }
1141+ if code_verifier :
1142+ payload ["code_verifier" ] = code_verifier
11111143 if extra :
11121144 payload .update (extra )
11131145
0 commit comments