oauth_models.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import enum
  2. from typing import Set, Union
  3. import flask
  4. class Scope(enum.Enum):
  5. EMAIL = "email"
  6. NAME = "name"
  7. OPENID = "openid"
  8. AVATAR_URL = "avatar_url"
  9. class ResponseType(enum.Enum):
  10. CODE = "code"
  11. TOKEN = "token"
  12. ID_TOKEN = "id_token"
  13. # All the OIDC flows supported by SimpleLogin
  14. # CF https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660
  15. SUPPORTED_OPENID_FLOWS = [
  16. {ResponseType.CODE},
  17. {ResponseType.TOKEN},
  18. {ResponseType.ID_TOKEN},
  19. {ResponseType.ID_TOKEN, ResponseType.TOKEN},
  20. {ResponseType.ID_TOKEN, ResponseType.CODE},
  21. ]
  22. # String form of SUPPORTED_OPENID_FLOWS
  23. SUPPORTED_OPENID_FLOWS_STR = "code|token|id_token|id_token,token|id_token,code"
  24. def get_scopes(request: flask.Request) -> Set[Scope]:
  25. scope_strs = _split_arg(request.args.getlist("scope"))
  26. return set([Scope(scope_str) for scope_str in scope_strs])
  27. def get_response_types(request: flask.Request) -> Set[ResponseType]:
  28. response_type_strs = _split_arg(request.args.getlist("response_type"))
  29. return set([ResponseType(r) for r in response_type_strs if r])
  30. def get_response_types_from_str(response_type_str) -> Set[ResponseType]:
  31. response_type_strs = _split_arg(response_type_str)
  32. return set([ResponseType(r) for r in response_type_strs if r])
  33. def response_types_to_str(response_types: [ResponseType]) -> str:
  34. """return a string representing a list of response type, for ex
  35. *code*, *id_token,token*,...
  36. """
  37. return ",".join([r.value for r in response_types])
  38. def _split_arg(arg_input: Union[str, list]) -> Set[str]:
  39. """convert input response_type/scope into a set of string.
  40. arg_input = request.args.getlist(response_type|scope)
  41. Take into account different variations and their combinations
  42. - the split character is " " or ","
  43. - the response_type/scope passed as a list ?scope=scope_1&scope=scope_2
  44. """
  45. res = set()
  46. if type(arg_input) is str:
  47. if " " in arg_input:
  48. for x in arg_input.split(" "):
  49. if x:
  50. res.add(x.lower())
  51. elif "," in arg_input:
  52. for x in arg_input.split(","):
  53. if x:
  54. res.add(x.lower())
  55. else:
  56. res.add(arg_input)
  57. else:
  58. for arg in arg_input:
  59. res = res.union(_split_arg(arg))
  60. return res