Pull request PEP8 compliant from nicchub:master.

This commit is contained in:
juanifioren 2015-01-28 15:19:36 -03:00
parent c323b0829b
commit be741e79e3
11 changed files with 125 additions and 71 deletions

View file

@ -50,6 +50,8 @@ Add the provider urls.
Settings
********
Add required variables to your project settings.
.. code:: python
# REQUIRED. Your server provider url.

View file

@ -1,10 +1,13 @@
import uuid
from datetime import timedelta
from django.utils import timezone
from openid_provider.lib.errors import *
from openid_provider.lib.utils.params import *
from openid_provider.lib.utils.token import *
from openid_provider.models import *
import uuid
class AuthorizeEndpoint(object):
@ -17,8 +20,7 @@ class AuthorizeEndpoint(object):
# Because in this endpoint we handle both GET
# and POST request.
self.query_dict = (self.request.POST if self.request.method == 'POST'
else self.request.GET)
self.query_dict = (self.request.POST if self.request.method == 'POST' else self.request.GET)
self._extract_params()
@ -32,12 +34,12 @@ class AuthorizeEndpoint(object):
self.grant_type = None
def _extract_params(self):
'''
"""
Get all the params used by the Authorization Code Flow
(and also for the Implicit).
See: http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
'''
"""
self.params.client_id = self.query_dict.get('client_id', '')
self.params.redirect_uri = self.query_dict.get('redirect_uri', '')
self.params.response_type = self.query_dict.get('response_type', '')
@ -45,11 +47,11 @@ class AuthorizeEndpoint(object):
self.params.state = self.query_dict.get('state', '')
def _extract_implicit_params(self):
'''
"""
Get specific params used by the Implicit Flow.
See: http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthRequest
'''
"""
self.params.nonce = self.query_dict.get('nonce', '')
def validate_params(self):
@ -69,8 +71,7 @@ class AuthorizeEndpoint(object):
if not (self.params.redirect_uri in self.client.redirect_uris):
raise RedirectUriError()
if not (self.grant_type) or \
not (self.params.response_type == self.client.response_type):
if not self.grant_type or not (self.params.response_type == self.client.response_type):
raise AuthorizeError(
self.params.redirect_uri,
@ -91,23 +92,23 @@ class AuthorizeEndpoint(object):
try:
self.validate_params()
if (self.grant_type == 'authorization_code'):
if self.grant_type == 'authorization_code':
code = Code()
code.user = self.request.user
code.client = self.client
code.code = uuid.uuid4().hex
code.expires_at = timezone.now() + timedelta(seconds=60*10) # TODO: Add this into settings.
code.expires_at = timezone.now() + timedelta(seconds=60*10) # TODO: Add this into settings.
code.scope = self.params.scope
code.save()
uri = self.params.redirect_uri + '?code={0}'.format(code.code)
else: # Implicit Flow
else: # Implicit Flow
id_token_dic = create_id_token_dic(
self.request.user,
'http://localhost:8000', # TODO: Add this into settings.
'http://localhost:8000', # TODO: Add this into settings.
self.client.client_id)
token = create_token(
@ -123,11 +124,11 @@ class AuthorizeEndpoint(object):
# TODO: Check if response_type is 'id_token token' then
# add access_token to the fragment.
uri = self.params.redirect_uri + \
'#token_type={0}&id_token={1}&expires_in={2}'.format(
'bearer',
id_token,
60*10)
uri = self.params.redirect_uri + '#token_type={0}&id_token={1}&expires_in={2}'.format(
'bearer',
id_token,
60*10
)
except:
raise AuthorizeError(
self.params.redirect_uri,
@ -135,7 +136,6 @@ class AuthorizeEndpoint(object):
self.grant_type)
# Add state if present.
uri = uri + ('&state={0}'.format(self.params.state)
if self.params.state else '')
uri = uri + ('&state={0}'.format(self.params.state) if self.params.state else '')
return uri

View file

@ -1,10 +1,12 @@
import urllib
from django.http import JsonResponse
from openid_provider.lib.errors import *
from openid_provider.lib.utils.params import *
from openid_provider.lib.utils.token import *
from openid_provider.models import *
from openid_provider import settings
import urllib
class TokenEndpoint(object):
@ -54,15 +56,15 @@ class TokenEndpoint(object):
def create_response_dic(self):
id_token_dic = create_id_token_dic(
self.code.user,
settings.get('SITE_URL'),
self.client.client_id)
self.code.user,
settings.get('SITE_URL'),
self.client.client_id)
token = create_token(
user=self.code.user,
client=self.code.client,
id_token_dic=id_token_dic,
scope=self.code.scope)
user=self.code.user,
client=self.code.client,
id_token_dic=id_token_dic,
scope=self.code.scope)
# Store the token.
token.save()
@ -75,7 +77,7 @@ class TokenEndpoint(object):
dic = {
'access_token': token.access_token,
'token_type': 'bearer',
'expires_in': 60*60, # TODO: Add this into settings.
'expires_in': 60*60, # TODO: Add this into settings.
'id_token': id_token,
}
@ -83,9 +85,9 @@ class TokenEndpoint(object):
@classmethod
def response(self, dic, status=200):
'''
"""
Create and return a response object.
'''
"""
response = JsonResponse(dic, status=status)
response['Cache-Control'] = 'no-store'
response['Pragma'] = 'no-cache'

View file

@ -1,9 +1,11 @@
import re
from django.http import HttpResponse, JsonResponse
from openid_provider.lib.errors import *
from openid_provider.lib.scopes import *
from openid_provider.lib.utils.params import *
from openid_provider.models import *
import re
class UserInfoEndpoint(object):
@ -21,12 +23,12 @@ class UserInfoEndpoint(object):
self.params.access_token = self._get_access_token()
def _get_access_token(self):
'''
"""
Get the access token using Authorization Request Header Field method.
See: http://tools.ietf.org/html/rfc6750#section-2.1
Return a string.
'''
"""
auth_header = self.request.META.get('HTTP_AUTHORIZATION', '')
if re.compile('^Bearer\s{1}.+$').match(auth_header):
@ -45,12 +47,12 @@ class UserInfoEndpoint(object):
raise UserInfoError('invalid_token')
def create_response_dic(self):
'''
"""
Create a diccionary with all the requested claims about the End-User.
See: http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
Return a diccionary.
'''
"""
dic = {
'sub': self.token.id_token.get('sub'),
}

View file

@ -6,33 +6,52 @@ class RedirectUriError(Exception):
error = 'Redirect URI Error'
description = 'The request fails due to a missing, invalid, or mismatching redirection URI (redirect_uri).'
class ClientIdError(Exception):
error = 'Client ID Error'
description = 'The client identifier (client_id) is missing or invalid.'
class AuthorizeError(Exception):
_errors = {
# Oauth2 errors.
# https://tools.ietf.org/html/rfc6749#section-4.1.2.1
'invalid_request': 'The request is otherwise malformed',
'unauthorized_client': 'The client is not authorized to request an authorization code using this method',
'access_denied': 'The resource owner or authorization server denied the request',
'unsupported_response_type': 'The authorization server does not support obtaining an authorization code using this method',
'unsupported_response_type': 'The authorization server does not support obtaining an authorization code using '
'this method',
'invalid_scope': 'The requested scope is invalid, unknown, or malformed',
'server_error': 'The authorization server encountered an error',
'temporarily_unavailable': 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server',
'temporarily_unavailable': 'The authorization server is currently unable to handle the request due to a '
'temporary overloading or maintenance of the server',
# OpenID errors.
# http://openid.net/specs/openid-connect-core-1_0.html#AuthError
'interaction_required': 'The Authorization Server requires End-User interaction of some form to proceed',
'login_required': 'The Authorization Server requires End-User authentication',
'account_selection_required': 'The End-User is required to select a session at the Authorization Server',
'consent_required': 'The Authorization Server requires End-User consent',
'invalid_request_uri': 'The request_uri in the Authorization Request returns an error or contains invalid data',
'invalid_request_object': 'The request parameter contains an invalid Request Object',
'request_not_supported': 'The provider does not support use of the request parameter',
'request_uri_not_supported': 'The provider does not support use of the request_uri parameter',
'registration_not_supported': 'The provider does not support use of the registration parameter',
}
@ -65,17 +84,26 @@ class AuthorizeError(Exception):
def response(self):
pass
class TokenError(Exception):
_errors = {
# Oauth2 errors.
# https://tools.ietf.org/html/rfc6749#section-5.2
'invalid_request': 'The request is otherwise malformed',
'invalid_client': 'Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)',
'invalid_grant': 'The provided authorization grant or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client',
'invalid_client': 'Client authentication failed (e.g., unknown client, no client authentication included, '
'or unsupported authentication method)',
'invalid_grant': 'The provided authorization grant or refresh token is invalid, expired, revoked, does not '
'match the redirection URI used in the authorization request, or was issued to another client',
'unauthorized_client': 'The authenticated client is not authorized to use this authorization grant type',
'unsupported_grant_type': 'The authorization grant type is not supported by the authorization server',
'invalid_scope': 'The requested scope is invalid, unknown, malformed, or exceeds the scope granted by the resource owner',
'invalid_scope': 'The requested scope is invalid, unknown, malformed, or exceeds the scope granted by the '
'resource owner',
}
def __init__(self, error):
@ -92,14 +120,20 @@ class TokenError(Exception):
return dic
class UserInfoError(Exception):
class UserInfoError(Exception):
_errors = {
# Oauth2 errors.
# https://tools.ietf.org/html/rfc6750#section-3.1
'invalid_request': ('The request is otherwise malformed', 400),
'invalid_token': ('The access token provided is expired, revoked, malformed, or invalid for other reasons', 401),
'insufficient_scope': ('The request requires higher privileges than provided by the access token', 403),
'invalid_request': (
'The request is otherwise malformed', 400
),
'invalid_token': (
'The access token provided is expired, revoked, malformed, or invalid for other reasons', 401
),
'insufficient_scope': (
'The request requires higher privileges than provided by the access token', 403
),
}
def __init__(self, code):

View file

@ -1,4 +1,5 @@
from django.utils.translation import ugettext as _
from openid_provider.models import UserInfo
@ -32,10 +33,10 @@ class StandardClaims(object):
return dic
def _scopes_registered(self):
'''
"""
Return a list that contains all the scopes registered
in the class.
'''
"""
scopes = []
for name in self.__class__.__dict__:
@ -47,9 +48,9 @@ class StandardClaims(object):
return scopes
def _clean_dic(self, dic):
'''
"""
Clean recursively all empty or None values inside a dict.
'''
"""
aux_dic = dic.copy()
for key, value in dic.iteritems():

View file

@ -1,7 +1,7 @@
class Params(object):
'''
"""
The purpose of this class is for accesing params via dot notation.
'''
"""
pass

View file

@ -1,19 +1,21 @@
from datetime import timedelta
from django.utils import timezone
import jwt
from openid_provider.models import *
import time
import jwt
import uuid
from datetime import timedelta
from django.utils import timezone
from openid_provider.models import *
def create_id_token_dic(user, iss, aud):
'''
"""
Receives a user object, iss (issuer) and aud (audience).
Then creates the id_token dic.
See: http://openid.net/specs/openid-connect-core-1_0.html#IDToken
Return a dic.
'''
"""
expires_in = 60*10
now = timezone.now()
@ -34,22 +36,24 @@ def create_id_token_dic(user, iss, aud):
return dic
def encode_id_token(id_token_dic, client_secret):
'''
"""
Represent the ID Token as a JSON Web Token (JWT).
Return a hash.
'''
"""
id_token_hash = jwt.encode(id_token_dic, client_secret)
return id_token_hash
def create_token(user, client, id_token_dic, scope):
'''
"""
Create and populate a Token object.
Return a Token object.
'''
"""
token = Token()
token.user = user
token.client = client
@ -58,7 +62,7 @@ def create_token(user, client, id_token_dic, scope):
token.id_token = id_token_dic
token.refresh_token = uuid.uuid4().hex
token.expires_at = timezone.now() + timedelta(seconds=60*60) # TODO: Add this into settings.
token.expires_at = timezone.now() + timedelta(seconds=60*60) # TODO: Add this into settings.
token.scope = scope
return token

View file

@ -1,7 +1,8 @@
from django.contrib.auth.models import User
import json
from django.db import models
from django.utils import timezone
import json
from django.contrib.auth.models import User
class Client(models.Model):
@ -18,6 +19,7 @@ class Client(models.Model):
response_type = models.CharField(max_length=30, choices=RESPONSE_TYPE_CHOICES)
_redirect_uris = models.TextField(default='')
def redirect_uris():
def fget(self):
return self._redirect_uris.splitlines()
@ -30,6 +32,7 @@ class Client(models.Model):
def default_redirect_uri(self):
return self.redirect_uris[0] if self.redirect_uris else ''
class Code(models.Model):
user = models.ForeignKey(User)
@ -38,6 +41,7 @@ class Code(models.Model):
expires_at = models.DateTimeField()
_scope = models.TextField(default='')
def scope():
def fget(self):
return self._scope.split()
@ -49,6 +53,7 @@ class Code(models.Model):
def has_expired(self):
return timezone.now() >= self.expires_at
class Token(models.Model):
user = models.ForeignKey(User)
@ -57,6 +62,7 @@ class Token(models.Model):
expires_at = models.DateTimeField()
_scope = models.TextField(default='')
def scope():
def fget(self):
return self._scope.split()
@ -66,6 +72,7 @@ class Token(models.Model):
scope = property(**scope())
_id_token = models.TextField()
def id_token():
def fget(self):
return json.loads(self._id_token)
@ -74,6 +81,7 @@ class Token(models.Model):
return locals()
id_token = property(**id_token())
class UserInfo(models.Model):
user = models.OneToOneField(User, primary_key=True)

View file

@ -1,12 +1,12 @@
from django.conf.urls import patterns, include, url
from django.views.decorators.csrf import csrf_exempt
from openid_provider.views import *
urlpatterns = patterns('',
url(r'^authorize/$', AuthorizeView.as_view(), name='authorize'),
url(r'^token/$', csrf_exempt(TokenView.as_view()), name='token'),
url(r'^userinfo/$', csrf_exempt(userinfo), name='userinfo'),
url(r'^authorize/$', AuthorizeView.as_view(), name='authorize'),
url(r'^token/$', csrf_exempt(TokenView.as_view()), name='token'),
url(r'^userinfo/$', csrf_exempt(userinfo), name='userinfo'),
)

View file

@ -5,7 +5,7 @@ from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import render
from django.views.decorators.http import require_http_methods
from django.views.generic import View
import urllib
from openid_provider.lib.errors import *
from openid_provider.lib.endpoints.authorize import *
from openid_provider.lib.endpoints.token import *
@ -69,6 +69,7 @@ class AuthorizeView(View):
return HttpResponseRedirect(uri)
class TokenView(View):
def post(self, request, *args, **kwargs):