2017-05-05 03:19:57 +00:00
|
|
|
from hashlib import sha224
|
|
|
|
|
2017-08-10 09:38:50 +00:00
|
|
|
import django
|
2018-03-23 18:46:12 +00:00
|
|
|
from django.http import HttpResponse
|
2018-06-19 16:09:45 +00:00
|
|
|
from django.utils.cache import patch_vary_headers
|
2018-03-23 18:46:12 +00:00
|
|
|
|
|
|
|
from oidc_provider import settings
|
|
|
|
|
2017-08-10 09:38:50 +00:00
|
|
|
|
|
|
|
if django.VERSION >= (1, 11):
|
|
|
|
from django.urls import reverse
|
|
|
|
else:
|
|
|
|
from django.core.urlresolvers import reverse
|
|
|
|
|
2016-10-04 17:32:54 +00:00
|
|
|
|
2015-11-12 20:12:18 +00:00
|
|
|
def redirect(uri):
|
|
|
|
"""
|
|
|
|
Custom Response object for redirecting to a Non-HTTP url scheme.
|
|
|
|
"""
|
|
|
|
response = HttpResponse('', status=302)
|
|
|
|
response['Location'] = uri
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
2016-05-25 21:58:58 +00:00
|
|
|
def get_site_url(site_url=None, request=None):
|
|
|
|
"""
|
|
|
|
Construct the site url.
|
|
|
|
|
|
|
|
Orders to decide site url:
|
|
|
|
1. valid `site_url` parameter
|
|
|
|
2. valid `SITE_URL` in settings
|
|
|
|
3. construct from `request` object
|
|
|
|
"""
|
|
|
|
site_url = site_url or settings.get('SITE_URL')
|
|
|
|
if site_url:
|
|
|
|
return site_url
|
|
|
|
elif request:
|
|
|
|
return '{}://{}'.format(request.scheme, request.get_host())
|
|
|
|
else:
|
|
|
|
raise Exception('Either pass `site_url`, '
|
|
|
|
'or set `SITE_URL` in settings, '
|
|
|
|
'or pass `request` object.')
|
|
|
|
|
2017-05-05 03:19:57 +00:00
|
|
|
|
2016-05-25 21:58:58 +00:00
|
|
|
def get_issuer(site_url=None, request=None):
|
2015-07-13 20:36:15 +00:00
|
|
|
"""
|
|
|
|
Construct the issuer full url. Basically is the site url with some path
|
|
|
|
appended.
|
|
|
|
"""
|
2016-05-25 21:58:58 +00:00
|
|
|
site_url = get_site_url(site_url=site_url, request=request)
|
2016-11-01 15:15:48 +00:00
|
|
|
path = reverse('oidc_provider:provider-info') \
|
2016-01-16 10:35:26 +00:00
|
|
|
.split('/.well-known/openid-configuration')[0]
|
2015-07-13 20:36:15 +00:00
|
|
|
issuer = site_url + path
|
2015-03-04 19:24:41 +00:00
|
|
|
|
2016-09-21 13:20:03 +00:00
|
|
|
return str(issuer)
|
2015-07-13 20:36:15 +00:00
|
|
|
|
|
|
|
|
2016-07-07 15:50:27 +00:00
|
|
|
def default_userinfo(claims, user):
|
2016-01-12 18:17:22 +00:00
|
|
|
"""
|
2016-07-07 15:50:27 +00:00
|
|
|
Default function for setting OIDC_USERINFO.
|
|
|
|
`claims` is a dict that contains all the OIDC standard claims.
|
2016-01-12 18:17:22 +00:00
|
|
|
"""
|
2016-07-07 15:50:27 +00:00
|
|
|
return claims
|
2016-01-12 18:17:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
def default_sub_generator(user):
|
|
|
|
"""
|
|
|
|
Default function for setting OIDC_IDTOKEN_SUB_GENERATOR.
|
|
|
|
"""
|
|
|
|
return str(user.id)
|
2016-01-19 20:37:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
def default_after_userlogin_hook(request, user, client):
|
|
|
|
"""
|
|
|
|
Default function for setting OIDC_AFTER_USERLOGIN_HOOK.
|
|
|
|
"""
|
|
|
|
return None
|
2016-02-12 16:02:35 +00:00
|
|
|
|
2017-05-05 03:19:57 +00:00
|
|
|
|
2017-08-08 22:41:42 +00:00
|
|
|
def default_after_end_session_hook(
|
2018-03-23 18:46:12 +00:00
|
|
|
request, id_token=None, post_logout_redirect_uri=None,
|
|
|
|
state=None, client=None, next_page=None):
|
2017-05-05 03:19:57 +00:00
|
|
|
"""
|
|
|
|
Default function for setting OIDC_AFTER_END_SESSION_HOOK.
|
|
|
|
|
|
|
|
:param request: Django request object
|
|
|
|
:type request: django.http.HttpRequest
|
|
|
|
|
2018-03-23 18:46:12 +00:00
|
|
|
:param id_token: token passed by `id_token_hint` url query param.
|
|
|
|
Do NOT trust this param or validate token
|
2017-05-05 03:19:57 +00:00
|
|
|
:type id_token: str
|
|
|
|
|
2018-03-23 18:46:12 +00:00
|
|
|
:param post_logout_redirect_uri: redirect url from url query param.
|
|
|
|
Do NOT trust this param
|
2017-05-05 03:19:57 +00:00
|
|
|
:type post_logout_redirect_uri: str
|
|
|
|
|
|
|
|
:param state: state param from url query params
|
|
|
|
:type state: str
|
|
|
|
|
2017-08-08 22:41:42 +00:00
|
|
|
:param client: If id_token has `aud` param and associated Client exists,
|
|
|
|
this is an instance of it - do NOT trust this param
|
2017-05-05 03:19:57 +00:00
|
|
|
:type client: oidc_provider.models.Client
|
|
|
|
|
|
|
|
:param next_page: calculated next_page redirection target
|
|
|
|
:type next_page: str
|
|
|
|
:return:
|
|
|
|
"""
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
2018-05-23 21:24:52 +00:00
|
|
|
def default_idtoken_processing_hook(
|
2018-05-31 07:23:58 +00:00
|
|
|
id_token, user, token, request, **kwargs):
|
2016-02-12 16:02:35 +00:00
|
|
|
"""
|
2018-06-04 07:56:31 +00:00
|
|
|
Hook to perform some additional actions to `id_token` dictionary just before serialization.
|
2016-02-12 16:02:35 +00:00
|
|
|
|
|
|
|
:param id_token: dictionary contains values that going to be serialized into `id_token`
|
|
|
|
:type id_token: dict
|
2016-02-25 13:10:07 +00:00
|
|
|
|
2016-02-25 09:46:10 +00:00
|
|
|
:param user: user for whom id_token is generated
|
|
|
|
:type user: User
|
2016-02-25 13:10:07 +00:00
|
|
|
|
2018-05-23 21:24:52 +00:00
|
|
|
:param token: the Token object created for the authentication request
|
|
|
|
:type token: oidc_provider.models.Token
|
|
|
|
|
|
|
|
:param request: the request initiating this ID token processing
|
|
|
|
:type request: django.http.HttpRequest
|
|
|
|
|
2016-02-12 16:02:35 +00:00
|
|
|
:return: custom modified dictionary of values for `id_token`
|
2018-05-23 21:24:52 +00:00
|
|
|
:rtype: dict
|
2016-02-12 16:02:35 +00:00
|
|
|
"""
|
|
|
|
return id_token
|
2017-05-05 03:19:57 +00:00
|
|
|
|
|
|
|
|
2018-04-23 13:59:56 +00:00
|
|
|
def default_introspection_processing_hook(introspection_response, client, id_token):
|
2018-02-05 15:29:08 +00:00
|
|
|
"""
|
|
|
|
Hook to customise the returned data from the token introspection endpoint
|
|
|
|
:param introspection_response:
|
2018-04-23 13:59:56 +00:00
|
|
|
:param client:
|
2018-02-05 15:29:08 +00:00
|
|
|
:param id_token:
|
|
|
|
:return:
|
|
|
|
"""
|
|
|
|
return introspection_response
|
|
|
|
|
|
|
|
|
2017-05-05 03:19:57 +00:00
|
|
|
def get_browser_state_or_default(request):
|
|
|
|
"""
|
|
|
|
Determine value to use as session state.
|
|
|
|
"""
|
2018-03-23 18:46:12 +00:00
|
|
|
key = (request.session.session_key or
|
|
|
|
settings.get('OIDC_UNAUTHENTICATED_SESSION_MANAGEMENT_KEY'))
|
2017-05-05 03:19:57 +00:00
|
|
|
return sha224(key.encode('utf-8')).hexdigest()
|
2018-02-05 15:29:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
def run_processing_hook(subject, hook_settings_name, **kwargs):
|
2018-05-23 21:16:26 +00:00
|
|
|
processing_hooks = settings.get(hook_settings_name)
|
|
|
|
if not isinstance(processing_hooks, (list, tuple)):
|
|
|
|
processing_hooks = [processing_hooks]
|
|
|
|
|
|
|
|
for hook_string in processing_hooks:
|
|
|
|
hook = settings.import_from_str(hook_string)
|
|
|
|
subject = hook(subject, **kwargs)
|
|
|
|
|
2018-02-05 15:29:08 +00:00
|
|
|
return subject
|
2018-06-19 16:09:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
def cors_allow_any(request, response):
|
|
|
|
"""
|
|
|
|
Add headers to permit CORS requests from any origin, with or without credentials,
|
|
|
|
with any headers.
|
|
|
|
"""
|
|
|
|
origin = request.META.get('HTTP_ORIGIN')
|
|
|
|
if not origin:
|
|
|
|
return response
|
|
|
|
|
|
|
|
# From the CORS spec: The string "*" cannot be used for a resource that supports credentials.
|
|
|
|
response['Access-Control-Allow-Origin'] = origin
|
|
|
|
patch_vary_headers(response, ['Origin'])
|
|
|
|
response['Access-Control-Allow-Credentials'] = 'true'
|
|
|
|
|
|
|
|
if request.method == 'OPTIONS':
|
|
|
|
if 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS' in request.META:
|
|
|
|
response['Access-Control-Allow-Headers'] \
|
|
|
|
= request.META['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']
|
|
|
|
response['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
|
|
|
|
|
|
|
|
return response
|