Skip to content

Commit 825ce98

Browse files
authored
Merge branch 'master' into cors-oauthlib
2 parents 46241ad + bd865d6 commit 825ce98

File tree

10 files changed

+67
-25
lines changed

10 files changed

+67
-25
lines changed

.github/workflows/test.yml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,27 @@ on: [push, pull_request]
44

55
jobs:
66
build:
7+
name: build (Python ${{ matrix.python-version }}, Django ${{ matrix.django-version }})
78
runs-on: ubuntu-latest
89
strategy:
910
fail-fast: false
10-
max-parallel: 5
1111
matrix:
1212
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
13+
django-version: ['2.2', '3.2', '4.0', '4.1', 'main']
14+
exclude:
15+
# https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django
16+
17+
# Python 3.10+ is not supported by Django 2.2
18+
- python-version: '3.10'
19+
django-version: '2.2'
20+
21+
# Python 3.7 is not supported by Django 4.0+
22+
- python-version: '3.7'
23+
django-version: '4.0'
24+
- python-version: '3.7'
25+
django-version: '4.1'
26+
- python-version: '3.7'
27+
django-version: 'main'
1328

1429
steps:
1530
- uses: actions/checkout@v2
@@ -42,8 +57,18 @@ jobs:
4257
- name: Tox tests
4358
run: |
4459
tox -v
60+
env:
61+
DJANGO: ${{ matrix.django-version }}
4562

4663
- name: Upload coverage
4764
uses: codecov/codecov-action@v1
4865
with:
4966
name: Python ${{ matrix.python-version }}
67+
68+
success:
69+
needs: build
70+
runs-on: ubuntu-latest
71+
name: Test successful
72+
steps:
73+
- name: Success
74+
run: echo Test successful

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/psf/black
3-
rev: 22.12.0
3+
rev: 23.1.0
44
hooks:
55
- id: black
66
exclude: ^(oauth2_provider/migrations/|tests/migrations/)
@@ -16,7 +16,7 @@ repos:
1616
- id: mixed-line-ending
1717
args: ['--fix=lf']
1818
- repo: https://github.com/PyCQA/isort
19-
rev: 5.10.1
19+
rev: 5.12.0
2020
hooks:
2121
- id: isort
2222
exclude: ^(oauth2_provider/migrations/|tests/migrations/)

AUTHORS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Joseph Abrahams
6060
Josh Thomas
6161
Jozef Knaperek
6262
Julien Palard
63+
Julian Mundhahs
6364
Jun Zhou
6465
Kaleb Porter
6566
Kristian Rune Larsen
@@ -90,3 +91,4 @@ Víðir Valberg Guðmundsson
9091
Will Beaufoy
9192
pySilver
9293
Łukasz Skarżyński
94+
Marcus Sonestedt

docs/settings.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ this value if you wrote your own implementation (subclass of
177177
ROTATE_REFRESH_TOKEN
178178
~~~~~~~~~~~~~~~~~~~~
179179
When is set to `True` (default) a new refresh token is issued to the client when the client refreshes an access token.
180-
Known bugs: `False` currently has a side effect of immediately revoking both access and refresh token on refreshing.
180+
If `False`, it will reuse the same refresh token and only update the access token with a new token value.
181181
See also: validator's rotate_refresh_token method can be overridden to make this variable
182182
(could be usable with expiring refresh tokens, in particular, so that they are rotated
183183
when close to expiration, theoretically).

docs/tutorial/tutorial_01.rst

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ point your browser to http://localhost:8000/o/applications/ and add an Applicati
8989
* `Redirect uris`: Applications must register at least one redirection endpoint before using the
9090
authorization endpoint. The :term:`Authorization Server` will deliver the access token to the client only if the client
9191
specifies one of the verified redirection uris. For this tutorial, paste verbatim the value
92-
`http://django-oauth-toolkit.herokuapp.com/consumer/exchange/`
92+
`https://www.getpostman.com/oauth2/callback`
9393

9494
* `Client type`: this value affects the security level at which some communications between the client application and
9595
the authorization server are performed. For this tutorial choose *Confidential*.
@@ -105,17 +105,28 @@ process we'll explain shortly)
105105
Test Your Authorization Server
106106
------------------------------
107107
Your authorization server is ready and can begin issuing access tokens. To test the process you need an OAuth2
108-
consumer; if you are familiar enough with OAuth2, you can use curl, requests, or anything that speaks http. For the rest
109-
of us, there is a `consumer service <http://django-oauth-toolkit.herokuapp.com/consumer/>`_ deployed on Heroku to test
110-
your provider.
108+
consumer; if you are familiar enough with OAuth2, you can use curl, requests, or anything that speaks http.
109+
110+
For this tutorial, we suggest using [Postman](https://www.postman.com/downloads/) :
111+
112+
Open up the Authorization tab under a request and, for this tutorial, set the fields as follows:
113+
114+
* Grant type: `Authorization code (With PKCE)`
115+
* Callback URL: `https://www.getpostman.com/oauth2/callback` <- need to be in your added application
116+
* Authorize using browser: leave unchecked
117+
* Auth URL: `http://localhost:8000/o/authorize/`
118+
* Access Token URL: `http://localhost:8000/o/token/`
119+
* Client ID: `random string for this app, as generated`
120+
* Client Secret: `random string for this app, as generated` <- must be before hashing, should not begin with 'pbkdf2_sha256' or similar
121+
122+
The rest can be left to their (mostly empty) default values.
111123

112124
Build an Authorization Link for Your Users
113125
++++++++++++++++++++++++++++++++++++++++++
114126
Authorizing an application to access OAuth2 protected data in an :term:`Authorization Code` flow is always initiated
115-
by the user. Your application can prompt users to click a special link to start the process. Go to the
116-
`Consumer <http://django-oauth-toolkit.herokuapp.com/consumer/>`_ page and complete the form by filling in your
117-
application's details obtained from the steps in this tutorial. Submit the form, and you'll receive a link your users can
118-
use to access the authorization page.
127+
by the user. Your application can prompt users to click a special link to start the process.
128+
129+
Here, we click "Get New Access Token" in postman, which should open your browser and show django's login.
119130

120131
Authorize the Application
121132
+++++++++++++++++++++++++
@@ -125,18 +136,19 @@ page is login protected by django-oauth-toolkit. Login, then you should see the
125136
her authorization to the client application. Flag the *Allow* checkbox and click *Authorize*, you will be redirected
126137
again to the consumer service.
127138

128-
__ loginTemplate_
139+
Possible errors:
129140

130-
If you are not redirected to the correct page after logging in successfully,
131-
you probably need to `setup your login template correctly`__.
141+
* loginTemplate: If you are not redirected to the correct page after logging in successfully, you probably need to `setup your login template correctly`__.
142+
* invalid client: client id and client secret needs to be correct. Secret cannot be copied from Django admin after creation.
143+
(but you can reset it by pasting the same random string into Django admin and into Postman, to avoid recreating the app)
144+
* invalid callback url: Add the postman link into your app in Django admin.
145+
* invalid_request: Use "Authorization Code (With PCKE)" from postman or disable PKCE in Django
132146

133147
Exchange the token
134148
++++++++++++++++++
135149
At this point your authorization server redirected the user to a special page on the consumer passing in an
136150
:term:`Authorization Code`, a special token the consumer will use to obtain the final access token.
137-
This operation is usually done automatically by the client application during the request/response cycle, but we cannot
138-
make a POST request from Heroku to your localhost, so we proceed manually with this step. Fill the form with the
139-
missing data and click *Submit*.
151+
140152
If everything is ok, you will be routed to another page showing your access token, the token type, its lifetime and
141153
the :term:`Refresh Token`.
142154

oauth2_provider/models.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,6 @@ def redirect_to_uri_allowed(uri, allowed_uris):
749749
and parsed_allowed_uri.netloc == parsed_uri.netloc
750750
and parsed_allowed_uri.path == parsed_uri.path
751751
):
752-
753752
aqs_set = set(parse_qsl(parsed_allowed_uri.query))
754753
if aqs_set.issubset(uqs_set):
755754
return True

oauth2_provider/oauth2_validators.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,6 @@ def save_bearer_token(self, token, request, *args, **kwargs):
572572
and isinstance(refresh_token_instance, RefreshToken)
573573
and refresh_token_instance.access_token
574574
):
575-
576575
access_token = AccessToken.objects.select_for_update().get(
577576
pk=refresh_token_instance.access_token.pk
578577
)

oauth2_provider/views/oidc.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ def get(self, request, *args, **kwargs):
8686
oauth2_settings.OIDC_RSA_PRIVATE_KEY,
8787
*oauth2_settings.OIDC_RSA_PRIVATE_KEYS_INACTIVE,
8888
]:
89-
9089
key = jwk.JWK.from_pem(pem.encode("utf8"))
9190
data = {"alg": "RS256", "use": "sig", "kid": key.thumbprint()}
9291
data.update(json.loads(key.export_public()))

tests/test_oauth2_validators.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ def test_save_bearer_token__without_user__raises_fatal_client(self):
160160
self.validator.save_bearer_token(token, mock.MagicMock())
161161

162162
def test_save_bearer_token__with_existing_tokens__does_not_create_new_tokens(self):
163-
164163
rotate_token_function = mock.MagicMock()
165164
rotate_token_function.return_value = False
166165
self.validator.rotate_refresh_token = rotate_token_function
@@ -190,7 +189,6 @@ def test_save_bearer_token__with_existing_tokens__does_not_create_new_tokens(sel
190189
self.assertEqual(1, AccessToken.objects.count())
191190

192191
def test_save_bearer_token__checks_to_rotate_tokens(self):
193-
194192
rotate_token_function = mock.MagicMock()
195193
rotate_token_function.return_value = False
196194
self.validator.rotate_refresh_token = rotate_token_function

tox.ini

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ envlist =
99
py{37,38,39,310}-dj32,
1010
py{38,39,310}-dj40,
1111
py{38,39,310,311}-dj41,
12-
py{38,39,310,311}-djmain,
12+
py{310,311}-djmain,
1313

1414
[gh-actions]
1515
python =
@@ -19,6 +19,14 @@ python =
1919
3.10: py310
2020
3.11: py311
2121

22+
[gh-actions:env]
23+
DJANGO =
24+
2.2: dj22
25+
3.2: dj32
26+
4.0: dj40
27+
4.1: dj41
28+
main: djmain
29+
2230
[pytest]
2331
django_find_project = false
2432
addopts =
@@ -70,7 +78,7 @@ commands =
7078
[testenv:{docs,livedocs}]
7179
basepython = python3.8
7280
changedir = docs
73-
whitelist_externals = make
81+
allowlist_externals = make
7482
commands =
7583
docs: make html
7684
livedocs: make livehtml

0 commit comments

Comments
 (0)