Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions oauth2_provider/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
from urllib.parse import urlparse, parse_qs, urlunparse

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

# Django 1.5 add support for custom auth user model
if django.VERSION >= (1, 5):
Expand Down
3 changes: 2 additions & 1 deletion oauth2_provider/oauth2_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.contrib.auth import authenticate
from oauthlib.oauth2 import RequestValidator

from .compat import unquote_plus
from .models import Grant, AccessToken, RefreshToken, get_application_model
from .settings import oauth2_settings

Expand Down Expand Up @@ -44,7 +45,7 @@ def _authenticate_basic_auth(self, request):
client_id, client_secret = auth_string_decoded.split(':', 1)

try:
request.client = Application.objects.get(client_id=client_id, client_secret=client_secret)
request.client = Application.objects.get(client_id=unquote_plus(client_id), client_secret=unquote_plus(client_secret))
return True

except Application.DoesNotExist:
Expand Down
46 changes: 46 additions & 0 deletions oauth2_provider/tests/test_client_credential.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from __future__ import unicode_literals

import json
import base64
try:
import urllib.parse as urllib
except ImportError:
import urllib

from django.core.urlresolvers import reverse
from django.test import TestCase, RequestFactory
Expand Down Expand Up @@ -116,3 +121,44 @@ def get_scopes(self):
self.assertEqual(r.user, self.dev_user)
self.assertEqual(r.client, self.application)
self.assertEqual(r.scopes, ['read', 'write'])


class TestClientResourcePasswordBased(BaseTest):
def test_client_resource_password_based(self):
"""
Request an access token using Resource Owner Password Based flow
"""

self.application.delete()
self.application = Application(
name="test_client_credentials_app",
user=self.dev_user,
client_type=Application.CLIENT_CONFIDENTIAL,
authorization_grant_type=Application.GRANT_PASSWORD,
)
self.application.save()

token_request_data = {
'grant_type': 'password',
'username': 'test_user',
'password': '123456'
}
auth_headers = self.get_basic_auth_header(urllib.quote_plus(self.application.client_id), urllib.quote_plus(self.application.client_secret))
response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
self.assertEqual(response.status_code, 200)

content = json.loads(response.content.decode("utf-8"))
access_token = content['access_token']

# use token to access the resource
auth_headers = {
'HTTP_AUTHORIZATION': 'Bearer ' + access_token,
}
request = self.factory.get("/fake-resource", **auth_headers)
request.user = self.test_user

view = ResourceView.as_view()
response = view(request)
self.assertEqual(response, "This is a protected resource")