diff --git a/oauth2_provider/management/commands/createapplication.py b/oauth2_provider/management/commands/createapplication.py
index e63d54280..95cb2d865 100644
--- a/oauth2_provider/management/commands/createapplication.py
+++ b/oauth2_provider/management/commands/createapplication.py
@@ -3,6 +3,7 @@
from oauth2_provider.models import get_application_model
+
Application = get_application_model()
@@ -11,44 +12,44 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument(
- 'client_type',
+ "client_type",
type=str,
- help='The client type, can be confidential or public',
+ help="The client type, can be confidential or public",
)
parser.add_argument(
- 'authorization_grant_type',
+ "authorization_grant_type",
type=str,
- help='The type of authorization grant to be used',
+ help="The type of authorization grant to be used",
)
parser.add_argument(
- '--client-id',
+ "--client-id",
type=str,
- help='The ID of the new application',
+ help="The ID of the new application",
)
parser.add_argument(
- '--user',
+ "--user",
type=str,
- help='The user the application belongs to',
+ help="The user the application belongs to",
)
parser.add_argument(
- '--redirect-uris',
+ "--redirect-uris",
type=str,
- help='The redirect URIs, this must be a space separated string e.g "URI1 URI2',
+ help="The redirect URIs, this must be a space separated string e.g 'URI1 URI2'",
)
parser.add_argument(
- '--client-secret',
+ "--client-secret",
type=str,
- help='The secret for this application',
+ help="The secret for this application",
)
parser.add_argument(
- '--name',
+ "--name",
type=str,
- help='The name this application',
+ help="The name this application",
)
parser.add_argument(
- '--skip-authorization',
- action='store_true',
- help='The ID of the new application',
+ "--skip-authorization",
+ action="store_true",
+ help="The ID of the new application",
)
def handle(self, *args, **options):
@@ -61,8 +62,8 @@ def handle(self, *args, **options):
# verbosity and others. Also do not pass any None to the Application
# instance so default values will be generated for those fields
if key in application_fields and value:
- if key == 'user':
- application_data.update({'user_id': value})
+ if key == "user":
+ application_data.update({"user_id": value})
else:
application_data.update({key: value})
@@ -71,15 +72,15 @@ def handle(self, *args, **options):
try:
new_application.full_clean()
except ValidationError as exc:
- errors = "\n ".join(['- ' + err_key + ': ' + str(err_value) for err_key,
+ errors = "\n ".join(["- " + err_key + ": " + str(err_value) for err_key,
err_value in exc.message_dict.items()])
self.stdout.write(
self.style.ERROR(
- 'Please correct the following errors:\n %s' % errors
+ "Please correct the following errors:\n %s" % errors
)
)
else:
new_application.save()
self.stdout.write(
- self.style.SUCCESS('New application created successfully')
+ self.style.SUCCESS("New application created successfully")
)
diff --git a/oauth2_provider/models.py b/oauth2_provider/models.py
index c29faaa83..f87a51691 100644
--- a/oauth2_provider/models.py
+++ b/oauth2_provider/models.py
@@ -1,6 +1,6 @@
+import logging
from datetime import timedelta
from urllib.parse import parse_qsl, urlparse
-import logging
from django.apps import apps
from django.conf import settings
@@ -15,6 +15,7 @@
from .settings import oauth2_settings
from .validators import RedirectURIValidator, WildcardSet
+
logger = logging.getLogger(__name__)
@@ -263,7 +264,7 @@ class AbstractAccessToken(models.Model):
Fields:
- * :attr:`user` The Django user representing resources' owner
+ * :attr:`user` The Django user representing resources" owner
* :attr:`source_refresh_token` If from a refresh, the consumed RefeshToken
* :attr:`token` Access token
* :attr:`application` Application instance
@@ -323,7 +324,7 @@ def allow_scopes(self, scopes):
def revoke(self):
"""
- Convenience method to uniform tokens' interface, for now
+ Convenience method to uniform tokens" interface, for now
simply remove this token from the database in order to revoke it.
"""
self.delete()
@@ -356,7 +357,7 @@ class AbstractRefreshToken(models.Model):
Fields:
- * :attr:`user` The Django user representing resources' owner
+ * :attr:`user` The Django user representing resources" owner
* :attr:`token` Token value
* :attr:`application` Application instance
* :attr:`access_token` AccessToken instance this refresh token is
@@ -459,14 +460,14 @@ def clear_expired():
access_token__expires__lt=refresh_expire_at,
)
- logger.info('%s Revoked refresh tokens to be deleted', revoked.count())
- logger.info('%s Expired refresh tokens to be deleted', expired.count())
+ logger.info("%s Revoked refresh tokens to be deleted", revoked.count())
+ logger.info("%s Expired refresh tokens to be deleted", expired.count())
revoked.delete()
expired.delete()
else:
- logger.info('refresh_expire_at is %s. No refresh tokens deleted.',
- refresh_expire_at)
+ logger.info("refresh_expire_at is %s. No refresh tokens deleted.",
+ refresh_expire_at)
access_tokens = access_token_model.objects.filter(
refresh_token__isnull=True,
@@ -474,8 +475,8 @@ def clear_expired():
)
grants = grant_model.objects.filter(expires__lt=now)
- logger.info('%s Expired access tokens to be deleted', access_tokens.count())
- logger.info('%s Expired grant tokens to be deleted', grants.count())
+ logger.info("%s Expired access tokens to be deleted", access_tokens.count())
+ logger.info("%s Expired grant tokens to be deleted", grants.count())
access_tokens.delete()
grants.delete()
diff --git a/oauth2_provider/oauth2_validators.py b/oauth2_provider/oauth2_validators.py
index 3595d12fc..9027a4841 100644
--- a/oauth2_provider/oauth2_validators.py
+++ b/oauth2_provider/oauth2_validators.py
@@ -480,7 +480,7 @@ def save_bearer_token(self, token, request, *args, **kwargs):
# expires_in is passed to Server on initialization
# custom server class can have logic to override this
expires = timezone.now() + timedelta(seconds=token.get(
- 'expires_in', oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS,
+ "expires_in", oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS,
))
if request.grant_type == "client_credentials":
diff --git a/oauth2_provider/settings.py b/oauth2_provider/settings.py
index 2e513928c..858efdbe7 100644
--- a/oauth2_provider/settings.py
+++ b/oauth2_provider/settings.py
@@ -188,18 +188,19 @@ def server_kwargs(self):
processing, callables have to be assigned directly.
For the likes of signed_token_generator it means something like
- {'token_generator': signed_token_generator(privkey, **kwargs)}
+ {"token_generator": signed_token_generator(privkey, **kwargs)}
"""
kwargs = {
key: getattr(self, value)
for key, value in [
- ('token_expires_in', 'ACCESS_TOKEN_EXPIRE_SECONDS'),
- ('refresh_token_expires_in', 'REFRESH_TOKEN_EXPIRE_SECONDS'),
- ('token_generator', 'ACCESS_TOKEN_GENERATOR'),
- ('refresh_token_generator', 'REFRESH_TOKEN_GENERATOR'),
+ ("token_expires_in", "ACCESS_TOKEN_EXPIRE_SECONDS"),
+ ("refresh_token_expires_in", "REFRESH_TOKEN_EXPIRE_SECONDS"),
+ ("token_generator", "ACCESS_TOKEN_GENERATOR"),
+ ("refresh_token_generator", "REFRESH_TOKEN_GENERATOR"),
]
}
kwargs.update(self.EXTRA_SERVER_KWARGS)
return kwargs
+
oauth2_settings = OAuth2ProviderSettings(USER_SETTINGS, DEFAULTS, IMPORT_STRINGS, MANDATORY)
diff --git a/oauth2_provider/validators.py b/oauth2_provider/validators.py
index a6f3a33b6..f3f82102c 100644
--- a/oauth2_provider/validators.py
+++ b/oauth2_provider/validators.py
@@ -3,7 +3,7 @@
from django.core.exceptions import ValidationError
from django.core.validators import URLValidator
-from django.utils.encoding import force_text
+from django.utils.encoding import force_str
class URIValidator(URLValidator):
@@ -28,7 +28,7 @@ def __init__(self, allowed_schemes, allow_fragments=False):
def __call__(self, value):
super().__call__(value)
- value = force_text(value)
+ value = force_str(value)
scheme, netloc, path, query, fragment = urlsplit(value)
if fragment and not self.allow_fragments:
raise ValidationError("Redirect URIs must not contain fragments")
diff --git a/oauth2_provider/views/base.py b/oauth2_provider/views/base.py
index 02c32c6aa..8a3a59c25 100644
--- a/oauth2_provider/views/base.py
+++ b/oauth2_provider/views/base.py
@@ -4,13 +4,13 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse, JsonResponse
+from django.shortcuts import render
+from django.urls import reverse
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.debug import sensitive_post_parameters
from django.views.generic import FormView, View
-from django.shortcuts import render
-from django.urls import reverse
from ..exceptions import OAuthToolkitError
from ..forms import AllowForm
@@ -21,6 +21,7 @@
from ..signals import app_authorized
from .mixins import OAuthLibMixin
+
log = logging.getLogger("oauth2_provider")
@@ -61,7 +62,9 @@ def redirect(self, redirect_to, application):
allowed_schemes = application.get_allowed_schemes()
return OAuth2ResponseRedirect(redirect_to, allowed_schemes)
-RFC3339 = '%Y-%m-%dT%H:%M:%SZ'
+
+RFC3339 = "%Y-%m-%dT%H:%M:%SZ"
+
class AuthorizationView(BaseAuthorizationView, FormView):
"""
@@ -208,23 +211,22 @@ def get(self, request, *args, **kwargs):
return self.render_to_response(self.get_context_data(**kwargs))
- def redirect(self, redirect_to, application,
- token = None):
+ def redirect(self, redirect_to, application, token=None):
if not redirect_to.startswith("urn:ietf:wg:oauth:2.0:oob"):
return super().redirect(redirect_to, application)
parsed_redirect = urllib.parse.urlparse(redirect_to)
- code = urllib.parse.parse_qs(parsed_redirect.query)['code'][0]
+ code = urllib.parse.parse_qs(parsed_redirect.query)["code"][0]
- if redirect_to.startswith('urn:ietf:wg:oauth:2.0:oob:auto'):
+ if redirect_to.startswith("urn:ietf:wg:oauth:2.0:oob:auto"):
response = {
- 'access_token': code,
- 'token_uri': redirect_to,
- 'client_id': application.client_id,
- 'client_secret': application.client_secret,
- 'revoke_uri': reverse('oauth2_provider:revoke-token'),
+ "access_token": code,
+ "token_uri": redirect_to,
+ "client_id": application.client_id,
+ "client_secret": application.client_secret,
+ "revoke_uri": reverse("oauth2_provider:revoke-token"),
}
return JsonResponse(response)
@@ -234,10 +236,11 @@ def redirect(self, redirect_to, application,
request=self.request,
template_name="oauth2_provider/authorized-oob.html",
context={
- 'code': code,
+ "code": code,
},
)
+
@method_decorator(csrf_exempt, name="dispatch")
class TokenView(OAuthLibMixin, View):
"""
diff --git a/tests/models.py b/tests/models.py
index cbbc50ba9..7ca0c57c5 100644
--- a/tests/models.py
+++ b/tests/models.py
@@ -1,10 +1,10 @@
from django.db import models
-from oauth2_provider.settings import oauth2_settings
from oauth2_provider.models import (
AbstractAccessToken, AbstractApplication,
AbstractGrant, AbstractRefreshToken
)
+from oauth2_provider.settings import oauth2_settings
class BaseTestApplication(AbstractApplication):
diff --git a/tests/settings.py b/tests/settings.py
index 1b7ba8db6..40eef5ebd 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -9,7 +9,7 @@
}
}
-AUTH_USER_MODEL = 'auth.User'
+AUTH_USER_MODEL = "auth.User"
OAUTH2_PROVIDER_APPLICATION_MODEL = "oauth2_provider.Application"
OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = "oauth2_provider.AccessToken"
OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = "oauth2_provider.RefreshToken"
diff --git a/tests/test_application_views.py b/tests/test_application_views.py
index 74162f087..6130876ce 100644
--- a/tests/test_application_views.py
+++ b/tests/test_application_views.py
@@ -8,6 +8,7 @@
from .models import SampleApplication
+
Application = get_application_model()
UserModel = get_user_model()
diff --git a/tests/test_authorization_code.py b/tests/test_authorization_code.py
index 793cca2d9..9a95bc269 100644
--- a/tests/test_authorization_code.py
+++ b/tests/test_authorization_code.py
@@ -31,6 +31,7 @@
URI_OOB = "urn:ietf:wg:oauth:2.0:oob"
URI_OOB_AUTO = "urn:ietf:wg:oauth:2.0:oob:auto"
+
# mocking a protected resource view
class ResourceView(ProtectedResourceView):
def get(self, request, *args, **kwargs):
@@ -1467,7 +1468,7 @@ def test_oob_as_html(self):
response = self.client.post(reverse("oauth2_provider:authorize"), data=authcode_data)
self.assertEqual(response.status_code, 200)
- self.assertRegex(response['Content-Type'], r'^text/html')
+ self.assertRegex(response["Content-Type"], r"^text/html")
content = response.content.decode("utf-8")
@@ -1475,12 +1476,9 @@ def test_oob_as_html(self):
# to extract the token, risking summoning zalgo in the process."
# -- https://github.com/jazzband/django-oauth-toolkit/issues/235
- matches = re.search(r'.*([^<>]*)
',
- content)
- self.assertIsNotNone(matches,
- msg="OOB response contains code inside tag")
- self.assertEqual(len(matches.groups()), 1,
- msg="OOB response contains multiple tags")
+ matches = re.search(r".*([^<>]*)
", content)
+ self.assertIsNotNone(matches, msg="OOB response contains code inside tag")
+ self.assertEqual(len(matches.groups()), 1, msg="OOB response contains multiple tags")
authorization_code = matches.groups()[0]
token_request_data = {
@@ -1516,12 +1514,12 @@ def test_oob_as_json(self):
response = self.client.post(reverse("oauth2_provider:authorize"), data=authcode_data)
self.assertEqual(response.status_code, 200)
- self.assertRegex(response['Content-Type'], '^application/json')
+ self.assertRegex(response["Content-Type"], "^application/json")
parsed_response = json.loads(response.content.decode("utf-8"))
- self.assertIn('access_token', parsed_response)
- authorization_code = parsed_response['access_token']
+ self.assertIn("access_token", parsed_response)
+ authorization_code = parsed_response["access_token"]
token_request_data = {
"grant_type": "authorization_code",
@@ -1539,6 +1537,7 @@ def test_oob_as_json(self):
self.assertEqual(content["scope"], "read write")
self.assertEqual(content["expires_in"], oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS)
+
class TestAuthorizationCodeProtectedResource(BaseTest):
def test_resource_access_allowed(self):
self.client.login(username="test_user", password="123456")
diff --git a/tests/test_commands.py b/tests/test_commands.py
index 8f1ddc27f..274eccec5 100644
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -7,6 +7,7 @@
from oauth2_provider.models import get_application_model
+
Application = get_application_model()
@@ -16,35 +17,35 @@ def test_command_creates_application(self):
output = StringIO()
self.assertEqual(Application.objects.count(), 0)
call_command(
- 'createapplication',
- 'confidential',
- 'authorization-code',
- '--redirect-uris=http://example.com http://example2.com',
+ "createapplication",
+ "confidential",
+ "authorization-code",
+ "--redirect-uris=http://example.com http://example2.com",
stdout=output,
)
self.assertEqual(Application.objects.count(), 1)
- self.assertIn('New application created successfully', output.getvalue())
+ self.assertIn("New application created successfully", output.getvalue())
def test_missing_required_args(self):
self.assertEqual(Application.objects.count(), 0)
with self.assertRaises(CommandError) as ctx:
call_command(
- 'createapplication',
- '--redirect-uris=http://example.com http://example2.com',
+ "createapplication",
+ "--redirect-uris=http://example.com http://example2.com",
)
- self.assertIn('client_type', ctx.exception.args[0])
- self.assertIn('authorization_grant_type', ctx.exception.args[0])
+ self.assertIn("client_type", ctx.exception.args[0])
+ self.assertIn("authorization_grant_type", ctx.exception.args[0])
self.assertEqual(Application.objects.count(), 0)
def test_command_creates_application_with_skipped_auth(self):
self.assertEqual(Application.objects.count(), 0)
call_command(
- 'createapplication',
- 'confidential',
- 'authorization-code',
- '--redirect-uris=http://example.com http://example2.com',
- '--skip-authorization',
+ "createapplication",
+ "confidential",
+ "authorization-code",
+ "--redirect-uris=http://example.com http://example2.com",
+ "--skip-authorization",
)
app = Application.objects.get()
@@ -52,10 +53,10 @@ def test_command_creates_application_with_skipped_auth(self):
def test_application_created_normally_with_no_skipped_auth(self):
call_command(
- 'createapplication',
- 'confidential',
- 'authorization-code',
- '--redirect-uris=http://example.com http://example2.com',
+ "createapplication",
+ "confidential",
+ "authorization-code",
+ "--redirect-uris=http://example.com http://example2.com",
)
app = Application.objects.get()
@@ -63,49 +64,49 @@ def test_application_created_normally_with_no_skipped_auth(self):
def test_application_created_with_name(self):
call_command(
- 'createapplication',
- 'confidential',
- 'authorization-code',
- '--redirect-uris=http://example.com http://example2.com',
- '--name=TEST',
+ "createapplication",
+ "confidential",
+ "authorization-code",
+ "--redirect-uris=http://example.com http://example2.com",
+ "--name=TEST",
)
app = Application.objects.get()
- self.assertEqual(app.name, 'TEST')
+ self.assertEqual(app.name, "TEST")
def test_application_created_with_client_secret(self):
call_command(
- 'createapplication',
- 'confidential',
- 'authorization-code',
- '--redirect-uris=http://example.com http://example2.com',
- '--client-secret=SECRET',
+ "createapplication",
+ "confidential",
+ "authorization-code",
+ "--redirect-uris=http://example.com http://example2.com",
+ "--client-secret=SECRET",
)
app = Application.objects.get()
- self.assertEqual(app.client_secret, 'SECRET')
+ self.assertEqual(app.client_secret, "SECRET")
def test_application_created_with_client_id(self):
call_command(
- 'createapplication',
- 'confidential',
- 'authorization-code',
- '--redirect-uris=http://example.com http://example2.com',
- '--client-id=someId',
+ "createapplication",
+ "confidential",
+ "authorization-code",
+ "--redirect-uris=http://example.com http://example2.com",
+ "--client-id=someId",
)
app = Application.objects.get()
- self.assertEqual(app.client_id, 'someId')
+ self.assertEqual(app.client_id, "someId")
def test_application_created_with_user(self):
User = get_user_model()
user = User.objects.create()
call_command(
- 'createapplication',
- 'confidential',
- 'authorization-code',
- '--redirect-uris=http://example.com http://example2.com',
- '--user=%s' % user.pk,
+ "createapplication",
+ "confidential",
+ "authorization-code",
+ "--redirect-uris=http://example.com http://example2.com",
+ "--user=%s" % user.pk,
)
app = Application.objects.get()
@@ -114,14 +115,14 @@ def test_application_created_with_user(self):
def test_validation_failed_message(self):
output = StringIO()
call_command(
- 'createapplication',
- 'confidential',
- 'authorization-code',
- '--redirect-uris=http://example.com http://example2.com',
- '--user=783',
+ "createapplication",
+ "confidential",
+ "authorization-code",
+ "--redirect-uris=http://example.com http://example2.com",
+ "--user=783",
stdout=output,
)
- self.assertIn('user', output.getvalue())
- self.assertIn('783', output.getvalue())
- self.assertIn('does not exist', output.getvalue())
+ self.assertIn("user", output.getvalue())
+ self.assertIn("783", output.getvalue())
+ self.assertIn("does not exist", output.getvalue())
diff --git a/tests/test_rest_framework.py b/tests/test_rest_framework.py
index 0251d98fe..21a6ccd71 100644
--- a/tests/test_rest_framework.py
+++ b/tests/test_rest_framework.py
@@ -98,10 +98,12 @@ class TokenHasScopeViewWrongAuth(BrokenOAuth2View):
class MethodScopeAltViewWrongAuth(BrokenOAuth2View):
permission_classes = [TokenMatchesOASRequirements]
+
class AuthenticationNone(OAuth2Authentication):
def authenticate(self, request):
return None
+
class AuthenticationNoneOAuth2View(MockView):
authentication_classes = [AuthenticationNone]
diff --git a/tests/test_token_revocation.py b/tests/test_token_revocation.py
index d1ab591d2..fdbc07229 100644
--- a/tests/test_token_revocation.py
+++ b/tests/test_token_revocation.py
@@ -1,5 +1,4 @@
import datetime
-from urllib.parse import urlencode
from django.contrib.auth import get_user_model
from django.test import RequestFactory, TestCase
diff --git a/tox.ini b/tox.ini
index 9c476eab8..7fce944af 100644
--- a/tox.ini
+++ b/tox.ini
@@ -46,12 +46,11 @@ deps = sphinx
[testenv:py37-flake8]
skip_install = True
commands =
- flake8 --exit-zero {toxinidir}
+ flake8 {toxinidir}
deps =
flake8
flake8-isort
-# TODO: restore this:
-# flake8-quotes
+ flake8-quotes
[coverage:run]
source = oauth2_provider
@@ -59,7 +58,7 @@ omit = */migrations/*
[flake8]
max-line-length = 110
-exclude = docs/, oauth2_provider/migrations/, .tox/
+exclude = docs/, oauth2_provider/migrations/, tests/migrations/, .tox/
application-import-names = oauth2_provider
inline-quotes = double