Merge pull request #9 from juanifioren/v0.4.x

update to lates version
This commit is contained in:
Wojciech Bartosiak 2016-10-23 17:22:09 +02:00 committed by GitHub
commit 1e8352791d
11 changed files with 65 additions and 13 deletions

View file

@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
### [Unreleased] ### [Unreleased]
### [0.4.2] - 2016-10-13
##### Added
- Support for client redirect URIs with query strings.
##### Fixed
- Bug when generating secret_key value using admin.
##### Changed
- Client is available to OIDC_EXTRA_SCOPE_CLAIMS implementations via `self.client`.
- The constructor signature for `ScopeClaims` has changed, it now is called with the `Token` as its single argument.
### [0.4.1] - 2016-10-03 ### [0.4.1] - 2016-10-03
##### Changed ##### Changed

View file

@ -41,8 +41,8 @@ Add the provider urls::
Generate server RSA key and run migrations (if you don't):: Generate server RSA key and run migrations (if you don't)::
$ python manage.py creatersakey
$ python manage.py migrate $ python manage.py migrate
$ python manage.py creatersakey
Add required variables to your project settings:: Add required variables to your project settings::

View file

@ -96,6 +96,7 @@ Inside your oidc_provider_settings.py file add the following class::
# self.user - Django user instance. # self.user - Django user instance.
# self.userinfo - Dict returned by OIDC_USERINFO function. # self.userinfo - Dict returned by OIDC_USERINFO function.
# self.scopes - List of scopes requested. # self.scopes - List of scopes requested.
# self.client - Client requesting this claims.
dic = { dic = {
'bar': 'Something dynamic here', 'bar': 'Something dynamic here',
} }

View file

@ -14,10 +14,11 @@ STANDARD_CLAIMS = {
class ScopeClaims(object): class ScopeClaims(object):
def __init__(self, user, scopes): def __init__(self, token):
self.user = user self.user = token.user
self.userinfo = settings.get('OIDC_USERINFO', import_str=True)(STANDARD_CLAIMS, self.user) self.userinfo = settings.get('OIDC_USERINFO', import_str=True)(STANDARD_CLAIMS, self.user)
self.scopes = scopes self.scopes = token.scope
self.client = token.client
def create_response_dic(self): def create_response_dic(self):
""" """

View file

@ -43,7 +43,8 @@ class TokenEndpoint(object):
self.params['client_id'] = client_id self.params['client_id'] = client_id
self.params['client_secret'] = client_secret self.params['client_secret'] = client_secret
self.params['redirect_uri'] = unquote(self.request.POST.get('redirect_uri', '')) self.params['redirect_uri'] = unquote(
self.request.POST.get('redirect_uri', '').split('?', 1)[0])
self.params['grant_type'] = self.request.POST.get('grant_type', '') self.params['grant_type'] = self.request.POST.get('grant_type', '')
self.params['code'] = self.request.POST.get('code', '') self.params['code'] = self.request.POST.get('code', '')
self.params['state'] = self.request.POST.get('state', '') self.params['state'] = self.request.POST.get('state', '')

View file

@ -17,9 +17,7 @@ def cleanup_url_from_query_string(uri):
:type uri: str :type uri: str
:return: cleaned URI without query string :return: cleaned URI without query string
""" """
clean_uri = urlsplit(uri) clean_uri = urlsplit(uri)
# noinspection PyProtectedMember
clean_uri = urlunsplit(clean_uri._replace(query='')) clean_uri = urlunsplit(clean_uri._replace(query=''))
return clean_uri return clean_uri

View file

@ -1,16 +1,19 @@
import random import random
import string import string
try: try:
from urlparse import parse_qs, urlsplit from urlparse import parse_qs, urlsplit
except ImportError: except ImportError:
from urllib.parse import parse_qs, urlsplit from urllib.parse import parse_qs, urlsplit
from django.utils import timezone
from django.contrib.auth.models import User from django.contrib.auth.models import User
from oidc_provider.models import ( from oidc_provider.models import (
Client, Client,
Code, Code,
) Token)
FAKE_NONCE = 'cb584e44c43ed6bd0bc2d9c7e242837d' FAKE_NONCE = 'cb584e44c43ed6bd0bc2d9c7e242837d'
@ -58,6 +61,16 @@ def create_fake_client(response_type, is_public=False):
return client return client
def create_fake_token(user, scopes, client):
expires_at = timezone.now() + timezone.timedelta(seconds=60)
token = Token(user=user, client=client, expires_at=expires_at)
token.scope = scopes
token.save()
return token
def is_code_valid(url, user, client): def is_code_valid(url, user, client):
""" """
Check if the code inside the url is valid. Supporting both query string and fragment. Check if the code inside the url is valid. Supporting both query string and fragment.

View file

@ -1,6 +1,7 @@
from django.test import TestCase from django.test import TestCase
from oidc_provider.lib.claims import ScopeClaims from oidc_provider.lib.claims import ScopeClaims
from oidc_provider.tests.app.utils import create_fake_user from oidc_provider.tests.app.utils import create_fake_user, create_fake_client, create_fake_token
class ClaimsTestCase(TestCase): class ClaimsTestCase(TestCase):
@ -8,7 +9,9 @@ class ClaimsTestCase(TestCase):
def setUp(self): def setUp(self):
self.user = create_fake_user() self.user = create_fake_user()
self.scopes = ['openid', 'address', 'email', 'phone', 'profile'] self.scopes = ['openid', 'address', 'email', 'phone', 'profile']
self.scopeClaims = ScopeClaims(self.user, self.scopes) self.client = create_fake_client('code')
self.token = create_fake_token(self.user, self.scopes, self.client)
self.scopeClaims = ScopeClaims(self.token)
def test_clean_dic(self): def test_clean_dic(self):
""" assert that _clean_dic function returns a clean dictionnary """ assert that _clean_dic function returns a clean dictionnary

View file

@ -319,6 +319,29 @@ class TokenTestCase(TestCase):
False, False,
msg='Client authentication fails using HTTP Basic Auth.') msg='Client authentication fails using HTTP Basic Auth.')
def test_client_redirect_url(self):
"""
Validate that client redirect URIs with query strings match registered
URIs, and that unregistered URIs are rejected.
"""
SIGKEYS = self._get_keys()
code = self._create_code()
post_data = self._auth_code_post_data(code=code.code)
# Unregistered URI
post_data['redirect_uri'] = 'http://invalid.example.org'
response = self._post_request(post_data)
self.assertIn('invalid_client', response.content.decode('utf-8')),
# Registered URI contained a query string
post_data['redirect_uri'] = 'http://example.com/?client=OidcClient'
response = self._post_request(post_data)
self.assertNotIn('invalid_client', response.content.decode('utf-8')),
def test_access_token_contains_nonce(self): def test_access_token_contains_nonce(self):
""" """
If present in the Authentication Request, Authorization Servers MUST If present in the Authentication Request, Authorization Servers MUST

View file

@ -162,11 +162,11 @@ def userinfo(request, *args, **kwargs):
'sub': token.id_token.get('sub'), 'sub': token.id_token.get('sub'),
} }
standard_claims = StandardScopeClaims(token.user, token.scope) standard_claims = StandardScopeClaims(token)
dic.update(standard_claims.create_response_dic()) dic.update(standard_claims.create_response_dic())
if settings.get('OIDC_EXTRA_SCOPE_CLAIMS'): if settings.get('OIDC_EXTRA_SCOPE_CLAIMS'):
extra_claims = settings.get('OIDC_EXTRA_SCOPE_CLAIMS', import_str=True)(token.user, token.scope) extra_claims = settings.get('OIDC_EXTRA_SCOPE_CLAIMS', import_str=True)(token)
dic.update(extra_claims.create_response_dic()) dic.update(extra_claims.create_response_dic())
response = JsonResponse(dic, status=200) response = JsonResponse(dic, status=200)

View file

@ -7,7 +7,7 @@ os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
setup( setup(
name='django-oidc-provider', name='django-oidc-provider',
version='0.4.1', version='0.4.2',
packages=[ packages=[
'oidc_provider', 'oidc_provider/lib', 'oidc_provider/lib/endpoints', 'oidc_provider', 'oidc_provider/lib', 'oidc_provider/lib/endpoints',
'oidc_provider/lib/utils', 'oidc_provider/tests', 'oidc_provider/tests/app', 'oidc_provider/lib/utils', 'oidc_provider/tests', 'oidc_provider/tests/app',