Skip to content

Commit

Permalink
Merge branch 'master' into doc-oidc
Browse files Browse the repository at this point in the history
  • Loading branch information
JonathanHuot committed Jan 29, 2020
2 parents ab0de9e + 845892c commit 7f5e92a
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 30 deletions.
35 changes: 19 additions & 16 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,34 @@ Changelog

3.1.0 (TBD)
------------------

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: BackendApplication.Client.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)
------------------
Expand Down
78 changes: 78 additions & 0 deletions docs/oauth2/grants/custom_grant.rst
Original file line number Diff line number Diff line change
@@ -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`
12 changes: 11 additions & 1 deletion docs/oauth2/grants/custom_validators.rst
Original file line number Diff line number Diff line change
@@ -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:
30 changes: 20 additions & 10 deletions docs/oauth2/grants/grants.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
6 changes: 6 additions & 0 deletions docs/oauth2/grants/refresh.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Refresh Token Grant
------------------------

.. autoclass:: oauthlib.oauth2.RefreshTokenGrant
:members:
:inherited-members:
11 changes: 11 additions & 0 deletions docs/oauth2/server.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion oauthlib/oauth2/rfc6749/grant_types/client_credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ def validate_token_request(self, request):
# 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:
Expand Down
2 changes: 1 addition & 1 deletion oauthlib/openid/connect/core/grant_types/dispatchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def _handler_for_request(self, request):
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)
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ commands=
# tox -e docs to mimick readthedocs build.
# as of today, RTD is using python2.7 and doesn't run "setup.py install"
[testenv:docs]
basepython=python2.7
basepython=python3.6
skipsdist=True
deps=
sphinx
Expand Down

0 comments on commit 7f5e92a

Please sign in to comment.