@@ -398,6 +398,22 @@ def get_user_id(self, details, response) -> str:
398398 uid = idp .get_user_permanent_id (response ["attributes" ])
399399 return f"{ idp .name } :{ uid } "
400400
401+ def parse_relay_state (self , relay_state_str : str ) -> dict :
402+ """Parse RelayState JSON or simple string into a dict"""
403+ try :
404+ relay_state : dict = json .loads (relay_state_str )
405+ except json .JSONDecodeError :
406+ # this is for backward compatibility; also some identity providers
407+ # (like Okta) send a simple string with the IdP name in RelayState
408+ # during IdP-initiated SSO:
409+ relay_state = {"idp" : relay_state_str }
410+
411+ # Validate that the data is dict
412+ if not isinstance (relay_state , dict ):
413+ raise AuthInvalidParameter (self , "RelayState" )
414+
415+ return relay_state
416+
401417 def auth_complete (self , * args , ** kwargs ):
402418 """
403419 The user has been redirected back from the IdP and we should
@@ -409,15 +425,7 @@ def auth_complete(self, *args, **kwargs):
409425 except KeyError :
410426 idp_name = None
411427 else :
412- # Parse RelayState JSON
413- try :
414- relay_state : dict = json .loads (relay_state_str )
415- except json .JSONDecodeError as error :
416- raise AuthInvalidParameter (self , "RelayState" ) from error
417-
418- # Validate that the data is dict
419- if not isinstance (relay_state , dict ):
420- raise AuthInvalidParameter (self , "RelayState" )
428+ relay_state = self .parse_relay_state (relay_state_str )
421429
422430 # Get IdP name
423431 idp_name = relay_state .get ("idp" )
0 commit comments