authentik.providers.oauth2.errors

OAuth errors

  1"""OAuth errors"""
  2
  3from urllib.parse import quote, urlparse
  4
  5from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
  6
  7from authentik.events.models import Event, EventAction
  8from authentik.lib.sentry import SentryIgnoredException
  9from authentik.lib.views import bad_request_message
 10from authentik.providers.oauth2.models import GrantTypes, RedirectURI
 11
 12
 13class OAuth2Error(SentryIgnoredException):
 14    """Base class for all OAuth2 Errors"""
 15
 16    error: str
 17    description: str
 18    cause: str | None = None
 19
 20    def create_dict(self, request: HttpRequest):
 21        """Return error as dict for JSON Rendering"""
 22        return {
 23            "error": self.error,
 24            "error_description": self.description,
 25            "request_id": request.request_id,
 26        }
 27
 28    def __repr__(self) -> str:
 29        return self.error
 30
 31    def to_event(self, message: str | None = None, **kwargs) -> Event:
 32        """Create configuration_error Event."""
 33        return Event.new(
 34            EventAction.CONFIGURATION_ERROR,
 35            message=message or self.description,
 36            cause=self.cause,
 37            error=self.error,
 38            **kwargs,
 39        )
 40
 41    def with_cause(self, cause: str):
 42        self.cause = cause
 43        return self
 44
 45
 46class RedirectUriError(OAuth2Error):
 47    """The request fails due to a missing, invalid, or mismatching
 48    redirection URI (redirect_uri)."""
 49
 50    error = "Redirect URI Error"
 51    description = (
 52        "The request fails due to a missing, invalid, or mismatching "
 53        "redirection URI (redirect_uri)."
 54    )
 55
 56    provided_uri: str
 57    allowed_uris: list[RedirectURI]
 58
 59    def __init__(self, provided_uri: str, allowed_uris: list[RedirectURI]) -> None:
 60        super().__init__()
 61        self.provided_uri = provided_uri
 62        self.allowed_uris = allowed_uris
 63
 64    def to_event(self, **kwargs) -> Event:
 65        return super().to_event(
 66            (
 67                f"Invalid redirect URI was used. Client used '{self.provided_uri}'. "
 68                f"Allowed redirect URIs are {','.join(self.allowed_uris)}"
 69            ),
 70            **kwargs,
 71        )
 72
 73
 74class ClientIdError(OAuth2Error):
 75    """The client identifier (client_id) is missing or invalid."""
 76
 77    error = "Client ID Error"
 78    description = "The client identifier (client_id) is missing or invalid."
 79
 80    client_id: str
 81
 82    def __init__(self, client_id: str) -> None:
 83        super().__init__()
 84        self.client_id = client_id
 85
 86    def to_event(self, **kwargs) -> Event:
 87        return super().to_event(f"Invalid client identifier: {self.client_id}.", **kwargs)
 88
 89
 90class UserAuthError(OAuth2Error):
 91    """
 92    Specific to the Resource Owner Password Credentials flow when
 93    the Resource Owners credentials are not valid.
 94    """
 95
 96    error = "access_denied"
 97    description = "The resource owner or authorization server denied the request."
 98
 99
100class TokenIntrospectionError(OAuth2Error):
101    """
102    Specific to the introspection endpoint. This error will be converted
103    to an "active: false" response, as per the spec.
104    See https://datatracker.ietf.org/doc/html/rfc7662
105    """
106
107
108class AuthorizeError(OAuth2Error):
109    """General Authorization Errors"""
110
111    errors = {
112        # OAuth2 errors.
113        # https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1
114        "invalid_request": "The request is otherwise malformed",
115        "unauthorized_client": (
116            "The client is not authorized to request an authorization code using this method"
117        ),
118        "access_denied": "The resource owner or authorization server denied the request",
119        "unsupported_response_type": (
120            "The authorization server does not support obtaining an authorization code "
121            "using this method"
122        ),
123        "invalid_scope": "The requested scope is invalid, unknown, or malformed",
124        "server_error": "The authorization server encountered an error",
125        "temporarily_unavailable": (
126            "The authorization server is currently unable to handle the request due to a "
127            "temporary overloading or maintenance of the server"
128        ),
129        # OpenID errors.
130        # http://openid.net/specs/openid-connect-core-1_0.html#AuthError
131        "interaction_required": (
132            "The Authorization Server requires End-User interaction of some form to proceed"
133        ),
134        "login_required": "The Authorization Server requires End-User authentication",
135        "account_selection_required": (
136            "The End-User is required to select a session at the Authorization Server"
137        ),
138        "consent_required": "The Authorization Server requires End-User consent",
139        "invalid_request_uri": (
140            "The request_uri in the Authorization Request returns an error or contains invalid data"
141        ),
142        "invalid_request_object": "The request parameter contains an invalid Request Object",
143        "request_not_supported": "The provider does not support use of the request parameter",
144        "request_uri_not_supported": (
145            "The provider does not support use of the request_uri parameter"
146        ),
147        "registration_not_supported": (
148            "The provider does not support use of the registration parameter"
149        ),
150    }
151
152    def __init__(
153        self,
154        redirect_uri: str,
155        error: str,
156        grant_type: str,
157        state: str,
158        description: str | None = None,
159    ):
160        super().__init__()
161        self.error = error
162        if description:
163            self.description = description
164        else:
165            self.description = self.errors[error]
166        self.redirect_uri = redirect_uri
167        self.grant_type = grant_type
168        self.state = state
169
170    def get_response(self, request: HttpRequest) -> HttpResponse:
171        """Wrapper around `self.create_uri()` that checks if the resulting URI is valid
172        (we might not have self.redirect_uri set), and returns a valid HTTP Response"""
173        uri = self.create_uri()
174        if urlparse(uri).scheme != "":
175            return HttpResponseRedirect(uri)
176        return bad_request_message(request, self.description, title=self.error)
177
178    def create_uri(self) -> str:
179        """Get a redirect URI with the error message"""
180        description = quote(str(self.description))
181
182        # See:
183        # http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthError
184        fragment_or_query = (
185            "#" if self.grant_type in [GrantTypes.IMPLICIT, GrantTypes.HYBRID] else "?"
186        )
187
188        uri = (
189            f"{self.redirect_uri}{fragment_or_query}error="
190            f"{self.error}&error_description={description}"
191        )
192
193        # Add state if present.
194        uri = uri + (f"&state={self.state}" if self.state else "")
195
196        return uri
197
198
199class TokenError(OAuth2Error):
200    """
201    OAuth2 token endpoint errors.
202    https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
203    """
204
205    errors = {
206        "invalid_request": "The request is otherwise malformed",
207        "invalid_client": (
208            "Client authentication failed (e.g., unknown client, no client authentication "
209            "included, or unsupported authentication method)"
210        ),
211        "invalid_grant": (
212            "The provided authorization grant or refresh token is invalid, expired, revoked, "
213            "does not match the redirection URI used in the authorization request, "
214            "or was issued to another client"
215        ),
216        "unauthorized_client": (
217            "The authenticated client is not authorized to use this authorization grant type"
218        ),
219        "unsupported_grant_type": (
220            "The authorization grant type is not supported by the authorization server"
221        ),
222        "invalid_scope": (
223            "The requested scope is invalid, unknown, malformed, or exceeds the scope "
224            "granted by the resource owner"
225        ),
226    }
227
228    def __init__(self, error):
229        super().__init__()
230        self.error = error
231        self.description = self.errors[error]
232
233
234class TokenRevocationError(OAuth2Error):
235    """
236    Specific to the revocation endpoint.
237    See https://datatracker.ietf.org/doc/html/rfc7662
238    """
239
240    errors = TokenError.errors | {
241        "unsupported_token_type": (
242            "The authorization server does not support the revocation of the presented "
243            "token type.  That is, the client tried to revoke an access token on a server not"
244            "supporting this feature."
245        )
246    }
247
248    def __init__(self, error: str):
249        super().__init__()
250        self.error = error
251        self.description = self.errors[error]
252
253
254class DeviceCodeError(TokenError):
255    """
256    Device-code flow errors
257    See https://datatracker.ietf.org/doc/html/rfc8628#section-3.2
258    Can also use codes form TokenError
259    """
260
261    errors = TokenError.errors | {
262        "authorization_pending": (
263            "The authorization request is still pending as the end user hasn't "
264            "yet completed the user-interaction steps"
265        ),
266        "access_denied": "The authorization request was denied.",
267        "expired_token": (
268            'The "device_code" has expired, and the device authorization '
269            "session has concluded.  The client MAY commence a new device "
270            "authorization request but SHOULD wait for user interaction before "
271            "restarting to avoid unnecessary polling."
272        ),
273        "slow_down": (
274            'A variant of "authorization_pending", the authorization request is'
275            "still pending and polling should continue, but the interval MUST"
276            "be increased by 5 seconds for this and all subsequent requests."
277        ),
278    }
279
280    def __init__(self, error: str):
281        super().__init__(error)
282        self.error = error
283        self.description = self.errors[error]
284
285
286class BearerTokenError(OAuth2Error):
287    """
288    OAuth2 errors.
289    https://datatracker.ietf.org/doc/html/rfc6750#section-3.1
290    """
291
292    errors = {
293        "invalid_request": ("The request is otherwise malformed", 400),
294        "invalid_token": (
295            (
296                "The access token provided is expired, revoked, malformed, "
297                "or invalid for other reasons"
298            ),
299            401,
300        ),
301        "insufficient_scope": (
302            "The request requires higher privileges than provided by the access token",
303            403,
304        ),
305    }
306
307    def __init__(self, code):
308        super().__init__()
309        self.code = code
310        error_tuple = self.errors.get(code, ("", ""))
311        self.description = error_tuple[0]
312        self.status = error_tuple[1]
class OAuth2Error(authentik.lib.sentry.SentryIgnoredException):
14class OAuth2Error(SentryIgnoredException):
15    """Base class for all OAuth2 Errors"""
16
17    error: str
18    description: str
19    cause: str | None = None
20
21    def create_dict(self, request: HttpRequest):
22        """Return error as dict for JSON Rendering"""
23        return {
24            "error": self.error,
25            "error_description": self.description,
26            "request_id": request.request_id,
27        }
28
29    def __repr__(self) -> str:
30        return self.error
31
32    def to_event(self, message: str | None = None, **kwargs) -> Event:
33        """Create configuration_error Event."""
34        return Event.new(
35            EventAction.CONFIGURATION_ERROR,
36            message=message or self.description,
37            cause=self.cause,
38            error=self.error,
39            **kwargs,
40        )
41
42    def with_cause(self, cause: str):
43        self.cause = cause
44        return self

Base class for all OAuth2 Errors

error: str
description: str
cause: str | None = None
def create_dict(self, request: django.http.request.HttpRequest):
21    def create_dict(self, request: HttpRequest):
22        """Return error as dict for JSON Rendering"""
23        return {
24            "error": self.error,
25            "error_description": self.description,
26            "request_id": request.request_id,
27        }

Return error as dict for JSON Rendering

def to_event( self, message: str | None = None, **kwargs) -> authentik.events.models.Event:
32    def to_event(self, message: str | None = None, **kwargs) -> Event:
33        """Create configuration_error Event."""
34        return Event.new(
35            EventAction.CONFIGURATION_ERROR,
36            message=message or self.description,
37            cause=self.cause,
38            error=self.error,
39            **kwargs,
40        )

Create configuration_error Event.

def with_cause(self, cause: str):
42    def with_cause(self, cause: str):
43        self.cause = cause
44        return self
class RedirectUriError(OAuth2Error):
47class RedirectUriError(OAuth2Error):
48    """The request fails due to a missing, invalid, or mismatching
49    redirection URI (redirect_uri)."""
50
51    error = "Redirect URI Error"
52    description = (
53        "The request fails due to a missing, invalid, or mismatching "
54        "redirection URI (redirect_uri)."
55    )
56
57    provided_uri: str
58    allowed_uris: list[RedirectURI]
59
60    def __init__(self, provided_uri: str, allowed_uris: list[RedirectURI]) -> None:
61        super().__init__()
62        self.provided_uri = provided_uri
63        self.allowed_uris = allowed_uris
64
65    def to_event(self, **kwargs) -> Event:
66        return super().to_event(
67            (
68                f"Invalid redirect URI was used. Client used '{self.provided_uri}'. "
69                f"Allowed redirect URIs are {','.join(self.allowed_uris)}"
70            ),
71            **kwargs,
72        )

The request fails due to a missing, invalid, or mismatching redirection URI (redirect_uri).

RedirectUriError( provided_uri: str, allowed_uris: list[authentik.providers.oauth2.models.RedirectURI])
60    def __init__(self, provided_uri: str, allowed_uris: list[RedirectURI]) -> None:
61        super().__init__()
62        self.provided_uri = provided_uri
63        self.allowed_uris = allowed_uris
error = 'Redirect URI Error'
description = 'The request fails due to a missing, invalid, or mismatching redirection URI (redirect_uri).'
provided_uri: str
def to_event(self, **kwargs) -> authentik.events.models.Event:
65    def to_event(self, **kwargs) -> Event:
66        return super().to_event(
67            (
68                f"Invalid redirect URI was used. Client used '{self.provided_uri}'. "
69                f"Allowed redirect URIs are {','.join(self.allowed_uris)}"
70            ),
71            **kwargs,
72        )

Create configuration_error Event.

class ClientIdError(OAuth2Error):
75class ClientIdError(OAuth2Error):
76    """The client identifier (client_id) is missing or invalid."""
77
78    error = "Client ID Error"
79    description = "The client identifier (client_id) is missing or invalid."
80
81    client_id: str
82
83    def __init__(self, client_id: str) -> None:
84        super().__init__()
85        self.client_id = client_id
86
87    def to_event(self, **kwargs) -> Event:
88        return super().to_event(f"Invalid client identifier: {self.client_id}.", **kwargs)

The client identifier (client_id) is missing or invalid.

ClientIdError(client_id: str)
83    def __init__(self, client_id: str) -> None:
84        super().__init__()
85        self.client_id = client_id
error = 'Client ID Error'
description = 'The client identifier (client_id) is missing or invalid.'
client_id: str
def to_event(self, **kwargs) -> authentik.events.models.Event:
87    def to_event(self, **kwargs) -> Event:
88        return super().to_event(f"Invalid client identifier: {self.client_id}.", **kwargs)

Create configuration_error Event.

class UserAuthError(OAuth2Error):
91class UserAuthError(OAuth2Error):
92    """
93    Specific to the Resource Owner Password Credentials flow when
94    the Resource Owners credentials are not valid.
95    """
96
97    error = "access_denied"
98    description = "The resource owner or authorization server denied the request."

Specific to the Resource Owner Password Credentials flow when the Resource Owners credentials are not valid.

error = 'access_denied'
description = 'The resource owner or authorization server denied the request.'
class TokenIntrospectionError(OAuth2Error):
101class TokenIntrospectionError(OAuth2Error):
102    """
103    Specific to the introspection endpoint. This error will be converted
104    to an "active: false" response, as per the spec.
105    See https://datatracker.ietf.org/doc/html/rfc7662
106    """

Specific to the introspection endpoint. This error will be converted to an "active: false" response, as per the spec. See https://datatracker.ietf.org/doc/html/rfc7662

class AuthorizeError(OAuth2Error):
109class AuthorizeError(OAuth2Error):
110    """General Authorization Errors"""
111
112    errors = {
113        # OAuth2 errors.
114        # https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1
115        "invalid_request": "The request is otherwise malformed",
116        "unauthorized_client": (
117            "The client is not authorized to request an authorization code using this method"
118        ),
119        "access_denied": "The resource owner or authorization server denied the request",
120        "unsupported_response_type": (
121            "The authorization server does not support obtaining an authorization code "
122            "using this method"
123        ),
124        "invalid_scope": "The requested scope is invalid, unknown, or malformed",
125        "server_error": "The authorization server encountered an error",
126        "temporarily_unavailable": (
127            "The authorization server is currently unable to handle the request due to a "
128            "temporary overloading or maintenance of the server"
129        ),
130        # OpenID errors.
131        # http://openid.net/specs/openid-connect-core-1_0.html#AuthError
132        "interaction_required": (
133            "The Authorization Server requires End-User interaction of some form to proceed"
134        ),
135        "login_required": "The Authorization Server requires End-User authentication",
136        "account_selection_required": (
137            "The End-User is required to select a session at the Authorization Server"
138        ),
139        "consent_required": "The Authorization Server requires End-User consent",
140        "invalid_request_uri": (
141            "The request_uri in the Authorization Request returns an error or contains invalid data"
142        ),
143        "invalid_request_object": "The request parameter contains an invalid Request Object",
144        "request_not_supported": "The provider does not support use of the request parameter",
145        "request_uri_not_supported": (
146            "The provider does not support use of the request_uri parameter"
147        ),
148        "registration_not_supported": (
149            "The provider does not support use of the registration parameter"
150        ),
151    }
152
153    def __init__(
154        self,
155        redirect_uri: str,
156        error: str,
157        grant_type: str,
158        state: str,
159        description: str | None = None,
160    ):
161        super().__init__()
162        self.error = error
163        if description:
164            self.description = description
165        else:
166            self.description = self.errors[error]
167        self.redirect_uri = redirect_uri
168        self.grant_type = grant_type
169        self.state = state
170
171    def get_response(self, request: HttpRequest) -> HttpResponse:
172        """Wrapper around `self.create_uri()` that checks if the resulting URI is valid
173        (we might not have self.redirect_uri set), and returns a valid HTTP Response"""
174        uri = self.create_uri()
175        if urlparse(uri).scheme != "":
176            return HttpResponseRedirect(uri)
177        return bad_request_message(request, self.description, title=self.error)
178
179    def create_uri(self) -> str:
180        """Get a redirect URI with the error message"""
181        description = quote(str(self.description))
182
183        # See:
184        # http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthError
185        fragment_or_query = (
186            "#" if self.grant_type in [GrantTypes.IMPLICIT, GrantTypes.HYBRID] else "?"
187        )
188
189        uri = (
190            f"{self.redirect_uri}{fragment_or_query}error="
191            f"{self.error}&error_description={description}"
192        )
193
194        # Add state if present.
195        uri = uri + (f"&state={self.state}" if self.state else "")
196
197        return uri

General Authorization Errors

AuthorizeError( redirect_uri: str, error: str, grant_type: str, state: str, description: str | None = None)
153    def __init__(
154        self,
155        redirect_uri: str,
156        error: str,
157        grant_type: str,
158        state: str,
159        description: str | None = None,
160    ):
161        super().__init__()
162        self.error = error
163        if description:
164            self.description = description
165        else:
166            self.description = self.errors[error]
167        self.redirect_uri = redirect_uri
168        self.grant_type = grant_type
169        self.state = state
errors = {'invalid_request': 'The request is otherwise malformed', 'unauthorized_client': 'The client is not authorized to request an authorization code using this method', 'access_denied': 'The resource owner or authorization server denied the request', 'unsupported_response_type': 'The authorization server does not support obtaining an authorization code using this method', 'invalid_scope': 'The requested scope is invalid, unknown, or malformed', 'server_error': 'The authorization server encountered an error', 'temporarily_unavailable': 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server', 'interaction_required': 'The Authorization Server requires End-User interaction of some form to proceed', 'login_required': 'The Authorization Server requires End-User authentication', 'account_selection_required': 'The End-User is required to select a session at the Authorization Server', 'consent_required': 'The Authorization Server requires End-User consent', 'invalid_request_uri': 'The request_uri in the Authorization Request returns an error or contains invalid data', 'invalid_request_object': 'The request parameter contains an invalid Request Object', 'request_not_supported': 'The provider does not support use of the request parameter', 'request_uri_not_supported': 'The provider does not support use of the request_uri parameter', 'registration_not_supported': 'The provider does not support use of the registration parameter'}
error
redirect_uri
grant_type
state
def get_response( self, request: django.http.request.HttpRequest) -> django.http.response.HttpResponse:
171    def get_response(self, request: HttpRequest) -> HttpResponse:
172        """Wrapper around `self.create_uri()` that checks if the resulting URI is valid
173        (we might not have self.redirect_uri set), and returns a valid HTTP Response"""
174        uri = self.create_uri()
175        if urlparse(uri).scheme != "":
176            return HttpResponseRedirect(uri)
177        return bad_request_message(request, self.description, title=self.error)

Wrapper around self.create_uri() that checks if the resulting URI is valid (we might not have self.redirect_uri set), and returns a valid HTTP Response

def create_uri(self) -> str:
179    def create_uri(self) -> str:
180        """Get a redirect URI with the error message"""
181        description = quote(str(self.description))
182
183        # See:
184        # http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthError
185        fragment_or_query = (
186            "#" if self.grant_type in [GrantTypes.IMPLICIT, GrantTypes.HYBRID] else "?"
187        )
188
189        uri = (
190            f"{self.redirect_uri}{fragment_or_query}error="
191            f"{self.error}&error_description={description}"
192        )
193
194        # Add state if present.
195        uri = uri + (f"&state={self.state}" if self.state else "")
196
197        return uri

Get a redirect URI with the error message

class TokenError(OAuth2Error):
200class TokenError(OAuth2Error):
201    """
202    OAuth2 token endpoint errors.
203    https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
204    """
205
206    errors = {
207        "invalid_request": "The request is otherwise malformed",
208        "invalid_client": (
209            "Client authentication failed (e.g., unknown client, no client authentication "
210            "included, or unsupported authentication method)"
211        ),
212        "invalid_grant": (
213            "The provided authorization grant or refresh token is invalid, expired, revoked, "
214            "does not match the redirection URI used in the authorization request, "
215            "or was issued to another client"
216        ),
217        "unauthorized_client": (
218            "The authenticated client is not authorized to use this authorization grant type"
219        ),
220        "unsupported_grant_type": (
221            "The authorization grant type is not supported by the authorization server"
222        ),
223        "invalid_scope": (
224            "The requested scope is invalid, unknown, malformed, or exceeds the scope "
225            "granted by the resource owner"
226        ),
227    }
228
229    def __init__(self, error):
230        super().__init__()
231        self.error = error
232        self.description = self.errors[error]
TokenError(error)
229    def __init__(self, error):
230        super().__init__()
231        self.error = error
232        self.description = self.errors[error]
errors = {'invalid_request': 'The request is otherwise malformed', 'invalid_client': 'Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)', 'invalid_grant': 'The provided authorization grant or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client', 'unauthorized_client': 'The authenticated client is not authorized to use this authorization grant type', 'unsupported_grant_type': 'The authorization grant type is not supported by the authorization server', 'invalid_scope': 'The requested scope is invalid, unknown, malformed, or exceeds the scope granted by the resource owner'}
error
description
class TokenRevocationError(OAuth2Error):
235class TokenRevocationError(OAuth2Error):
236    """
237    Specific to the revocation endpoint.
238    See https://datatracker.ietf.org/doc/html/rfc7662
239    """
240
241    errors = TokenError.errors | {
242        "unsupported_token_type": (
243            "The authorization server does not support the revocation of the presented "
244            "token type.  That is, the client tried to revoke an access token on a server not"
245            "supporting this feature."
246        )
247    }
248
249    def __init__(self, error: str):
250        super().__init__()
251        self.error = error
252        self.description = self.errors[error]

Specific to the revocation endpoint. See https://datatracker.ietf.org/doc/html/rfc7662

TokenRevocationError(error: str)
249    def __init__(self, error: str):
250        super().__init__()
251        self.error = error
252        self.description = self.errors[error]
errors = {'invalid_request': 'The request is otherwise malformed', 'invalid_client': 'Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)', 'invalid_grant': 'The provided authorization grant or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client', 'unauthorized_client': 'The authenticated client is not authorized to use this authorization grant type', 'unsupported_grant_type': 'The authorization grant type is not supported by the authorization server', 'invalid_scope': 'The requested scope is invalid, unknown, malformed, or exceeds the scope granted by the resource owner', 'unsupported_token_type': 'The authorization server does not support the revocation of the presented token type. That is, the client tried to revoke an access token on a server notsupporting this feature.'}
error
description
class DeviceCodeError(TokenError):
255class DeviceCodeError(TokenError):
256    """
257    Device-code flow errors
258    See https://datatracker.ietf.org/doc/html/rfc8628#section-3.2
259    Can also use codes form TokenError
260    """
261
262    errors = TokenError.errors | {
263        "authorization_pending": (
264            "The authorization request is still pending as the end user hasn't "
265            "yet completed the user-interaction steps"
266        ),
267        "access_denied": "The authorization request was denied.",
268        "expired_token": (
269            'The "device_code" has expired, and the device authorization '
270            "session has concluded.  The client MAY commence a new device "
271            "authorization request but SHOULD wait for user interaction before "
272            "restarting to avoid unnecessary polling."
273        ),
274        "slow_down": (
275            'A variant of "authorization_pending", the authorization request is'
276            "still pending and polling should continue, but the interval MUST"
277            "be increased by 5 seconds for this and all subsequent requests."
278        ),
279    }
280
281    def __init__(self, error: str):
282        super().__init__(error)
283        self.error = error
284        self.description = self.errors[error]

Device-code flow errors See https://datatracker.ietf.org/doc/html/rfc8628#section-3.2 Can also use codes form TokenError

DeviceCodeError(error: str)
281    def __init__(self, error: str):
282        super().__init__(error)
283        self.error = error
284        self.description = self.errors[error]
errors = {'invalid_request': 'The request is otherwise malformed', 'invalid_client': 'Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)', 'invalid_grant': 'The provided authorization grant or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client', 'unauthorized_client': 'The authenticated client is not authorized to use this authorization grant type', 'unsupported_grant_type': 'The authorization grant type is not supported by the authorization server', 'invalid_scope': 'The requested scope is invalid, unknown, malformed, or exceeds the scope granted by the resource owner', 'authorization_pending': "The authorization request is still pending as the end user hasn't yet completed the user-interaction steps", 'access_denied': 'The authorization request was denied.', 'expired_token': 'The "device_code" has expired, and the device authorization session has concluded. The client MAY commence a new device authorization request but SHOULD wait for user interaction before restarting to avoid unnecessary polling.', 'slow_down': 'A variant of "authorization_pending", the authorization request isstill pending and polling should continue, but the interval MUSTbe increased by 5 seconds for this and all subsequent requests.'}
error
description
class BearerTokenError(OAuth2Error):
287class BearerTokenError(OAuth2Error):
288    """
289    OAuth2 errors.
290    https://datatracker.ietf.org/doc/html/rfc6750#section-3.1
291    """
292
293    errors = {
294        "invalid_request": ("The request is otherwise malformed", 400),
295        "invalid_token": (
296            (
297                "The access token provided is expired, revoked, malformed, "
298                "or invalid for other reasons"
299            ),
300            401,
301        ),
302        "insufficient_scope": (
303            "The request requires higher privileges than provided by the access token",
304            403,
305        ),
306    }
307
308    def __init__(self, code):
309        super().__init__()
310        self.code = code
311        error_tuple = self.errors.get(code, ("", ""))
312        self.description = error_tuple[0]
313        self.status = error_tuple[1]
BearerTokenError(code)
308    def __init__(self, code):
309        super().__init__()
310        self.code = code
311        error_tuple = self.errors.get(code, ("", ""))
312        self.description = error_tuple[0]
313        self.status = error_tuple[1]
errors = {'invalid_request': ('The request is otherwise malformed', 400), 'invalid_token': ('The access token provided is expired, revoked, malformed, or invalid for other reasons', 401), 'insufficient_scope': ('The request requires higher privileges than provided by the access token', 403)}
code
description
status