open_id_connect_url.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. from typing import Optional
  2. from fastapi.openapi.models import OpenIdConnect as OpenIdConnectModel
  3. from fastapi.security.base import SecurityBase
  4. from starlette.exceptions import HTTPException
  5. from starlette.requests import Request
  6. from starlette.status import HTTP_403_FORBIDDEN
  7. from typing_extensions import Annotated, Doc
  8. class OpenIdConnect(SecurityBase):
  9. """
  10. OpenID Connect authentication class. An instance of it would be used as a
  11. dependency.
  12. """
  13. def __init__(
  14. self,
  15. *,
  16. openIdConnectUrl: Annotated[
  17. str,
  18. Doc(
  19. """
  20. The OpenID Connect URL.
  21. """
  22. ),
  23. ],
  24. scheme_name: Annotated[
  25. Optional[str],
  26. Doc(
  27. """
  28. Security scheme name.
  29. It will be included in the generated OpenAPI (e.g. visible at `/docs`).
  30. """
  31. ),
  32. ] = None,
  33. description: Annotated[
  34. Optional[str],
  35. Doc(
  36. """
  37. Security scheme description.
  38. It will be included in the generated OpenAPI (e.g. visible at `/docs`).
  39. """
  40. ),
  41. ] = None,
  42. auto_error: Annotated[
  43. bool,
  44. Doc(
  45. """
  46. By default, if no HTTP Authorization header is provided, required for
  47. OpenID Connect authentication, it will automatically cancel the request
  48. and send the client an error.
  49. If `auto_error` is set to `False`, when the HTTP Authorization header
  50. is not available, instead of erroring out, the dependency result will
  51. be `None`.
  52. This is useful when you want to have optional authentication.
  53. It is also useful when you want to have authentication that can be
  54. provided in one of multiple optional ways (for example, with OpenID
  55. Connect or in a cookie).
  56. """
  57. ),
  58. ] = True,
  59. ):
  60. self.model = OpenIdConnectModel(
  61. openIdConnectUrl=openIdConnectUrl, description=description
  62. )
  63. self.scheme_name = scheme_name or self.__class__.__name__
  64. self.auto_error = auto_error
  65. async def __call__(self, request: Request) -> Optional[str]:
  66. authorization = request.headers.get("Authorization")
  67. if not authorization:
  68. if self.auto_error:
  69. raise HTTPException(
  70. status_code=HTTP_403_FORBIDDEN, detail="Not authenticated"
  71. )
  72. else:
  73. return None
  74. return authorization