summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Huot <JonathanHuot@users.noreply.github.com>2020-04-22 16:11:47 +0200
committerGitHub <noreply@github.com>2020-04-22 16:11:47 +0200
commitaf5ac6d7da7aaad09ab5ffeb31a2972aaffe3e2f (patch)
treee7dc3844024d38021ba4edc4fb6dbb55a85d2e56
parent75b9f4f7e4387e670a3fae925d5522ff3a01a746 (diff)
parent82544c2034987080ad6e11c3f1efe7378467c57b (diff)
downloadoauthlib-af5ac6d7da7aaad09ab5ffeb31a2972aaffe3e2f.tar.gz
Merge branch 'master' into doc-sponsor
-rw-r--r--CHANGELOG.rst50
-rw-r--r--docs/oauth2/grants/custom_grant.rst78
-rw-r--r--docs/oauth2/grants/custom_validators.rst12
-rw-r--r--docs/oauth2/grants/grants.rst30
-rw-r--r--docs/oauth2/grants/refresh.rst6
-rw-r--r--docs/oauth2/oidc.rst17
-rw-r--r--docs/oauth2/oidc/authcode.rst6
-rw-r--r--docs/oauth2/oidc/dispatchers.rst24
-rw-r--r--docs/oauth2/oidc/endpoints.rst21
-rw-r--r--docs/oauth2/oidc/grants.rst41
-rw-r--r--docs/oauth2/oidc/hybrid.rst6
-rw-r--r--docs/oauth2/oidc/implicit.rst6
-rw-r--r--docs/oauth2/oidc/userinfo.rst7
-rw-r--r--docs/oauth2/oidc/validator.rst33
-rw-r--r--docs/oauth2/server.rst11
-rw-r--r--examples/skeleton_oauth2_web_application_server.py9
-rw-r--r--oauthlib/oauth2/rfc6749/clients/base.py26
-rw-r--r--oauthlib/oauth2/rfc6749/clients/legacy_application.py1
-rw-r--r--oauthlib/oauth2/rfc6749/clients/mobile_application.py2
-rw-r--r--oauthlib/oauth2/rfc6749/clients/service_application.py1
-rw-r--r--oauthlib/oauth2/rfc6749/clients/web_application.py1
-rw-r--r--oauthlib/oauth2/rfc6749/grant_types/client_credentials.py2
-rw-r--r--oauthlib/openid/connect/core/grant_types/dispatchers.py19
-rw-r--r--requirements-test.txt1
-rw-r--r--tests/oauth1/rfc5849/endpoints/test_access_token.py2
-rw-r--r--tests/oauth1/rfc5849/endpoints/test_authorization.py2
-rw-r--r--tests/oauth1/rfc5849/endpoints/test_base.py2
-rw-r--r--tests/oauth1/rfc5849/endpoints/test_request_token.py2
-rw-r--r--tests/oauth1/rfc5849/endpoints/test_resource.py2
-rw-r--r--tests/oauth1/rfc5849/endpoints/test_signature_only.py2
-rw-r--r--tests/oauth2/rfc6749/clients/test_backend_application.py2
-rw-r--r--tests/oauth2/rfc6749/clients/test_legacy_application.py2
-rw-r--r--tests/oauth2/rfc6749/clients/test_mobile_application.py2
-rw-r--r--tests/oauth2/rfc6749/clients/test_service_application.py2
-rw-r--r--tests/oauth2/rfc6749/clients/test_web_application.py2
-rw-r--r--tests/oauth2/rfc6749/endpoints/test_client_authentication.py2
-rw-r--r--tests/oauth2/rfc6749/endpoints/test_credentials_preservation.py2
-rw-r--r--tests/oauth2/rfc6749/endpoints/test_error_responses.py2
-rw-r--r--tests/oauth2/rfc6749/endpoints/test_extra_credentials.py2
-rw-r--r--tests/oauth2/rfc6749/endpoints/test_introspect_endpoint.py2
-rw-r--r--tests/oauth2/rfc6749/endpoints/test_resource_owner_association.py2
-rw-r--r--tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py2
-rw-r--r--tests/oauth2/rfc6749/endpoints/test_scope_handling.py2
-rw-r--r--tests/oauth2/rfc6749/grant_types/test_authorization_code.py2
-rw-r--r--tests/oauth2/rfc6749/grant_types/test_client_credentials.py2
-rw-r--r--tests/oauth2/rfc6749/grant_types/test_implicit.py2
-rw-r--r--tests/oauth2/rfc6749/grant_types/test_refresh_token.py2
-rw-r--r--tests/oauth2/rfc6749/grant_types/test_resource_owner_password.py2
-rw-r--r--tests/oauth2/rfc6749/test_parameters.py2
-rw-r--r--tests/oauth2/rfc6749/test_server.py2
-rw-r--r--tests/oauth2/rfc6749/test_tokens.py2
-rw-r--r--tests/openid/connect/core/endpoints/test_claims_handling.py2
-rw-r--r--tests/openid/connect/core/endpoints/test_openid_connect_params_handling.py2
-rw-r--r--tests/openid/connect/core/endpoints/test_userinfo_endpoint.py2
-rw-r--r--tests/openid/connect/core/grant_types/test_authorization_code.py2
-rw-r--r--tests/openid/connect/core/grant_types/test_base.py2
-rw-r--r--tests/openid/connect/core/grant_types/test_dispatchers.py2
-rw-r--r--tests/openid/connect/core/grant_types/test_hybrid.py2
-rw-r--r--tests/openid/connect/core/grant_types/test_implicit.py2
-rw-r--r--tests/openid/connect/core/test_server.py2
-rw-r--r--tests/openid/connect/core/test_tokens.py2
61 files changed, 389 insertions, 95 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index e07ec3c..c42df83 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,33 +1,51 @@
Changelog
=========
-3.1.0 (TBD)
+3.1.1 (TBD)
------------------
+OAuth2.0 Client - Bugfixes
+ * #730: Base OAuth2 Client now has a consistent way of managing the `scope`: it consistently
+ relies on the `scope` provided in the constructor if any, except if overridden temporarily
+ in a method call. Note that in particular providing a non-None `scope` in
+ `prepare_authorization_request` or `prepare_refresh_token` does not override anymore
+ `self.scope` forever, it is just used temporarily.
+ * #726: MobileApplicationClient.prepare_request_uri and MobileApplicationClient.parse_request_uri_response,
+ ServiceApplicationClient.prepare_request_body,
+ and WebApplicationClient.prepare_request_uri now correctly use the default `scope` provided in
+ constructor.
+ * #725: LegacyApplicationClient.prepare_request_body now correctly uses the default `scope` provided in constructor
+
+3.1.0 (2019-08-06)
+------------------
OAuth2.0 Provider - Features
-* #660: OIDC add support of nonce, c_hash, at_hash fields
- - New RequestValidator.fill_id_token method
- - Deprecated RequestValidator.get_id_token method
-* #677: OIDC add UserInfo endpoint
- - New RequestValidator.get_userinfo_claims method
+
+ * #660: OIDC add support of `nonce`, `c_hash`, `at_hash fields`
+ - New `RequestValidator.fill_id_token` method
+ - Deprecated `RequestValidator.get_id_token` method
+ * #677: OIDC add `UserInfo` endpoint - New `RequestValidator.get_userinfo_claims` method
OAuth2.0 Provider - Security
-* #665: Enhance data leak to logs
- - New default to not expose request content in logs
- - New function `oauthlib.set_debug(True)`
-* #666: Disabling query parameters for POST requests
+
+ * #665: Enhance data leak to logs
+ * New default to not expose request content in logs
+ * New function `oauthlib.set_debug(True)`
+ * #666: Disabling query parameters for POST requests
OAuth2.0 Provider - Bugfixes
-* #670: Fix validate_authorization_request to return the new PKCE fields
-* #674: Fix token_type to be case-insensitive (bearer and Bearer)
+
+ * #670: Fix `validate_authorization_request` to return the new PKCE fields
+ * #674: Fix `token_type` to be case-insensitive (`bearer` and `Bearer`)
OAuth2.0 Client - Bugfixes
-* #290: Fix Authorization Code's errors processing
-* #603: BackendApplication.Client.prepare_request_body use the "scope" argument as intended.
-* #672: Fix edge case when expires_in=Null
+
+ * #290: Fix Authorization Code's errors processing
+ * #603: BackendApplicationClient.prepare_request_body use the `scope` argument as intended.
+ * #672: Fix edge case when `expires_in=Null`
OAuth1.0 Client
-* #669: Add case-insensitive headers to oauth1 BaseEndpoint
+
+ * #669: Add case-insensitive headers to oauth1 `BaseEndpoint`
3.0.2 (2019-07-04)
------------------
diff --git a/docs/oauth2/grants/custom_grant.rst b/docs/oauth2/grants/custom_grant.rst
new file mode 100644
index 0000000..8c4571c
--- /dev/null
+++ b/docs/oauth2/grants/custom_grant.rst
@@ -0,0 +1,78 @@
+=================
+Custom Grant type
+=================
+
+Writing a custom grant type can be useful to implement a specification
+which is in an early draft, or implement a grant provided by a
+specific OAuth2.0 Authorization Server documentation but not provided
+by oauthlib. For information, any grant types with a clear
+specification can be integrated in oauthlib, just make a PR for that !
+See :doc:`how to contribute here </contributing>`.
+
+Please find how to create a new grant and use it in an endpoint:
+
+.. contents:: Tutorial Contents
+ :depth: 3
+
+
+1. Define your Grant Type
+-------------------------
+The heart of your code is done by subclassing
+:py:class:`GrantTypeBase`. If you want to use it in the Authorize
+endpoint, you will have to implement
+:py:meth:`create_authorization_response`, if you want to use the Token
+endpoint, implement :py:meth:`create_token_response`. You can also
+implement both.
+
+2. Implement the grant
+----------------------
+Inside the method's implementation, you will have to:
+
+* add validations of the request (syntax, parameters, ...)
+* call and orchestrate one or multiple Request Validators calls
+* generate and return HTTP response
+
+You can define new Request Validator methods if needed, or reuse the
+existing ones.
+
+3. Associate it with Endpoints
+------------------------------
+Then, once implemented, you have to instanciate the grant object and
+bind it to your endpoint. Either :py:class:`AuthorizationEndpoint`,
+:py:class:`TokenEndpoint` or both.
+
+4. Example
+----------
+This example shows how to add a simple extension to the `Token endpoint`:
+
+* creation of a new class ``MyCustomGrant``, and implement ``create_token_response``.
+* do basics and custom request validations, then call a custom method
+ of `Request Validator` to extend the interface for the implementor.
+* instanciate the new grant, and bind it with an existing ``Server``.
+
+.. code-block:: python
+
+ grant_name = 'urn:ietf:params:oauth:grant-type:my-custom-grant'
+
+ class MyCustomGrant(GrantTypeBase):
+ def create_token_response(self, request, token_handler):
+ if not request.grant_type == grant_name:
+ raise errors.UnsupportedGrantTypeError(request=request)
+
+ # implement your custom validation checks
+ # ..
+ self.request_validator.your_custom_check(request)
+
+ token = token_handler.create_token(request)
+ return self._get_default_headers(), json.dumps(token), 200
+
+ def setup_oauthlib():
+ my_custom_grant = MyCustomGrant()
+ server = Server(request_validator)
+ server.grant_types[grant_name] = my_custom_grant
+
+
+You can find concrete examples directly in the code source of existing
+grants and existing servers. See Grant Types in
+:py:mod:`oauthlib.oauth2.rfc749.grant_types`, and Servers in
+:py:mod:`oauthlib.oauth2.rfc749.endpoints.pre_configured`
diff --git a/docs/oauth2/grants/custom_validators.rst b/docs/oauth2/grants/custom_validators.rst
index 4629e6f..9917dd7 100644
--- a/docs/oauth2/grants/custom_validators.rst
+++ b/docs/oauth2/grants/custom_validators.rst
@@ -1,5 +1,15 @@
Custom Validators
-----------------
-.. autoclass:: oauthlib.oauth2.rfc6749.grant_types.base.ValidatorsContainer
+The Custom validators are useful when you want to change a particular
+behavior of an existing grant. That is often needed because of the
+diversity of the identity softwares and to let the oauthlib framework to be
+flexible as possible.
+
+However, if you are looking into writing a custom grant type, please
+refer to the :doc:`Custom Grant Type </oauth2/grants/custom_grant>`
+instead.
+
+.. autoclass::
+ oauthlib.oauth2.rfc6749.grant_types.base.ValidatorsContainer
:members:
diff --git a/docs/oauth2/grants/grants.rst b/docs/oauth2/grants/grants.rst
index 16b17be..e183761 100644
--- a/docs/oauth2/grants/grants.rst
+++ b/docs/oauth2/grants/grants.rst
@@ -9,23 +9,32 @@ Grant types
implicit
password
credentials
- custom_validators
+ refresh
jwt
+ custom_validators
+ custom_grant
-Grant types are what make OAuth 2 so flexible. The Authorization Code grant is
-very similar to OAuth 1 (with less crypto), the Implicit grant serves less
-secure applications such as mobile applications, the Resource Owner Password
-Credentials grant allows for legacy applications to incrementally transition to
-OAuth 2, the Client Credentials grant is excellent for embedded services and
-backend applications.
+Grant types are what make OAuth 2 so flexible. The :doc:`Authorization
+Code grant </oauth2/grants/authcode>` is the default for almost all
+Web Applications, the :doc:`Implicit grant </oauth2/grants/implicit>`
+serves less secure applications such as Mobile Applications or
+Single-Page Applications, the :doc:`Client Credentials grant
+</oauth2/grants/credentials>` is excellent for embedded services and
+backend applications. We have also the :doc:`Resource Owner Password
+Credentials grant </oauth2/grants/password>` when there is a high
+degree of trust between the resource owner and the client, and when
+other authorization grant types are not available. This is also often
+used for legacy applications to incrementally transition to OAuth 2.
The main purpose of the grant types is to authorize access to protected
resources in various ways with different security credentials.
Naturally, OAuth 2 allows for extension grant types to be defined and OAuthLib
-attempts to cater for easy inclusion of this as much as possible.
+attempts to cater for easy inclusion of this as much as possible. See
+:doc:`Custom Grant Type </oauth2/grants/custom_grant>`.
-OAuthlib also offers hooks for registering your own custom validations for use
+OAuthlib also offers hooks for registering your own :doc:`Custom
+Validators </oauth2/grants/custom_validators>` for use
with the existing grant type handlers
(:py:class:`oauthlib.oauth2.rfc6749.grant_types.base.ValidatorsContainer`).
In some situations, this may be more convenient than subclassing or writing
@@ -36,6 +45,7 @@ client to request new tokens for as long as you as provider allow them too. In
general, OAuth 2 tokens should expire quickly and rather than annoying the user
by require them to go through the authorization redirect loop you may use the
refresh token to get a new access token. Refresh tokens, contrary to what their
-name suggest, are components of a grant type rather than token types (like
+name suggest, are components of a grant type (see :doc:`Refresh Token
+grant </oauth2/grants/refresh>`) rather than token types (like
Bearer tokens), much like the authorization code in the authorization code
grant.
diff --git a/docs/oauth2/grants/refresh.rst b/docs/oauth2/grants/refresh.rst
new file mode 100644
index 0000000..df925ff
--- /dev/null
+++ b/docs/oauth2/grants/refresh.rst
@@ -0,0 +1,6 @@
+Refresh Token Grant
+------------------------
+
+.. autoclass:: oauthlib.oauth2.RefreshTokenGrant
+ :members:
+ :inherited-members:
diff --git a/docs/oauth2/oidc.rst b/docs/oauth2/oidc.rst
index d062386..a3810a6 100644
--- a/docs/oauth2/oidc.rst
+++ b/docs/oauth2/oidc.rst
@@ -1,16 +1,21 @@
OpenID Connect
==============
-OpenID Connect represents a substantial set of behaviors and interactions built on the foundations of OAuth2. OAuthLib supports
-OpenID Connect `Authentication flows`_ when the initial grant type request's ``scope`` parameter contains ``openid``. Clients wishing
-to provide this support must implement several new features within their ``RequestValidator`` subclass.
+OpenID Connect represents a substantial set of behaviors and
+interactions built on the foundations of OAuth2. OAuthLib supports
+OpenID Connect `Authentication flows`_ when the initial grant type
+request's ``scope`` parameter contains ``openid``. Providers wishing
+to provide this support must implement a couple of new features within
+their ``RequestValidator`` subclass.
+
+A new userinfo endpoint can also be implemented to fulfill the core of OIDC.
.. _`Authentication flows`: http://openid.net/specs/openid-connect-core-1_0.html#Authentication
.. toctree::
:maxdepth: 2
- oidc/id_tokens
oidc/validator
-
-
+ oidc/endpoints
+ oidc/grants
+ oidc/id_tokens
diff --git a/docs/oauth2/oidc/authcode.rst b/docs/oauth2/oidc/authcode.rst
new file mode 100644
index 0000000..11c4a62
--- /dev/null
+++ b/docs/oauth2/oidc/authcode.rst
@@ -0,0 +1,6 @@
+OpenID Authorization Code
+-------------------------
+
+.. autoclass:: oauthlib.openid.connect.core.grant_types.AuthorizationCodeGrant
+ :members:
+ :inherited-members:
diff --git a/docs/oauth2/oidc/dispatchers.rst b/docs/oauth2/oidc/dispatchers.rst
new file mode 100644
index 0000000..f4d395e
--- /dev/null
+++ b/docs/oauth2/oidc/dispatchers.rst
@@ -0,0 +1,24 @@
+Dispatchers
+-----------
+
+.. contents::
+ :depth: 2
+
+Authorization Request
+^^^^^^^^^^^^^^^^^^^^^
+
+.. autoclass:: oauthlib.openid.connect.core.grant_types.ImplicitTokenGrantDispatcher
+ :members:
+ :inherited-members:
+
+
+.. autoclass:: oauthlib.openid.connect.core.grant_types.AuthorizationCodeGrantDispatcher
+ :members:
+ :inherited-members:
+
+Token Request
+^^^^^^^^^^^^^
+
+.. autoclass:: oauthlib.openid.connect.core.grant_types.AuthorizationTokenGrantDispatcher
+ :members:
+ :inherited-members:
diff --git a/docs/oauth2/oidc/endpoints.rst b/docs/oauth2/oidc/endpoints.rst
new file mode 100644
index 0000000..51cd1e9
--- /dev/null
+++ b/docs/oauth2/oidc/endpoints.rst
@@ -0,0 +1,21 @@
+OpenID Provider Endpoints
+=========================
+
+Endpoints in OpenID Connect Core adds a new UserInfo Endpoint. All
+existing OAuth2.0 endpoints are common to both protocols.
+
+.. toctree::
+ :maxdepth: 2
+
+ userinfo
+
+See also the related endpoints from OAuth2.0:
+
+.. hlist::
+ :columns: 1
+
+ * :doc:`Authorization endpoint </oauth2/endpoints/authorization>`
+ * :doc:`Introspect endpoint </oauth2/endpoints/introspect>`
+ * :doc:`Token endpoint </oauth2/endpoints/token>`
+ * :doc:`Revocation endpoint </oauth2/endpoints/revocation>`
+ * :doc:`Resource endpoint </oauth2/endpoints/resource>`
diff --git a/docs/oauth2/oidc/grants.rst b/docs/oauth2/oidc/grants.rst
new file mode 100644
index 0000000..aa1f70f
--- /dev/null
+++ b/docs/oauth2/oidc/grants.rst
@@ -0,0 +1,41 @@
+===========
+Grant types
+===========
+
+The OpenID Connect specification adds a new `Hybrid` flow and adds
+variants to the existing `Authorization Code` and `Implicit`
+flows. They share the same principle: having `openid` in the scope and
+a combination of new `response_type` values.
+
+
+.. list-table:: OpenID Connect "response_type" Values
+ :widths: 50 50
+ :header-rows: 1
+
+ * - "response_type" value
+ - Flow
+ * - `code`
+ - Authorization Code Flow
+ * - `id_token`
+ - Implicit Flow
+ * - `id_token token`
+ - Implicit Flow
+ * - `code id_token`
+ - Hybrid Flow
+ * - `code token`
+ - Hybrid Flow
+ * - `code id_token token`
+ - Hybrid Flow
+
+
+Special Dispatcher classes have been made to dynamically route the HTTP
+requests to either an OAuth2.0 flow or an OIDC flow. It basically
+checks the presence of `openid` scope in the parameters.
+
+.. toctree::
+ :maxdepth: 2
+
+ dispatchers
+ authcode
+ implicit
+ hybrid
diff --git a/docs/oauth2/oidc/hybrid.rst b/docs/oauth2/oidc/hybrid.rst
new file mode 100644
index 0000000..6a6c2e7
--- /dev/null
+++ b/docs/oauth2/oidc/hybrid.rst
@@ -0,0 +1,6 @@
+OpenID Hybrid
+-------------
+
+.. autoclass:: oauthlib.openid.connect.core.grant_types.HybridGrant
+ :members:
+ :inherited-members:
diff --git a/docs/oauth2/oidc/implicit.rst b/docs/oauth2/oidc/implicit.rst
new file mode 100644
index 0000000..08cef20
--- /dev/null
+++ b/docs/oauth2/oidc/implicit.rst
@@ -0,0 +1,6 @@
+OpenID Implicit
+---------------
+
+.. autoclass:: oauthlib.openid.connect.core.grant_types.ImplicitGrant
+ :members:
+ :inherited-members:
diff --git a/docs/oauth2/oidc/userinfo.rst b/docs/oauth2/oidc/userinfo.rst
new file mode 100644
index 0000000..7ba4fbf
--- /dev/null
+++ b/docs/oauth2/oidc/userinfo.rst
@@ -0,0 +1,7 @@
+========================
+OpenID UserInfo endpoint
+========================
+
+
+.. autoclass:: oauthlib.openid.connect.core.endpoints.userinfo.UserInfoEndpoint
+ :members:
diff --git a/docs/oauth2/oidc/validator.rst b/docs/oauth2/oidc/validator.rst
index 17f5825..a04e12e 100644
--- a/docs/oauth2/oidc/validator.rst
+++ b/docs/oauth2/oidc/validator.rst
@@ -1,7 +1,16 @@
-OpenID Connect
-=========================================
+Creating a Provider
+=============================================
-Migrate your OAuth2.0 server into an OIDC provider
+.. contents::
+ :depth: 2
+
+1. Create an OIDC provider
+-----------------------
+If you don't have an OAuth2.0 Provider, you can follow the instructions at
+:doc:`OAuth2.0 Creating a Provider </oauth2/server>`. Then, follow the
+migration step below.
+
+2. Migrate your OAuth2.0 provider into an OIDC provider
----------------------------------------------------
If you have a OAuth2.0 provider running and want to upgrade to OIDC, you can
@@ -19,13 +28,21 @@ Into
from oauthlib.openid import Server
from oauthlib.openid import RequestValidator
-Then, you have to implement the new RequestValidator methods as shown below.
-Note that a new UserInfo endpoint is defined and need a new controller into your webserver.
+Then, you have to implement the new `RequestValidator` methods as
+shown below. Note also that a new :doc:`UserInfo endpoint </oauth2/oidc/userinfo>` can be defined
+and needs a new controller into your webserver.
-RequestValidator Extension
-----------------------------------------------------
+3. Extend RequestValidator
+--------------------------
-A couple of methods must be implemented in your validator subclass if you wish to support OpenID Connect:
+A couple of methods must be implemented in your validator subclass if
+you wish to support OpenID Connect:
.. autoclass:: oauthlib.openid.RequestValidator
:members:
+
+4. Preconfigured all-in-one servers
+-----------------------------------
+
+.. autoclass:: oauthlib.openid.connect.core.endpoints.pre_configured.Server
+ :members:
diff --git a/docs/oauth2/server.rst b/docs/oauth2/server.rst
index d9846c5..15420f3 100644
--- a/docs/oauth2/server.rst
+++ b/docs/oauth2/server.rst
@@ -239,6 +239,17 @@ the token.
# the scopes into a string.
scopes = django.db.models.TextField()
+**Redirect URI**:
+
+ If the client specifies a redirect_uri when obtaining code then that
+ redirect URI must be bound to the code and verified equal in this
+ method, according to RFC 6749 section 4.1. This field holds that
+ bound value.
+
+ .. code-block:: python
+
+ redirect_uri = django.db.models.TextField()
+
**Authorization Code**:
An unguessable unique string of characters.
diff --git a/examples/skeleton_oauth2_web_application_server.py b/examples/skeleton_oauth2_web_application_server.py
index 9a30373..91859fc 100644
--- a/examples/skeleton_oauth2_web_application_server.py
+++ b/examples/skeleton_oauth2_web_application_server.py
@@ -54,13 +54,18 @@ class SkeletonValidator(RequestValidator):
# Token request
+ def client_authentication_required(self, request, *args, **kwargs):
+ # Check if the client provided authentication information that needs to
+ # be validated, e.g. HTTP Basic auth
+ pass
+
def authenticate_client(self, request, *args, **kwargs):
# Whichever authentication method suits you, HTTP Basic might work
pass
def authenticate_client_id(self, client_id, request, *args, **kwargs):
- # Don't allow public (non-authenticated) clients
- return False
+ # The client_id must match an existing public (non-confidential) client
+ pass
def validate_code(self, client_id, code, client, request, *args, **kwargs):
# Validate the code belongs to the client. Add associated scopes
diff --git a/oauthlib/oauth2/rfc6749/clients/base.py b/oauthlib/oauth2/rfc6749/clients/base.py
index 04dabe6..4043258 100644
--- a/oauthlib/oauth2/rfc6749/clients/base.py
+++ b/oauthlib/oauth2/rfc6749/clients/base.py
@@ -220,7 +220,10 @@ class Client:
the provider. If provided then it must also be provided in the
token request.
- :param scope:
+ :param scope: List of scopes to request. Must be equal to
+ or a subset of the scopes granted when obtaining the refresh
+ token. If none is provided, the ones provided in the constructor are
+ used.
:param kwargs: Additional parameters to included in the request.
@@ -231,10 +234,11 @@ class Client:
self.state = state or self.state_generator()
self.redirect_url = redirect_url or self.redirect_url
- self.scope = scope or self.scope
+ # do not assign scope to self automatically anymore
+ scope = self.scope if scope is None else scope
auth_url = self.prepare_request_uri(
authorization_url, redirect_uri=self.redirect_url,
- scope=self.scope, state=self.state, **kwargs)
+ scope=scope, state=self.state, **kwargs)
return auth_url, FORM_ENC_HEADERS, ''
def prepare_token_request(self, token_url, authorization_response=None,
@@ -295,7 +299,8 @@ class Client:
:param scope: List of scopes to request. Must be equal to
or a subset of the scopes granted when obtaining the refresh
- token.
+ token. If none is provided, the ones provided in the constructor are
+ used.
:param kwargs: Additional parameters to included in the request.
@@ -304,9 +309,10 @@ class Client:
if not is_secure_transport(token_url):
raise InsecureTransportError()
- self.scope = scope or self.scope
+ # do not assign scope to self automatically anymore
+ scope = self.scope if scope is None else scope
body = self.prepare_refresh_body(body=body,
- refresh_token=refresh_token, scope=self.scope, **kwargs)
+ refresh_token=refresh_token, scope=scope, **kwargs)
return token_url, FORM_ENC_HEADERS, body
def prepare_token_revocation_request(self, revocation_url, token,
@@ -380,7 +386,8 @@ class Client:
returns an error response as described in `Section 5.2`_.
:param body: The response body from the token request.
- :param scope: Scopes originally requested.
+ :param scope: Scopes originally requested. If none is provided, the ones
+ provided in the constructor are used.
:return: Dictionary of token parameters.
:raises: Warning if scope has changed. OAuth2Error if response is invalid.
@@ -416,6 +423,7 @@ class Client:
.. _`Section 5.2`: https://tools.ietf.org/html/rfc6749#section-5.2
.. _`Section 7.1`: https://tools.ietf.org/html/rfc6749#section-7.1
"""
+ scope = self.scope if scope is None else scope
self.token = parse_token_response(body, scope=scope)
self.populate_token_attributes(self.token)
return self.token
@@ -437,9 +445,11 @@ class Client:
Section 3.3. The requested scope MUST NOT include any scope
not originally granted by the resource owner, and if omitted is
treated as equal to the scope originally granted by the
- resource owner.
+ resource owner. Note that if none is provided, the ones provided
+ in the constructor are used if any.
"""
refresh_token = refresh_token or self.refresh_token
+ scope = self.scope if scope is None else scope
return prepare_token_request(self.refresh_token_key, body=body, scope=scope,
refresh_token=refresh_token, **kwargs)
diff --git a/oauthlib/oauth2/rfc6749/clients/legacy_application.py b/oauthlib/oauth2/rfc6749/clients/legacy_application.py
index 1bb0e14..fe2ff4a 100644
--- a/oauthlib/oauth2/rfc6749/clients/legacy_application.py
+++ b/oauthlib/oauth2/rfc6749/clients/legacy_application.py
@@ -79,5 +79,6 @@ class LegacyApplicationClient(Client):
"""
kwargs['client_id'] = self.client_id
kwargs['include_client_id'] = include_client_id
+ scope = self.scope if scope is None else scope
return prepare_token_request(self.grant_type, body=body, username=username,
password=password, scope=scope, **kwargs)
diff --git a/oauthlib/oauth2/rfc6749/clients/mobile_application.py b/oauthlib/oauth2/rfc6749/clients/mobile_application.py
index 73627c4..cd325f4 100644
--- a/oauthlib/oauth2/rfc6749/clients/mobile_application.py
+++ b/oauthlib/oauth2/rfc6749/clients/mobile_application.py
@@ -91,6 +91,7 @@ class MobileApplicationClient(Client):
.. _`Section 3.3`: https://tools.ietf.org/html/rfc6749#section-3.3
.. _`Section 10.12`: https://tools.ietf.org/html/rfc6749#section-10.12
"""
+ scope = self.scope if scope is None else scope
return prepare_grant_uri(uri, self.client_id, self.response_type,
redirect_uri=redirect_uri, state=state, scope=scope, **kwargs)
@@ -167,6 +168,7 @@ class MobileApplicationClient(Client):
.. _`Section 7.1`: https://tools.ietf.org/html/rfc6749#section-7.1
.. _`Section 3.3`: https://tools.ietf.org/html/rfc6749#section-3.3
"""
+ scope = self.scope if scope is None else scope
self.token = parse_implicit_response(uri, state=state, scope=scope)
self.populate_token_attributes(self.token)
return self.token
diff --git a/oauthlib/oauth2/rfc6749/clients/service_application.py b/oauthlib/oauth2/rfc6749/clients/service_application.py
index 09fc7ba..34c2a66 100644
--- a/oauthlib/oauth2/rfc6749/clients/service_application.py
+++ b/oauthlib/oauth2/rfc6749/clients/service_application.py
@@ -181,6 +181,7 @@ class ServiceApplicationClient(Client):
kwargs['client_id'] = self.client_id
kwargs['include_client_id'] = include_client_id
+ scope = self.scope if scope is None else scope
return prepare_token_request(self.grant_type,
body=body,
assertion=assertion,
diff --git a/oauthlib/oauth2/rfc6749/clients/web_application.py b/oauthlib/oauth2/rfc6749/clients/web_application.py
index aedc9d1..42b2c96 100644
--- a/oauthlib/oauth2/rfc6749/clients/web_application.py
+++ b/oauthlib/oauth2/rfc6749/clients/web_application.py
@@ -84,6 +84,7 @@ class WebApplicationClient(Client):
.. _`Section 3.3`: https://tools.ietf.org/html/rfc6749#section-3.3
.. _`Section 10.12`: https://tools.ietf.org/html/rfc6749#section-10.12
"""
+ scope = self.scope if scope is None else scope
return prepare_grant_uri(uri, self.client_id, 'code',
redirect_uri=redirect_uri, scope=scope, state=state, **kwargs)
diff --git a/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py b/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py
index fdb0bf6..05f13af 100644
--- a/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py
+++ b/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py
@@ -117,8 +117,8 @@ class ClientCredentialsGrant(GrantTypeBase):
# 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
+ log.debug('Authorizing access to client %r.', request.client_id)
self.validate_scopes(request)
for validator in self.custom_validators.post_token:
diff --git a/oauthlib/openid/connect/core/grant_types/dispatchers.py b/oauthlib/openid/connect/core/grant_types/dispatchers.py
index 541467a..6dcc0cb 100644
--- a/oauthlib/openid/connect/core/grant_types/dispatchers.py
+++ b/oauthlib/openid/connect/core/grant_types/dispatchers.py
@@ -9,8 +9,10 @@ class Dispatcher:
class AuthorizationCodeGrantDispatcher(Dispatcher):
"""
- This is an adapter class that will route simple Authorization Code requests, those that have response_type=code and a scope
- including 'openid' to either the default_grant or the oidc_grant based on the scopes requested.
+ This is an adapter class that will route simple Authorization Code
+ requests, those that have `response_type=code` and a scope including
+ `openid` to either the `default_grant` or the `oidc_grant` based on
+ the scopes requested.
"""
def __init__(self, default_grant=None, oidc_grant=None):
self.default_grant = default_grant
@@ -26,16 +28,20 @@ class AuthorizationCodeGrantDispatcher(Dispatcher):
return handler
def create_authorization_response(self, request, token_handler):
+ """Read scope and route to the designated handler."""
return self._handler_for_request(request).create_authorization_response(request, token_handler)
def validate_authorization_request(self, request):
+ """Read scope and route to the designated handler."""
return self._handler_for_request(request).validate_authorization_request(request)
class ImplicitTokenGrantDispatcher(Dispatcher):
"""
- This is an adapter class that will route simple Authorization Code requests, those that have response_type=code and a scope
- including 'openid' to either the default_grant or the oidc_grant based on the scopes requested.
+ This is an adapter class that will route simple Authorization
+ requests, those that have `id_token` in `response_type` and a scope
+ including `openid` to either the `default_grant` or the `oidc_grant`
+ based on the scopes requested.
"""
def __init__(self, default_grant=None, oidc_grant=None):
self.default_grant = default_grant
@@ -51,9 +57,11 @@ class ImplicitTokenGrantDispatcher(Dispatcher):
return handler
def create_authorization_response(self, request, token_handler):
+ """Read scope and route to the designated handler."""
return self._handler_for_request(request).create_authorization_response(request, token_handler)
def validate_authorization_request(self, request):
+ """Read scope and route to the designated handler."""
return self._handler_for_request(request).validate_authorization_request(request)
@@ -75,7 +83,7 @@ class AuthorizationTokenGrantDispatcher(Dispatcher):
code = parameters.get('code', None)
redirect_uri = parameters.get('redirect_uri', None)
- # If code is not pressent fallback to `default_grant` wich will
+ # If code is not pressent fallback to `default_grant` which will
# raise an error for the missing `code` in `create_token_response` step.
if code:
scopes = self.request_validator.get_authorization_code_scopes(client_id, code, redirect_uri, request)
@@ -87,5 +95,6 @@ class AuthorizationTokenGrantDispatcher(Dispatcher):
return handler
def create_token_response(self, request, token_handler):
+ """Read scope and route to the designated handler."""
handler = self._handler_for_request(request)
return handler.create_token_response(request, token_handler)
diff --git a/requirements-test.txt b/requirements-test.txt
index 64485a6..6d8d6e9 100644
--- a/requirements-test.txt
+++ b/requirements-test.txt
@@ -1,4 +1,3 @@
-r requirements.txt
-mock>=2.0
pytest>=4.0
pytest-cov>=2.6
diff --git a/tests/oauth1/rfc5849/endpoints/test_access_token.py b/tests/oauth1/rfc5849/endpoints/test_access_token.py
index 9ba8a3e..05d62fc 100644
--- a/tests/oauth1/rfc5849/endpoints/test_access_token.py
+++ b/tests/oauth1/rfc5849/endpoints/test_access_token.py
@@ -1,4 +1,4 @@
-from mock import ANY, MagicMock
+from unittest.mock import ANY, MagicMock
from oauthlib.oauth1 import RequestValidator
from oauthlib.oauth1.rfc5849 import Client
diff --git a/tests/oauth1/rfc5849/endpoints/test_authorization.py b/tests/oauth1/rfc5849/endpoints/test_authorization.py
index 178bddf..a9b2fc0 100644
--- a/tests/oauth1/rfc5849/endpoints/test_authorization.py
+++ b/tests/oauth1/rfc5849/endpoints/test_authorization.py
@@ -1,4 +1,4 @@
-from mock import MagicMock
+from unittest.mock import MagicMock
from oauthlib.oauth1 import RequestValidator
from oauthlib.oauth1.rfc5849 import errors
diff --git a/tests/oauth1/rfc5849/endpoints/test_base.py b/tests/oauth1/rfc5849/endpoints/test_base.py
index de6c1a4..6fc991a 100644
--- a/tests/oauth1/rfc5849/endpoints/test_base.py
+++ b/tests/oauth1/rfc5849/endpoints/test_base.py
@@ -1,6 +1,6 @@
from re import sub
-from mock import MagicMock
+from unittest.mock import MagicMock
from oauthlib.common import CaseInsensitiveDict, safe_string_equals
from oauthlib.oauth1 import Client, RequestValidator
diff --git a/tests/oauth1/rfc5849/endpoints/test_request_token.py b/tests/oauth1/rfc5849/endpoints/test_request_token.py
index ece36bd..e16ea7b 100644
--- a/tests/oauth1/rfc5849/endpoints/test_request_token.py
+++ b/tests/oauth1/rfc5849/endpoints/test_request_token.py
@@ -1,4 +1,4 @@
-from mock import ANY, MagicMock
+from unittest.mock import ANY, MagicMock
from oauthlib.oauth1 import RequestValidator
from oauthlib.oauth1.rfc5849 import Client
diff --git a/tests/oauth1/rfc5849/endpoints/test_resource.py b/tests/oauth1/rfc5849/endpoints/test_resource.py
index 41c9aee..2aeb1c8 100644
--- a/tests/oauth1/rfc5849/endpoints/test_resource.py
+++ b/tests/oauth1/rfc5849/endpoints/test_resource.py
@@ -1,4 +1,4 @@
-from mock import ANY, MagicMock
+from unittest.mock import ANY, MagicMock
from oauthlib.oauth1 import RequestValidator
from oauthlib.oauth1.rfc5849 import Client
diff --git a/tests/oauth1/rfc5849/endpoints/test_signature_only.py b/tests/oauth1/rfc5849/endpoints/test_signature_only.py
index 9804137..2ff1073 100644
--- a/tests/oauth1/rfc5849/endpoints/test_signature_only.py
+++ b/tests/oauth1/rfc5849/endpoints/test_signature_only.py
@@ -1,4 +1,4 @@
-from mock import ANY, MagicMock
+from unittest.mock import ANY, MagicMock
from oauthlib.oauth1 import RequestValidator
from oauthlib.oauth1.rfc5849 import Client
diff --git a/tests/oauth2/rfc6749/clients/test_backend_application.py b/tests/oauth2/rfc6749/clients/test_backend_application.py
index 8d80b39..b05786a 100644
--- a/tests/oauth2/rfc6749/clients/test_backend_application.py
+++ b/tests/oauth2/rfc6749/clients/test_backend_application.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import os
-from mock import patch
+from unittest.mock import patch
from oauthlib import signals
from oauthlib.oauth2 import BackendApplicationClient
diff --git a/tests/oauth2/rfc6749/clients/test_legacy_application.py b/tests/oauth2/rfc6749/clients/test_legacy_application.py
index 34ea108..1daf2a3 100644
--- a/tests/oauth2/rfc6749/clients/test_legacy_application.py
+++ b/tests/oauth2/rfc6749/clients/test_legacy_application.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import os
-from mock import patch
+from unittest.mock import patch
from oauthlib import signals
from oauthlib.oauth2 import LegacyApplicationClient
diff --git a/tests/oauth2/rfc6749/clients/test_mobile_application.py b/tests/oauth2/rfc6749/clients/test_mobile_application.py
index e2bdebe..2fb839e 100644
--- a/tests/oauth2/rfc6749/clients/test_mobile_application.py
+++ b/tests/oauth2/rfc6749/clients/test_mobile_application.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import os
-from mock import patch
+from unittest.mock import patch
from oauthlib import signals
from oauthlib.oauth2 import MobileApplicationClient
diff --git a/tests/oauth2/rfc6749/clients/test_service_application.py b/tests/oauth2/rfc6749/clients/test_service_application.py
index ba9406b..6f48e23 100644
--- a/tests/oauth2/rfc6749/clients/test_service_application.py
+++ b/tests/oauth2/rfc6749/clients/test_service_application.py
@@ -3,7 +3,7 @@ import os
from time import time
import jwt
-from mock import patch
+from unittest.mock import patch
from oauthlib.common import Request
from oauthlib.oauth2 import ServiceApplicationClient
diff --git a/tests/oauth2/rfc6749/clients/test_web_application.py b/tests/oauth2/rfc6749/clients/test_web_application.py
index e3382c8..719a07d 100644
--- a/tests/oauth2/rfc6749/clients/test_web_application.py
+++ b/tests/oauth2/rfc6749/clients/test_web_application.py
@@ -2,7 +2,7 @@
import os
import warnings
-from mock import patch
+from unittest.mock import patch
from oauthlib import common, signals
from oauthlib.oauth2 import (BackendApplicationClient, Client,
diff --git a/tests/oauth2/rfc6749/endpoints/test_client_authentication.py b/tests/oauth2/rfc6749/endpoints/test_client_authentication.py
index 48b5485..69cb7ee 100644
--- a/tests/oauth2/rfc6749/endpoints/test_client_authentication.py
+++ b/tests/oauth2/rfc6749/endpoints/test_client_authentication.py
@@ -11,7 +11,7 @@ prevents this check from being circumvented with a client form parameter.
"""
import json
-import mock
+from unittest import mock
from oauthlib.oauth2 import (BackendApplicationServer, LegacyApplicationServer,
MobileApplicationServer, RequestValidator,
diff --git a/tests/oauth2/rfc6749/endpoints/test_credentials_preservation.py b/tests/oauth2/rfc6749/endpoints/test_credentials_preservation.py
index bda71f7..9a76da9 100644
--- a/tests/oauth2/rfc6749/endpoints/test_credentials_preservation.py
+++ b/tests/oauth2/rfc6749/endpoints/test_credentials_preservation.py
@@ -5,7 +5,7 @@ uri and the Implicit Grant will need to preserve state.
"""
import json
-import mock
+from unittest import mock
from oauthlib.oauth2 import (MobileApplicationServer, RequestValidator,
WebApplicationServer)
diff --git a/tests/oauth2/rfc6749/endpoints/test_error_responses.py b/tests/oauth2/rfc6749/endpoints/test_error_responses.py
index cdf2b63..aac66df 100644
--- a/tests/oauth2/rfc6749/endpoints/test_error_responses.py
+++ b/tests/oauth2/rfc6749/endpoints/test_error_responses.py
@@ -2,7 +2,7 @@
"""
import json
-import mock
+from unittest import mock
from oauthlib.common import urlencode
from oauthlib.oauth2 import (BackendApplicationServer, LegacyApplicationServer,
diff --git a/tests/oauth2/rfc6749/endpoints/test_extra_credentials.py b/tests/oauth2/rfc6749/endpoints/test_extra_credentials.py
index 6895dcd..936a129 100644
--- a/tests/oauth2/rfc6749/endpoints/test_extra_credentials.py
+++ b/tests/oauth2/rfc6749/endpoints/test_extra_credentials.py
@@ -1,6 +1,6 @@
"""Ensure extra credentials can be supplied for inclusion in tokens.
"""
-import mock
+from unittest import mock
from oauthlib.oauth2 import (BackendApplicationServer, LegacyApplicationServer,
MobileApplicationServer, RequestValidator,
diff --git a/tests/oauth2/rfc6749/endpoints/test_introspect_endpoint.py b/tests/oauth2/rfc6749/endpoints/test_introspect_endpoint.py
index 0942d96..3c67673 100644
--- a/tests/oauth2/rfc6749/endpoints/test_introspect_endpoint.py
+++ b/tests/oauth2/rfc6749/endpoints/test_introspect_endpoint.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from json import loads
-from mock import MagicMock
+from unittest.mock import MagicMock
from oauthlib.common import urlencode
from oauthlib.oauth2 import RequestValidator, IntrospectEndpoint
diff --git a/tests/oauth2/rfc6749/endpoints/test_resource_owner_association.py b/tests/oauth2/rfc6749/endpoints/test_resource_owner_association.py
index 9e9d836..6280cac 100644
--- a/tests/oauth2/rfc6749/endpoints/test_resource_owner_association.py
+++ b/tests/oauth2/rfc6749/endpoints/test_resource_owner_association.py
@@ -2,7 +2,7 @@
"""
import json
-import mock
+from unittest import mock
from oauthlib.oauth2 import (BackendApplicationServer, LegacyApplicationServer,
MobileApplicationServer, RequestValidator,
diff --git a/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py b/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py
index 0e3b2e1..6bfba9a 100644
--- a/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py
+++ b/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from json import loads
-from mock import MagicMock
+from unittest.mock import MagicMock
from oauthlib.common import urlencode
from oauthlib.oauth2 import RequestValidator, RevocationEndpoint
diff --git a/tests/oauth2/rfc6749/endpoints/test_scope_handling.py b/tests/oauth2/rfc6749/endpoints/test_scope_handling.py
index 65e0e3c..0bf760b 100644
--- a/tests/oauth2/rfc6749/endpoints/test_scope_handling.py
+++ b/tests/oauth2/rfc6749/endpoints/test_scope_handling.py
@@ -5,7 +5,7 @@ need to be persisted temporarily in an authorization code.
"""
import json
-import mock
+from unittest import mock
from oauthlib.oauth2 import (BackendApplicationServer, LegacyApplicationServer,
MobileApplicationServer, RequestValidator, Server,
diff --git a/tests/oauth2/rfc6749/grant_types/test_authorization_code.py b/tests/oauth2/rfc6749/grant_types/test_authorization_code.py
index 4ed9086..a9e384f 100644
--- a/tests/oauth2/rfc6749/grant_types/test_authorization_code.py
+++ b/tests/oauth2/rfc6749/grant_types/test_authorization_code.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import json
-import mock
+from unittest import mock
from oauthlib.common import Request
from oauthlib.oauth2.rfc6749 import errors
diff --git a/tests/oauth2/rfc6749/grant_types/test_client_credentials.py b/tests/oauth2/rfc6749/grant_types/test_client_credentials.py
index d994278..0a45ef6 100644
--- a/tests/oauth2/rfc6749/grant_types/test_client_credentials.py
+++ b/tests/oauth2/rfc6749/grant_types/test_client_credentials.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import json
-import mock
+from unittest import mock
from oauthlib.common import Request
from oauthlib.oauth2.rfc6749.grant_types import ClientCredentialsGrant
diff --git a/tests/oauth2/rfc6749/grant_types/test_implicit.py b/tests/oauth2/rfc6749/grant_types/test_implicit.py
index ffd766a..4a0313d 100644
--- a/tests/oauth2/rfc6749/grant_types/test_implicit.py
+++ b/tests/oauth2/rfc6749/grant_types/test_implicit.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-import mock
+from unittest import mock
from oauthlib.common import Request
from oauthlib.oauth2.rfc6749.grant_types import ImplicitGrant
diff --git a/tests/oauth2/rfc6749/grant_types/test_refresh_token.py b/tests/oauth2/rfc6749/grant_types/test_refresh_token.py
index 074f359..0d0fd37 100644
--- a/tests/oauth2/rfc6749/grant_types/test_refresh_token.py
+++ b/tests/oauth2/rfc6749/grant_types/test_refresh_token.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import json
-import mock
+from unittest import mock
from oauthlib.common import Request
from oauthlib.oauth2.rfc6749 import errors
diff --git a/tests/oauth2/rfc6749/grant_types/test_resource_owner_password.py b/tests/oauth2/rfc6749/grant_types/test_resource_owner_password.py
index 4e93015..42f0aa6 100644
--- a/tests/oauth2/rfc6749/grant_types/test_resource_owner_password.py
+++ b/tests/oauth2/rfc6749/grant_types/test_resource_owner_password.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import json
-import mock
+from unittest import mock
from oauthlib.common import Request
from oauthlib.oauth2.rfc6749 import errors
diff --git a/tests/oauth2/rfc6749/test_parameters.py b/tests/oauth2/rfc6749/test_parameters.py
index e9b3621..4380447 100644
--- a/tests/oauth2/rfc6749/test_parameters.py
+++ b/tests/oauth2/rfc6749/test_parameters.py
@@ -1,4 +1,4 @@
-from mock import patch
+from unittest.mock import patch
from oauthlib import signals
from oauthlib.oauth2.rfc6749.errors import *
diff --git a/tests/oauth2/rfc6749/test_server.py b/tests/oauth2/rfc6749/test_server.py
index 9288e49..e6ad5cd 100644
--- a/tests/oauth2/rfc6749/test_server.py
+++ b/tests/oauth2/rfc6749/test_server.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import json
-import mock
+from unittest import mock
from oauthlib import common
from oauthlib.oauth2.rfc6749 import errors, tokens
diff --git a/tests/oauth2/rfc6749/test_tokens.py b/tests/oauth2/rfc6749/test_tokens.py
index 61a23cb..8402133 100644
--- a/tests/oauth2/rfc6749/test_tokens.py
+++ b/tests/oauth2/rfc6749/test_tokens.py
@@ -1,4 +1,4 @@
-import mock
+from unittest import mock
from oauthlib.common import Request
from oauthlib.oauth2.rfc6749.tokens import (
diff --git a/tests/openid/connect/core/endpoints/test_claims_handling.py b/tests/openid/connect/core/endpoints/test_claims_handling.py
index 943210c..1fe86ef 100644
--- a/tests/openid/connect/core/endpoints/test_claims_handling.py
+++ b/tests/openid/connect/core/endpoints/test_claims_handling.py
@@ -6,7 +6,7 @@ The claims parameter is an optional query param for the Authorization Request en
request the claims should be transferred (via the oauthlib request) to be persisted
with the Access Token when it is created.
"""
-import mock
+from unittest import mock
from oauthlib.openid import RequestValidator
from oauthlib.openid.connect.core.endpoints.pre_configured import Server
diff --git a/tests/openid/connect/core/endpoints/test_openid_connect_params_handling.py b/tests/openid/connect/core/endpoints/test_openid_connect_params_handling.py
index 26ff46b..98482e2 100644
--- a/tests/openid/connect/core/endpoints/test_openid_connect_params_handling.py
+++ b/tests/openid/connect/core/endpoints/test_openid_connect_params_handling.py
@@ -1,4 +1,4 @@
-import mock
+from unittest import mock
from oauthlib.oauth2 import InvalidRequestError
from oauthlib.oauth2.rfc6749.endpoints.authorization import \
diff --git a/tests/openid/connect/core/endpoints/test_userinfo_endpoint.py b/tests/openid/connect/core/endpoints/test_userinfo_endpoint.py
index 9edc970..dd48bdd 100644
--- a/tests/openid/connect/core/endpoints/test_userinfo_endpoint.py
+++ b/tests/openid/connect/core/endpoints/test_userinfo_endpoint.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-import mock
+from unittest import mock
import json
from oauthlib.openid import RequestValidator
diff --git a/tests/openid/connect/core/grant_types/test_authorization_code.py b/tests/openid/connect/core/grant_types/test_authorization_code.py
index b6bb99c..829af92 100644
--- a/tests/openid/connect/core/grant_types/test_authorization_code.py
+++ b/tests/openid/connect/core/grant_types/test_authorization_code.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import json
-import mock
+from unittest import mock
from oauthlib.common import Request
from oauthlib.oauth2.rfc6749.tokens import BearerToken
diff --git a/tests/openid/connect/core/grant_types/test_base.py b/tests/openid/connect/core/grant_types/test_base.py
index d506b7e..786b24b 100644
--- a/tests/openid/connect/core/grant_types/test_base.py
+++ b/tests/openid/connect/core/grant_types/test_base.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-import mock
+from unittest import mock
import time
from oauthlib.common import Request
diff --git a/tests/openid/connect/core/grant_types/test_dispatchers.py b/tests/openid/connect/core/grant_types/test_dispatchers.py
index 2fc4ae6..d423915 100644
--- a/tests/openid/connect/core/grant_types/test_dispatchers.py
+++ b/tests/openid/connect/core/grant_types/test_dispatchers.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-import mock
+from unittest import mock
from oauthlib.common import Request
diff --git a/tests/openid/connect/core/grant_types/test_hybrid.py b/tests/openid/connect/core/grant_types/test_hybrid.py
index 3347031..53175df 100644
--- a/tests/openid/connect/core/grant_types/test_hybrid.py
+++ b/tests/openid/connect/core/grant_types/test_hybrid.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-import mock
+from unittest import mock
from oauthlib.oauth2.rfc6749 import errors
from oauthlib.oauth2.rfc6749.tokens import BearerToken
diff --git a/tests/openid/connect/core/grant_types/test_implicit.py b/tests/openid/connect/core/grant_types/test_implicit.py
index c8fefd4..b914eb6 100644
--- a/tests/openid/connect/core/grant_types/test_implicit.py
+++ b/tests/openid/connect/core/grant_types/test_implicit.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-import mock
+from unittest import mock
from oauthlib.common import Request
from oauthlib.oauth2.rfc6749 import errors
diff --git a/tests/openid/connect/core/test_server.py b/tests/openid/connect/core/test_server.py
index 681748f..bb3cc3c 100644
--- a/tests/openid/connect/core/test_server.py
+++ b/tests/openid/connect/core/test_server.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import json
-import mock
+from unittest import mock
from oauthlib.oauth2.rfc6749 import errors
from oauthlib.oauth2.rfc6749.endpoints.authorization import AuthorizationEndpoint
diff --git a/tests/openid/connect/core/test_tokens.py b/tests/openid/connect/core/test_tokens.py
index f1a6688..5889df5 100644
--- a/tests/openid/connect/core/test_tokens.py
+++ b/tests/openid/connect/core/test_tokens.py
@@ -1,4 +1,4 @@
-import mock
+from unittest import mock
from oauthlib.openid.connect.core.tokens import JWTToken