Skip to content

Commit f32211e

Browse files
author
afabiani
committed
1 parent 1fe832d commit f32211e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+1610
-730
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ __pycache__
2525
pip-log.txt
2626

2727
# Unit test / coverage reports
28-
.cache
28+
.pytest_cache
2929
.coverage
3030
.tox
3131
.pytest_cache/

.travis.yml

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,18 @@
1-
# https://travis-ci.org/evonove/django-oauth-toolkit
2-
sudo: false
3-
language: python
1+
# https://travis-ci.org/jazzband/django-oauth-toolkit
2+
dist: xenial
43

5-
python: "3.6"
4+
language: python
65

7-
env:
8-
- TOXENV=py27-django111
9-
- TOXENV=py34-django111
10-
- TOXENV=py36-django111
11-
- TOXENV=py36-django20
12-
- TOXENV=py36-djangomaster
13-
- TOXENV=docs
14-
- TOXENV=flake8
6+
python:
7+
- "3.4"
158

169
cache:
1710
directories:
1811
- $HOME/.cache/pip
1912
- $TRAVIS_BUILD_DIR/.tox
2013

21-
matrix:
22-
fast_finish: true
23-
24-
allow_failures:
25-
- env: TOXENV=py36-djangomaster
26-
2714
install:
28-
- pip install coveralls tox
15+
- pip install coveralls tox tox-travis
2916

3017
script:
3118
- tox

CHANGELOG.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
1-
### 1.1.3 [2018-10-12]
1+
### 1.3.0 [unreleased]
2+
3+
* Fix a race condition in creation of AccessToken with external oauth2 server.
4+
* **Backwards-incompatible** squashed migrations:
5+
If you are currently on a release < 1.2.0, you will need to first install 1.2.x then `manage.py migrate` before
6+
upgrading to >= 1.3.0.
7+
8+
### 1.2.0 [2018-06-03]
9+
10+
* **Compatibility**: Python 3.4 is the new minimum required version.
11+
* **Compatibility**: Django 2.0 is the new minimum required version.
12+
* **New feature**: Added TokenMatchesOASRequirements Permissions.
13+
* validators.URIValidator has been updated to match URLValidator behaviour more closely.
14+
* Moved `redirect_uris` validation to the application clean() method.
215

3-
* Fix a concurrency issue with Refresh Tokens (#638)
4-
* Fix Refresh Token revocation when the Access Token does not exist (#625)
516

617
### 1.1.2 [2018-05-12]
718

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ Please report any security issues to the JazzBand security team at <security@jaz
4242
Requirements
4343
------------
4444

45-
* Python 2.7, 3.4, 3.5, 3.6
46-
* Django 1.11, 2.0
45+
* Python 3.4+
46+
* Django 2.0+
4747

4848
Installation
4949
------------

docs/advanced_topics.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ Be aware that, when you intend to swap the application model, you should create
4848
migration defining the swapped application model prior to setting OAUTH2_PROVIDER_APPLICATION_MODEL.
4949
You'll run into models.E022 in Core system checks if you don't get the order right.
5050

51+
You can force your migration providing the custom model to run in the right order by
52+
adding::
53+
54+
run_before = [
55+
('oauth2_provider', '0001_initial'),
56+
]
57+
58+
to the migration class.
59+
5160
That's all, now Django OAuth Toolkit will use your model wherever an Application instance is needed.
5261

5362
**Notice:** `OAUTH2_PROVIDER_APPLICATION_MODEL` is the only setting variable that is not namespaced, this

docs/conf.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
#
31
# Django OAuth Toolkit documentation build configuration file, created by
42
# sphinx-quickstart on Mon May 20 19:40:43 2013.
53
#
@@ -12,7 +10,6 @@
1210
# serve to show the default.
1311

1412
import os
15-
import re
1613
import sys
1714

1815
import django

docs/index.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ If you need support please send a message to the `Django OAuth Toolkit Google Gr
2121
Requirements
2222
------------
2323

24-
* Python 2.7, 3.4, 3.5, 3.6
25-
* Django 1.8, 1.9, 1.10, 1.11
24+
* Python 3.4+
25+
* Django 2.0+
2626

2727
Index
2828
=====

docs/rest-framework/getting_started.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,26 @@ Grab your access_token and start using your new OAuth2 API:
189189
# Insert a new user
190190
curl -H "Authorization: Bearer <your_access_token>" -X POST -d"username=foo&password=bar" http://localhost:8000/users/
191191

192+
Some time has passed and your access token is about to expire, you can get renew the access token issued using the `refresh token`:
193+
194+
::
195+
196+
curl -X POST -d "grant_type=refresh_token&refresh_token=<your_refresh_token>&client_id=<your_client_id>&client_secret=<your_client_secret>" http://localhost:8000/o/token/
197+
198+
Your response should be similar to your first access_token request, containing a new access_token and refresh_token:
199+
200+
.. code-block:: javascript
201+
202+
{
203+
"access_token": "<your_new_access_token>",
204+
"token_type": "Bearer",
205+
"expires_in": 36000,
206+
"refresh_token": "<your_new_refresh_token>",
207+
"scope": "read write groups"
208+
}
209+
210+
211+
192212
Step 5: Testing Restricted Access
193213
---------------------------------
194214

docs/rest-framework/openapi.yaml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
openapi: "3.0.0"
2+
info:
3+
title: songs
4+
version: v1
5+
components:
6+
securitySchemes:
7+
song_auth:
8+
type: oauth2
9+
flows:
10+
implicit:
11+
authorizationUrl: http://localhost:8000/o/authorize
12+
scopes:
13+
read: read about a song
14+
create: create a new song
15+
update: update an existing song
16+
delete: delete a song
17+
post: create a new song
18+
widget: widget scope
19+
scope2: scope too
20+
scope3: another scope
21+
paths:
22+
/songs:
23+
get:
24+
security:
25+
- song_auth: [read]
26+
responses:
27+
'200':
28+
description: A list of songs.
29+
post:
30+
security:
31+
- song_auth: [create]
32+
- song_auth: [post, widget]
33+
responses:
34+
'201':
35+
description: new song added
36+
put:
37+
security:
38+
- song_auth: [update]
39+
- song_auth: [put, widget]
40+
responses:
41+
'204':
42+
description: song updated
43+
delete:
44+
security:
45+
- song_auth: [delete]
46+
- song_auth: [scope2, scope3]
47+
responses:
48+
'200':
49+
description: song deleted

docs/rest-framework/permissions.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ For example:
4848
4949
When a request is performed both the `READ_SCOPE` \\ `WRITE_SCOPE` and 'music' scopes are required to be authorized for the current access token.
5050

51+
5152
TokenHasResourceScope
5253
----------------------
5354
The `TokenHasResourceScope` permission class allows access only when the current access token has been authorized for **all** the scopes listed in the `required_scopes` field of the view but according of request's method.
@@ -81,3 +82,36 @@ For example:
8182
required_scopes = ['music']
8283
8384
The `required_scopes` attribute is mandatory.
85+
86+
87+
TokenMatchesOASRequirements
88+
------------------------------
89+
90+
The `TokenMatchesOASRequirements` permission class allows the access based on a per-method basis
91+
and with alternative lists of required scopes. This permission provides full functionality
92+
required by REST API specifications like the
93+
`OpenAPI Specification (OAS) security requirement object <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securityRequirementObject>`_.
94+
95+
The `required_alternate_scopes` attribute is a required map keyed by HTTP method name where each value is
96+
a list of alternative lists of required scopes.
97+
98+
In the follow example GET requires "read" scope, POST requires either "create" scope **OR** "post" and "widget" scopes,
99+
etc.
100+
101+
.. code-block:: python
102+
103+
class SongView(views.APIView):
104+
authentication_classes = [OAuth2Authentication]
105+
permission_classes = [TokenMatchesOASRequirements]
106+
required_alternate_scopes = {
107+
"GET": [["read"]],
108+
"POST": [["create"], ["post", "widget"]],
109+
"PUT": [["update"], ["put", "widget"]],
110+
"DELETE": [["delete"], ["scope2", "scope3"]],
111+
}
112+
113+
The following is a minimal OAS declaration that shows the same required alternate scopes. It is complete enough
114+
to try it in the `swagger editor <https://editor.swagger.io>`_.
115+
116+
.. literalinclude:: openapi.yaml
117+
:language: YAML

docs/settings.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,10 @@ RESOURCE_SERVER_TOKEN_CACHING_SECONDS
185185
The number of seconds an authorization token received from the introspection endpoint remains valid.
186186
If the expire time of the received token is less than ``RESOURCE_SERVER_TOKEN_CACHING_SECONDS`` the expire time
187187
will be used.
188+
189+
190+
PKCE_REQUIRED
191+
~~~~~~~~~~~~~
192+
Default: ``False``
193+
194+
Whether or not PKCE is required. Can be either a bool or a callable that takes a client id and returns a bool.

docs/tutorial/tutorial_01.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ the API, subject to approval by its users.
8585

8686
Let's register your application.
8787

88-
Point your browser to http://localhost:8000/o/applications/ and add an Application instance.
88+
You need to be logged in before registration. So, go to http://localhost:8000/admin and log in. After that
89+
point your browser to http://localhost:8000/o/applications/ and add an Application instance.
8990
`Client id` and `Client Secret` are automatically generated; you have to provide the rest of the informations:
9091

9192
* `User`: the owner of the Application (e.g. a developer, or the currently logged in user.)

oauth2_provider/apps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44
class DOTConfig(AppConfig):
55
name = "oauth2_provider"
6-
verbose_name = "Django/GeoNode OAuth Toolkit"
6+
verbose_name = "Django OAuth Toolkit"

oauth2_provider/compat.py

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,4 @@
11
"""
22
The `compat` module provides support for backwards compatibility with older
3-
versions of django and python.
3+
versions of Django and Python.
44
"""
5-
# flake8: noqa
6-
from __future__ import unicode_literals
7-
8-
9-
# urlparse in python3 has been renamed to urllib.parse
10-
try:
11-
from urlparse import parse_qs, parse_qsl, urlparse, urlsplit, urlunparse, urlunsplit
12-
except ImportError:
13-
from urllib.parse import parse_qs, parse_qsl, urlparse, urlsplit, urlunsplit, urlunparse
14-
15-
try:
16-
from urllib import urlencode, quote_plus, unquote_plus
17-
except ImportError:
18-
from urllib.parse import urlencode, quote_plus, unquote_plus
19-
20-
# bastb Django 1.10 has updated Middleware. This code imports the Mixin required to get old-style
21-
# middleware working again
22-
# More?
23-
# https://docs.djangoproject.com/en/1.10/topics/http/middleware/#upgrading-pre-django-1-10-style-middleware
24-
try:
25-
from django.utils.deprecation import MiddlewareMixin
26-
except ImportError:
27-
MiddlewareMixin = object
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# flake8: noqa
22
from .authentication import OAuth2Authentication
3-
from .permissions import TokenHasScope, TokenHasReadWriteScope, TokenHasResourceScope
4-
from .permissions import IsAuthenticatedOrTokenHasScope
3+
from .permissions import (
4+
TokenHasScope, TokenHasReadWriteScope, TokenMatchesOASRequirements,
5+
TokenHasResourceScope, IsAuthenticatedOrTokenHasScope
6+
)

oauth2_provider/contrib/rest_framework/authentication.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ def authenticate_header(self, request):
3939
www_authenticate_attributes = OrderedDict([
4040
("realm", self.www_authenticate_realm,),
4141
])
42-
www_authenticate_attributes.update(request.oauth2_error)
42+
oauth2_error = getattr(request, "oauth2_error", {})
43+
www_authenticate_attributes.update(oauth2_error)
4344
return "Bearer {attributes}".format(
4445
attributes=self._dict_to_string(www_authenticate_attributes),
4546
)

0 commit comments

Comments
 (0)