django-oidc-provider/oidc_provider/lib/endpoints/authorize.py

182 lines
6.1 KiB
Python
Raw Normal View History

from datetime import timedelta
2015-06-08 19:36:49 +00:00
import logging
from django.utils import timezone
2015-02-18 18:07:22 +00:00
from oidc_provider.lib.errors import *
from oidc_provider.lib.utils.params import *
from oidc_provider.lib.utils.token import *
from oidc_provider.models import *
2015-01-08 20:55:24 +00:00
2015-06-19 20:46:00 +00:00
2015-06-08 19:36:49 +00:00
logger = logging.getLogger(__name__)
2015-01-08 20:55:24 +00:00
class AuthorizeEndpoint(object):
def __init__(self, request):
self.request = request
self.params = Params()
2015-01-08 20:55:24 +00:00
# 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)
2015-01-08 20:55:24 +00:00
self._extract_params()
# Determine which flow to use.
if self.params.response_type in ['code']:
self.grant_type = 'authorization_code'
elif self.params.response_type in ['id_token', 'id_token token']:
self.grant_type = 'implicit'
self._extract_implicit_params()
else:
self.grant_type = None
def _extract_params(self):
"""
2015-01-08 20:55:24 +00:00
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
"""
2015-01-08 20:55:24 +00:00
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', '')
self.params.scope = self.query_dict.get('scope', '').split()
2015-01-08 20:55:24 +00:00
self.params.state = self.query_dict.get('state', '')
def _extract_implicit_params(self):
"""
2015-01-08 20:55:24 +00:00
Get specific params used by the Implicit Flow.
See: http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthRequest
"""
2015-01-08 20:55:24 +00:00
self.params.nonce = self.query_dict.get('nonce', '')
def validate_params(self):
if not self.params.redirect_uri:
2015-06-19 20:46:00 +00:00
logger.error('[Authorize] Missing redirect uri.')
2015-01-08 20:55:24 +00:00
raise RedirectUriError()
if not ('openid' in self.params.scope):
2015-06-19 20:46:00 +00:00
logger.error('[Authorize] Missing openid scope.')
raise AuthorizeError(
self.params.redirect_uri,
'invalid_scope',
self.grant_type)
2015-01-08 20:55:24 +00:00
try:
self.client = Client.objects.get(client_id=self.params.client_id)
if not (self.params.redirect_uri in self.client.redirect_uris):
2015-06-19 20:46:00 +00:00
logger.error('[Authorize] Invalid redirect uri: %s', self.params.redirect_uri)
2015-01-08 20:55:24 +00:00
raise RedirectUriError()
if not self.grant_type or not (self.params.response_type == self.client.response_type):
2015-06-19 20:46:00 +00:00
logger.error('[Authorize] Invalid response type: %s', self.params.response_type)
raise AuthorizeError(
self.params.redirect_uri,
'unsupported_response_type',
self.grant_type)
2015-01-08 20:55:24 +00:00
except Client.DoesNotExist:
2015-06-19 20:46:00 +00:00
logger.error('[Authorize] Invalid client identifier: %s', self.params.client_id)
2015-01-08 20:55:24 +00:00
raise ClientIdError()
2015-06-15 19:04:44 +00:00
def create_response_uri(self):
2015-01-08 20:55:24 +00:00
try:
if self.grant_type == 'authorization_code':
code = create_code(
user=self.request.user,
client=self.client,
scope=self.params.scope)
2015-01-08 20:55:24 +00:00
code.save()
# Create the response uri.
2015-01-08 20:55:24 +00:00
uri = self.params.redirect_uri + '?code={0}'.format(code.code)
elif self.grant_type == 'implicit':
2015-04-17 22:39:55 +00:00
id_token_dic = create_id_token(
user=self.request.user,
aud=self.client.client_id)
2015-01-08 20:55:24 +00:00
token = create_token(
user=self.request.user,
client=self.client,
id_token_dic=id_token_dic,
scope=self.params.scope)
# Store the token.
token.save()
id_token = encode_id_token(
id_token_dic, self.client.client_secret)
# Create the response uri.
uri = self.params.redirect_uri + \
'#token_type={0}&id_token={1}&expires_in={2}'.format(
'bearer',
id_token,
60 * 10,
)
# Check if response_type is 'id_token token' then
2015-01-08 20:55:24 +00:00
# add access_token to the fragment.
if self.params.response_type == 'id_token token':
uri += '&access_token={0}'.format(token.access_token)
2015-06-19 20:46:00 +00:00
except Exception as error:
logger.error('[Authorize] Error when trying to create response uri: %s', error)
raise AuthorizeError(
self.params.redirect_uri,
'server_error',
self.grant_type)
2015-01-08 20:55:24 +00:00
# Add state if present.
uri += ('&state={0}'.format(self.params.state) if self.params.state else '')
2015-01-08 20:55:24 +00:00
return uri
def set_client_user_consent(self):
"""
Save the user consent given to a specific client.
Return None.
"""
expires_at = timezone.now() + timedelta(
days=settings.get('OIDC_USER_CONSENT_EXPIRE'))
uc, created = UserConsent.objects.get_or_create(
user=self.request.user,
client=self.client,
defaults={'expires_at': expires_at})
uc.scope = self.params.scope
# Rewrite expires_at if object already exists.
if not created:
uc.expires_at = expires_at
uc.save()
def client_has_user_consent(self):
"""
Check if already exists user consent for some client.
Return bool.
"""
value = False
try:
uc = UserConsent.objects.get(user=self.request.user,
client=self.client)
if (set(self.params.scope).issubset(uc.scope)) and \
not (uc.has_expired()):
value = True
except UserConsent.DoesNotExist:
pass
return value