Skip to content

Commit

Permalink
- bump to 1.1.4.1a0
Browse files Browse the repository at this point in the history
  • Loading branch information
afabiani committed Jul 26, 2019
1 parent 1fe832d commit f32211e
Show file tree
Hide file tree
Showing 74 changed files with 1,610 additions and 730 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ __pycache__
pip-log.txt

# Unit test / coverage reports
.cache
.pytest_cache
.coverage
.tox
.pytest_cache/
Expand Down
25 changes: 6 additions & 19 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,31 +1,18 @@
# https://travis-ci.org/evonove/django-oauth-toolkit
sudo: false
language: python
# https://travis-ci.org/jazzband/django-oauth-toolkit
dist: xenial

python: "3.6"
language: python

env:
- TOXENV=py27-django111
- TOXENV=py34-django111
- TOXENV=py36-django111
- TOXENV=py36-django20
- TOXENV=py36-djangomaster
- TOXENV=docs
- TOXENV=flake8
python:
- "3.4"

cache:
directories:
- $HOME/.cache/pip
- $TRAVIS_BUILD_DIR/.tox

matrix:
fast_finish: true

allow_failures:
- env: TOXENV=py36-djangomaster

install:
- pip install coveralls tox
- pip install coveralls tox tox-travis

script:
- tox
Expand Down
17 changes: 14 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
### 1.1.3 [2018-10-12]
### 1.3.0 [unreleased]

* Fix a race condition in creation of AccessToken with external oauth2 server.
* **Backwards-incompatible** squashed migrations:
If you are currently on a release < 1.2.0, you will need to first install 1.2.x then `manage.py migrate` before
upgrading to >= 1.3.0.

### 1.2.0 [2018-06-03]

* **Compatibility**: Python 3.4 is the new minimum required version.
* **Compatibility**: Django 2.0 is the new minimum required version.
* **New feature**: Added TokenMatchesOASRequirements Permissions.
* validators.URIValidator has been updated to match URLValidator behaviour more closely.
* Moved `redirect_uris` validation to the application clean() method.

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

### 1.1.2 [2018-05-12]

Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ Please report any security issues to the JazzBand security team at <security@jaz
Requirements
------------

* Python 2.7, 3.4, 3.5, 3.6
* Django 1.11, 2.0
* Python 3.4+
* Django 2.0+

Installation
------------
Expand Down
9 changes: 9 additions & 0 deletions docs/advanced_topics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ Be aware that, when you intend to swap the application model, you should create
migration defining the swapped application model prior to setting OAUTH2_PROVIDER_APPLICATION_MODEL.
You'll run into models.E022 in Core system checks if you don't get the order right.

You can force your migration providing the custom model to run in the right order by
adding::

run_before = [
('oauth2_provider', '0001_initial'),
]

to the migration class.

That's all, now Django OAuth Toolkit will use your model wherever an Application instance is needed.

**Notice:** `OAUTH2_PROVIDER_APPLICATION_MODEL` is the only setting variable that is not namespaced, this
Expand Down
3 changes: 0 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
#
# Django OAuth Toolkit documentation build configuration file, created by
# sphinx-quickstart on Mon May 20 19:40:43 2013.
#
Expand All @@ -12,7 +10,6 @@
# serve to show the default.

import os
import re
import sys

import django
Expand Down
4 changes: 2 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ If you need support please send a message to the `Django OAuth Toolkit Google Gr
Requirements
------------

* Python 2.7, 3.4, 3.5, 3.6
* Django 1.8, 1.9, 1.10, 1.11
* Python 3.4+
* Django 2.0+

Index
=====
Expand Down
20 changes: 20 additions & 0 deletions docs/rest-framework/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,26 @@ Grab your access_token and start using your new OAuth2 API:
# Insert a new user
curl -H "Authorization: Bearer <your_access_token>" -X POST -d"username=foo&password=bar" http://localhost:8000/users/

Some time has passed and your access token is about to expire, you can get renew the access token issued using the `refresh token`:

::

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/

Your response should be similar to your first access_token request, containing a new access_token and refresh_token:

.. code-block:: javascript
{
"access_token": "<your_new_access_token>",
"token_type": "Bearer",
"expires_in": 36000,
"refresh_token": "<your_new_refresh_token>",
"scope": "read write groups"
}
Step 5: Testing Restricted Access
---------------------------------

Expand Down
49 changes: 49 additions & 0 deletions docs/rest-framework/openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
openapi: "3.0.0"
info:
title: songs
version: v1
components:
securitySchemes:
song_auth:
type: oauth2
flows:
implicit:
authorizationUrl: http://localhost:8000/o/authorize
scopes:
read: read about a song
create: create a new song
update: update an existing song
delete: delete a song
post: create a new song
widget: widget scope
scope2: scope too
scope3: another scope
paths:
/songs:
get:
security:
- song_auth: [read]
responses:
'200':
description: A list of songs.
post:
security:
- song_auth: [create]
- song_auth: [post, widget]
responses:
'201':
description: new song added
put:
security:
- song_auth: [update]
- song_auth: [put, widget]
responses:
'204':
description: song updated
delete:
security:
- song_auth: [delete]
- song_auth: [scope2, scope3]
responses:
'200':
description: song deleted
34 changes: 34 additions & 0 deletions docs/rest-framework/permissions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ For example:
When a request is performed both the `READ_SCOPE` \\ `WRITE_SCOPE` and 'music' scopes are required to be authorized for the current access token.


TokenHasResourceScope
----------------------
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.
Expand Down Expand Up @@ -81,3 +82,36 @@ For example:
required_scopes = ['music']
The `required_scopes` attribute is mandatory.


TokenMatchesOASRequirements
------------------------------

The `TokenMatchesOASRequirements` permission class allows the access based on a per-method basis
and with alternative lists of required scopes. This permission provides full functionality
required by REST API specifications like the
`OpenAPI Specification (OAS) security requirement object <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securityRequirementObject>`_.

The `required_alternate_scopes` attribute is a required map keyed by HTTP method name where each value is
a list of alternative lists of required scopes.

In the follow example GET requires "read" scope, POST requires either "create" scope **OR** "post" and "widget" scopes,
etc.

.. code-block:: python
class SongView(views.APIView):
authentication_classes = [OAuth2Authentication]
permission_classes = [TokenMatchesOASRequirements]
required_alternate_scopes = {
"GET": [["read"]],
"POST": [["create"], ["post", "widget"]],
"PUT": [["update"], ["put", "widget"]],
"DELETE": [["delete"], ["scope2", "scope3"]],
}
The following is a minimal OAS declaration that shows the same required alternate scopes. It is complete enough
to try it in the `swagger editor <https://editor.swagger.io>`_.

.. literalinclude:: openapi.yaml
:language: YAML
7 changes: 7 additions & 0 deletions docs/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,10 @@ RESOURCE_SERVER_TOKEN_CACHING_SECONDS
The number of seconds an authorization token received from the introspection endpoint remains valid.
If the expire time of the received token is less than ``RESOURCE_SERVER_TOKEN_CACHING_SECONDS`` the expire time
will be used.


PKCE_REQUIRED
~~~~~~~~~~~~~
Default: ``False``

Whether or not PKCE is required. Can be either a bool or a callable that takes a client id and returns a bool.
3 changes: 2 additions & 1 deletion docs/tutorial/tutorial_01.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ the API, subject to approval by its users.

Let's register your application.

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

* `User`: the owner of the Application (e.g. a developer, or the currently logged in user.)
Expand Down
2 changes: 1 addition & 1 deletion oauth2_provider/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

class DOTConfig(AppConfig):
name = "oauth2_provider"
verbose_name = "Django/GeoNode OAuth Toolkit"
verbose_name = "Django OAuth Toolkit"
25 changes: 1 addition & 24 deletions oauth2_provider/compat.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,4 @@
"""
The `compat` module provides support for backwards compatibility with older
versions of django and python.
versions of Django and Python.
"""
# flake8: noqa
from __future__ import unicode_literals


# urlparse in python3 has been renamed to urllib.parse
try:
from urlparse import parse_qs, parse_qsl, urlparse, urlsplit, urlunparse, urlunsplit
except ImportError:
from urllib.parse import parse_qs, parse_qsl, urlparse, urlsplit, urlunsplit, urlunparse

try:
from urllib import urlencode, quote_plus, unquote_plus
except ImportError:
from urllib.parse import urlencode, quote_plus, unquote_plus

# bastb Django 1.10 has updated Middleware. This code imports the Mixin required to get old-style
# middleware working again
# More?
# https://docs.djangoproject.com/en/1.10/topics/http/middleware/#upgrading-pre-django-1-10-style-middleware
try:
from django.utils.deprecation import MiddlewareMixin
except ImportError:
MiddlewareMixin = object
6 changes: 4 additions & 2 deletions oauth2_provider/contrib/rest_framework/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# flake8: noqa
from .authentication import OAuth2Authentication
from .permissions import TokenHasScope, TokenHasReadWriteScope, TokenHasResourceScope
from .permissions import IsAuthenticatedOrTokenHasScope
from .permissions import (
TokenHasScope, TokenHasReadWriteScope, TokenMatchesOASRequirements,
TokenHasResourceScope, IsAuthenticatedOrTokenHasScope
)
3 changes: 2 additions & 1 deletion oauth2_provider/contrib/rest_framework/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ def authenticate_header(self, request):
www_authenticate_attributes = OrderedDict([
("realm", self.www_authenticate_realm,),
])
www_authenticate_attributes.update(request.oauth2_error)
oauth2_error = getattr(request, "oauth2_error", {})
www_authenticate_attributes.update(oauth2_error)
return "Bearer {attributes}".format(
attributes=self._dict_to_string(www_authenticate_attributes),
)
Loading

0 comments on commit f32211e

Please sign in to comment.