| 60 | |
| 61 | @dataclass |
| 62 | class TokenHandler: |
| 63 | provider: OAuthAuthorizationServerProvider[Any, Any, Any] |
| 64 | client_authenticator: ClientAuthenticator |
| 65 | |
| 66 | def response(self, obj: TokenSuccessResponse | TokenErrorResponse): |
| 67 | status_code = 200 |
| 68 | if isinstance(obj, TokenErrorResponse): |
| 69 | status_code = 400 |
| 70 | |
| 71 | return PydanticJSONResponse( |
| 72 | content=obj, |
| 73 | status_code=status_code, |
| 74 | headers={ |
| 75 | "Cache-Control": "no-store", |
| 76 | "Pragma": "no-cache", |
| 77 | }, |
| 78 | ) |
| 79 | |
| 80 | async def handle(self, request: Request): |
| 81 | try: |
| 82 | client_info = await self.client_authenticator.authenticate_request(request) |
| 83 | except AuthenticationError as e: |
| 84 | # Authentication failures should return 401 |
| 85 | return PydanticJSONResponse( |
| 86 | content=TokenErrorResponse( |
| 87 | error="invalid_client", |
| 88 | error_description=e.message, |
| 89 | ), |
| 90 | status_code=401, |
| 91 | headers={ |
| 92 | "Cache-Control": "no-store", |
| 93 | "Pragma": "no-cache", |
| 94 | }, |
| 95 | ) |
| 96 | |
| 97 | try: |
| 98 | form_data = await request.form() |
| 99 | # TODO(Marcelo): Can someone check if this `dict()` wrapper is necessary? |
| 100 | token_request = token_request_adapter.validate_python(dict(form_data)) |
| 101 | except ValidationError as validation_error: # pragma: no cover |
| 102 | return self.response( |
| 103 | TokenErrorResponse( |
| 104 | error="invalid_request", |
| 105 | error_description=stringify_pydantic_error(validation_error), |
| 106 | ) |
| 107 | ) |
| 108 | |
| 109 | if token_request.grant_type not in client_info.grant_types: # pragma: no cover |
| 110 | return self.response( |
| 111 | TokenErrorResponse( |
| 112 | error="unsupported_grant_type", |
| 113 | error_description=(f"Unsupported grant type (supported grant types are {client_info.grant_types})"), |
| 114 | ) |
| 115 | ) |
| 116 | |
| 117 | tokens: OAuthToken |
| 118 | |
| 119 | match token_request: |
no outgoing calls
no test coverage detected