2015-07-01 19:43:35 +00:00
|
|
|
try:
|
|
|
|
from urllib.parse import quote
|
|
|
|
except ImportError:
|
|
|
|
from urllib import quote
|
2014-12-19 15:27:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
class RedirectUriError(Exception):
|
|
|
|
|
2015-01-09 17:59:23 +00:00
|
|
|
error = 'Redirect URI Error'
|
2018-03-22 20:53:31 +00:00
|
|
|
description = 'The request fails due to a missing, invalid, or mismatching' \
|
|
|
|
' redirection URI (redirect_uri).'
|
2014-12-19 15:27:43 +00:00
|
|
|
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2014-12-19 15:27:43 +00:00
|
|
|
class ClientIdError(Exception):
|
|
|
|
|
2015-01-09 17:59:23 +00:00
|
|
|
error = 'Client ID Error'
|
2014-12-19 15:27:43 +00:00
|
|
|
description = 'The client identifier (client_id) is missing or invalid.'
|
|
|
|
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2017-05-05 03:19:57 +00:00
|
|
|
class UserAuthError(Exception):
|
|
|
|
"""
|
|
|
|
Specific to the Resource Owner Password Credentials flow when
|
|
|
|
the Resource Owners credentials are not valid.
|
|
|
|
"""
|
|
|
|
error = 'access_denied'
|
2018-03-23 18:46:12 +00:00
|
|
|
description = 'The resource owner or authorization server denied the request.'
|
2017-05-05 03:19:57 +00:00
|
|
|
|
|
|
|
def create_dict(self):
|
|
|
|
return {
|
|
|
|
'error': self.error,
|
|
|
|
'error_description': self.description,
|
|
|
|
}
|
|
|
|
|
2017-08-08 22:41:42 +00:00
|
|
|
|
2014-12-19 15:27:43 +00:00
|
|
|
class AuthorizeError(Exception):
|
|
|
|
|
|
|
|
_errors = {
|
|
|
|
# Oauth2 errors.
|
|
|
|
# https://tools.ietf.org/html/rfc6749#section-4.1.2.1
|
|
|
|
'invalid_request': 'The request is otherwise malformed',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'unauthorized_client': 'The client is not authorized to request an '
|
|
|
|
'authorization code using this method',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'access_denied': 'The resource owner or authorization server denied '
|
|
|
|
'the request',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'unsupported_response_type': 'The authorization server does not '
|
|
|
|
'support obtaining an authorization code '
|
|
|
|
'using this method',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'invalid_scope': 'The requested scope is invalid, unknown, or '
|
|
|
|
'malformed',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2014-12-19 15:27:43 +00:00
|
|
|
'server_error': 'The authorization server encountered an error',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'temporarily_unavailable': 'The authorization server is currently '
|
|
|
|
'unable to handle the request due to a '
|
|
|
|
'temporary overloading or maintenance of '
|
|
|
|
'the server',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2014-12-19 15:27:43 +00:00
|
|
|
# OpenID errors.
|
|
|
|
# http://openid.net/specs/openid-connect-core-1_0.html#AuthError
|
2015-05-13 21:36:04 +00:00
|
|
|
'interaction_required': 'The Authorization Server requires End-User '
|
|
|
|
'interaction of some form to proceed',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'login_required': 'The Authorization Server requires End-User '
|
|
|
|
'authentication',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'account_selection_required': 'The End-User is required to select a '
|
|
|
|
'session at the Authorization Server',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'consent_required': 'The Authorization Server requires End-User'
|
|
|
|
'consent',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'invalid_request_uri': 'The request_uri in the Authorization Request '
|
|
|
|
'returns an error or contains invalid data',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'invalid_request_object': 'The request parameter contains an invalid '
|
|
|
|
'Request Object',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'request_not_supported': 'The provider does not support use of the '
|
|
|
|
'request parameter',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'request_uri_not_supported': 'The provider does not support use of the '
|
|
|
|
'request_uri parameter',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'registration_not_supported': 'The provider does not support use of '
|
|
|
|
'the registration parameter',
|
2014-12-19 15:27:43 +00:00
|
|
|
}
|
|
|
|
|
2015-01-08 20:55:24 +00:00
|
|
|
def __init__(self, redirect_uri, error, grant_type):
|
2014-12-19 15:27:43 +00:00
|
|
|
self.error = error
|
|
|
|
self.description = self._errors.get(error)
|
|
|
|
self.redirect_uri = redirect_uri
|
2015-01-08 20:55:24 +00:00
|
|
|
self.grant_type = grant_type
|
2014-12-19 15:27:43 +00:00
|
|
|
|
|
|
|
def create_uri(self, redirect_uri, state):
|
2015-07-01 19:43:35 +00:00
|
|
|
description = quote(self.description)
|
2014-12-19 15:27:43 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
# See:
|
|
|
|
# http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthError
|
2015-01-08 20:55:24 +00:00
|
|
|
hash_or_question = '#' if self.grant_type == 'implicit' else '?'
|
|
|
|
|
|
|
|
uri = '{0}{1}error={2}&error_description={3}'.format(
|
|
|
|
redirect_uri,
|
|
|
|
hash_or_question,
|
|
|
|
self.error,
|
|
|
|
description)
|
2014-12-19 15:27:43 +00:00
|
|
|
|
|
|
|
# Add state if present.
|
2015-01-06 22:51:47 +00:00
|
|
|
uri = uri + ('&state={0}'.format(state) if state else '')
|
2014-12-19 15:27:43 +00:00
|
|
|
|
|
|
|
return uri
|
|
|
|
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2014-12-19 15:27:43 +00:00
|
|
|
class TokenError(Exception):
|
2016-02-15 20:13:19 +00:00
|
|
|
"""
|
|
|
|
OAuth2 token endpoint errors.
|
|
|
|
https://tools.ietf.org/html/rfc6749#section-5.2
|
|
|
|
"""
|
2014-12-19 15:27:43 +00:00
|
|
|
|
|
|
|
_errors = {
|
|
|
|
'invalid_request': 'The request is otherwise malformed',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'invalid_client': 'Client authentication failed (e.g., unknown client, '
|
|
|
|
'no client authentication included, or unsupported '
|
|
|
|
'authentication method)',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'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',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'unauthorized_client': 'The authenticated client is not authorized to '
|
|
|
|
'use this authorization grant type',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'unsupported_grant_type': 'The authorization grant type is not '
|
|
|
|
'supported by the authorization server',
|
2015-01-28 18:19:36 +00:00
|
|
|
|
2015-05-13 21:36:04 +00:00
|
|
|
'invalid_scope': 'The requested scope is invalid, unknown, malformed, '
|
|
|
|
'or exceeds the scope granted by the resource owner',
|
2014-12-19 15:27:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
def __init__(self, error):
|
|
|
|
self.error = error
|
|
|
|
self.description = self._errors.get(error)
|
|
|
|
|
|
|
|
def create_dict(self):
|
|
|
|
dic = {
|
|
|
|
'error': self.error,
|
|
|
|
'error_description': self.description,
|
|
|
|
}
|
|
|
|
|
|
|
|
return dic
|
|
|
|
|
|
|
|
|
2016-02-15 20:13:19 +00:00
|
|
|
class BearerTokenError(Exception):
|
|
|
|
"""
|
|
|
|
OAuth2 errors.
|
|
|
|
https://tools.ietf.org/html/rfc6750#section-3.1
|
|
|
|
"""
|
|
|
|
|
2014-12-19 15:27:43 +00:00
|
|
|
_errors = {
|
2015-01-28 18:19:36 +00:00
|
|
|
'invalid_request': (
|
|
|
|
'The request is otherwise malformed', 400
|
|
|
|
),
|
|
|
|
'invalid_token': (
|
2015-05-13 21:36:04 +00:00
|
|
|
'The access token provided is expired, revoked, malformed, '
|
|
|
|
'or invalid for other reasons', 401
|
2015-01-28 18:19:36 +00:00
|
|
|
),
|
|
|
|
'insufficient_scope': (
|
2015-05-13 21:36:04 +00:00
|
|
|
'The request requires higher privileges than provided by '
|
|
|
|
'the access token', 403
|
2015-01-28 18:19:36 +00:00
|
|
|
),
|
2014-12-19 15:27:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
def __init__(self, code):
|
|
|
|
self.code = code
|
|
|
|
error_tuple = self._errors.get(code, ('', ''))
|
|
|
|
self.description = error_tuple[0]
|
|
|
|
self.status = error_tuple[1]
|