You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
4.8 KiB
121 lines
4.8 KiB
# -*- coding: utf-8 -*-
|
|
"""
|
|
oauthlib.oauth2.rfc6749.grant_types
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
"""
|
|
from __future__ import absolute_import, unicode_literals
|
|
|
|
import json
|
|
import logging
|
|
|
|
from .. import errors
|
|
from ..request_validator import RequestValidator
|
|
from .base import GrantTypeBase
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class ClientCredentialsGrant(GrantTypeBase):
|
|
|
|
"""`Client Credentials Grant`_
|
|
|
|
The client can request an access token using only its client
|
|
credentials (or other supported means of authentication) when the
|
|
client is requesting access to the protected resources under its
|
|
control, or those of another resource owner that have been previously
|
|
arranged with the authorization server (the method of which is beyond
|
|
the scope of this specification).
|
|
|
|
The client credentials grant type MUST only be used by confidential
|
|
clients::
|
|
|
|
+---------+ +---------------+
|
|
: : : :
|
|
: :>-- A - Client Authentication --->: Authorization :
|
|
: Client : : Server :
|
|
: :<-- B ---- Access Token ---------<: :
|
|
: : : :
|
|
+---------+ +---------------+
|
|
|
|
Figure 6: Client Credentials Flow
|
|
|
|
The flow illustrated in Figure 6 includes the following steps:
|
|
|
|
(A) The client authenticates with the authorization server and
|
|
requests an access token from the token endpoint.
|
|
|
|
(B) The authorization server authenticates the client, and if valid,
|
|
issues an access token.
|
|
|
|
.. _`Client Credentials Grant`: https://tools.ietf.org/html/rfc6749#section-4.4
|
|
"""
|
|
|
|
def create_token_response(self, request, token_handler):
|
|
"""Return token or error in JSON format.
|
|
|
|
If the access token request is valid and authorized, the
|
|
authorization server issues an access token as described in
|
|
`Section 5.1`_. A refresh token SHOULD NOT be included. If the request
|
|
failed client authentication or is invalid, the authorization server
|
|
returns an error response as described in `Section 5.2`_.
|
|
|
|
.. _`Section 5.1`: https://tools.ietf.org/html/rfc6749#section-5.1
|
|
.. _`Section 5.2`: https://tools.ietf.org/html/rfc6749#section-5.2
|
|
"""
|
|
headers = {
|
|
'Content-Type': 'application/json',
|
|
'Cache-Control': 'no-store',
|
|
'Pragma': 'no-cache',
|
|
}
|
|
try:
|
|
log.debug('Validating access token request, %r.', request)
|
|
self.validate_token_request(request)
|
|
except errors.OAuth2Error as e:
|
|
log.debug('Client error in token request. %s.', e)
|
|
return headers, e.json, e.status_code
|
|
|
|
token = token_handler.create_token(request, refresh_token=False, save_token=False)
|
|
|
|
for modifier in self._token_modifiers:
|
|
token = modifier(token)
|
|
self.request_validator.save_token(token, request)
|
|
|
|
log.debug('Issuing token to client id %r (%r), %r.',
|
|
request.client_id, request.client, token)
|
|
return headers, json.dumps(token), 200
|
|
|
|
def validate_token_request(self, request):
|
|
for validator in self.custom_validators.pre_token:
|
|
validator(request)
|
|
|
|
if not getattr(request, 'grant_type', None):
|
|
raise errors.InvalidRequestError('Request is missing grant type.',
|
|
request=request)
|
|
|
|
if not request.grant_type == 'client_credentials':
|
|
raise errors.UnsupportedGrantTypeError(request=request)
|
|
|
|
for param in ('grant_type', 'scope'):
|
|
if param in request.duplicate_params:
|
|
raise errors.InvalidRequestError(description='Duplicate %s parameter.' % param,
|
|
request=request)
|
|
|
|
log.debug('Authenticating client, %r.', request)
|
|
if not self.request_validator.authenticate_client(request):
|
|
log.debug('Client authentication failed, %r.', request)
|
|
raise errors.InvalidClientError(request=request)
|
|
else:
|
|
if not hasattr(request.client, 'client_id'):
|
|
raise NotImplementedError('Authenticate client must set the '
|
|
'request.client.client_id attribute '
|
|
'in authenticate_client.')
|
|
# Ensure client is authorized use of this grant type
|
|
self.validate_grant_type(request)
|
|
|
|
log.debug('Authorizing access to user %r.', request.user)
|
|
request.client_id = request.client_id or request.client.client_id
|
|
self.validate_scopes(request)
|
|
|
|
for validator in self.custom_validators.post_token:
|
|
validator(request)
|