try: from urllib.parse import quote except ImportError: from urllib import quote class RedirectUriError(Exception): error = 'Redirect URI Error' description = 'The request fails due to a missing, invalid, or mismatching' \ ' redirection URI (redirect_uri).' class ClientIdError(Exception): error = 'Client ID Error' description = 'The client identifier (client_id) is missing or invalid.' class UserAuthError(Exception): """ 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.' def create_dict(self): return { 'error': self.error, 'error_description': self.description, } class TokenIntrospectionError(Exception): """ Specific to the introspection endpoint. This error will be converted to an "active: false" response, as per the spec. See https://tools.ietf.org/html/rfc7662 """ pass class AuthorizeError(Exception): _errors = { # Oauth2 errors. # https://tools.ietf.org/html/rfc6749#section-4.1.2.1 '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', # OpenID errors. # http://openid.net/specs/openid-connect-core-1_0.html#AuthError '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', } def __init__(self, redirect_uri, error, grant_type): self.error = error self.description = self._errors.get(error) self.redirect_uri = redirect_uri self.grant_type = grant_type def create_uri(self, redirect_uri, state): description = quote(self.description) # See: # http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthError 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) # Add state if present. uri = uri + ('&state={0}'.format(state) if state else '') return uri class TokenError(Exception): """ OAuth2 token endpoint errors. https://tools.ietf.org/html/rfc6749#section-5.2 """ _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', } 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 class BearerTokenError(Exception): """ OAuth2 errors. https://tools.ietf.org/html/rfc6750#section-3.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 ), } def __init__(self, code): self.code = code error_tuple = self._errors.get(code, ('', '')) self.description = error_tuple[0] self.status = error_tuple[1]