Browse Source

DIV-1136: Add local keycloak sign in support.

pull/172/head
Steven Ly 5 years ago
committed by Michael Olund
parent
commit
e8d7d59707
12 changed files with 2191 additions and 23 deletions
  1. +11
    -1
      .env.example
  2. +2105
    -0
      conf/keycloak/realm-export.json
  3. +15
    -0
      docker-compose.yml
  4. +10
    -0
      edivorce/apps/core/middleware/keycloak.py
  5. +1
    -1
      edivorce/apps/core/templates/base.html
  6. +1
    -1
      edivorce/apps/core/templates/intro.html
  7. +1
    -1
      edivorce/apps/core/templates/localdev/register.html
  8. +5
    -4
      edivorce/apps/core/views/main.py
  9. +2
    -1
      edivorce/apps/core/views/pdf.py
  10. +6
    -5
      edivorce/apps/poc/urls.py
  11. +32
    -9
      edivorce/settings/base.py
  12. +2
    -0
      edivorce/urls.py

+ 11
- 1
.env.example View File

@ -26,4 +26,14 @@ EFILING_HUB_CLIENT_SECRET=''
EFILING_HUB_API_BASE_URL=''
# BCE ID test accounts for localdev
EFILING_BCEID=
EFILING_BCEID=
# Keycloak settings
OIDC_OP_JWKS_ENDPOINT=
OIDC_RP_CLIENT_ID=
OIDC_RP_CLIENT_SECRET=
OIDC_OP_AUTHORIZATION_ENDPOINT=
OIDC_OP_TOKEN_ENDPOINT=
OIDC_OP_USER_ENDPOINT=
LOGIN_REDIRECT_URL=
LOGOUT_REDIRECT_URL=

+ 2105
- 0
conf/keycloak/realm-export.json
File diff suppressed because it is too large
View File


+ 15
- 0
docker-compose.yml View File

@ -43,5 +43,20 @@ services:
- "5005:5001"
restart: always
# Keycloak
keycloak:
container_name: edivorce-keycloak
image: jboss/keycloak:9.0.3
environment:
DB_VENDOR: H2
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: admin
KEYCLOAK_IMPORT: /tmp/realm-export.json
volumes:
- ./conf/keycloak/realm-export.json:/tmp/realm-export.json
ports:
- 8081:8080
command: ["-Dkeycloak.profile.feature.upload_scripts=enabled"]
volumes:
data-redis:

+ 10
- 0
edivorce/apps/core/middleware/keycloak.py View File

@ -0,0 +1,10 @@
from mozilla_django_oidc.auth import OIDCAuthenticationBackend
class EDivorceKeycloakBackend(OIDCAuthenticationBackend):
def verify_claims(self, claims):
verified = super(EDivorceKeycloakBackend, self).verify_claims(claims)
print(claims)
return verified

+ 1
- 1
edivorce/apps/core/templates/base.html View File

@ -55,7 +55,7 @@
{% if request.user.is_authenticated %}
<span>
{{ request.user.display_name}}
&nbsp;&nbsp;|&nbsp;&nbsp; <a href="{% url 'logout' %}">Log out</a>
&nbsp;&nbsp;|&nbsp;&nbsp; <a href="{% url 'oidc_logout' %}">Log out</a>
</span>
{% endif %}
</div>


+ 1
- 1
edivorce/apps/core/templates/intro.html View File

@ -51,7 +51,7 @@
<h3>
Already started completing forms online and want to pick up where you left off?
</h3>
<a href="{% url 'login' %}" class="btn btn-primary btn-lg">Returning users</a>
<a href="{% url 'oidc_authentication_init' %}" class="btn btn-primary btn-lg">Returning users</a>
</div>
</div>
{% endblock %}


+ 1
- 1
edivorce/apps/core/templates/localdev/register.html View File

@ -10,7 +10,7 @@
<p>Enter <strong>any user id</strong> with the password <em><strong>divorce</strong></em> to
simulate a login in your localdev envirommnent.</p>
<a href="{% url 'login' %}">Goto Login</a>
<a href="{% url 'oidc_authentication_init' %}">Goto Login</a>
</body>

+ 5
- 4
edivorce/apps/core/views/main.py View File

@ -4,6 +4,7 @@ from django.conf import settings
from django.shortcuts import render, redirect
from django.urls import reverse
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from edivorce.apps.core.utils.derived import get_derived_data
from ..decorators import bceid_required, intercept, prequal_completed
@ -164,7 +165,7 @@ def logout(request):
return response
@bceid_required
@login_required
@prequal_completed
@intercept
def overview(request):
@ -192,7 +193,7 @@ def overview(request):
return response
@bceid_required
@login_required
@prequal_completed
def dashboard_nav(request, nav_step):
"""
@ -212,7 +213,7 @@ def dashboard_nav(request, nav_step):
return render(request, template_name=template_name, context=responses_dict)
@bceid_required
@login_required
@prequal_completed
def submit_initial_files(request):
return _submit_files(request, initial=True)
@ -309,7 +310,7 @@ def contact(request):
return render(request, 'contact-us.html', context={'active_page': 'contact'})
@bceid_required
@login_required
def intercept_page(request):
"""
On intercept, show the Orders page to get the requested orders before the


+ 2
- 1
edivorce/apps/core/views/pdf.py View File

@ -5,6 +5,7 @@ import json
from django.conf import settings
from django.http import HttpResponse
from django.template.loader import render_to_string
from django.contrib.auth.decorators import login_required
import requests
@ -16,7 +17,7 @@ from ..utils.user_response import get_data_for_user
EXHIBITS = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ'[::-1])
@bceid_required
@login_required
def form(request, form_number):
""" View for rendering PDF's and previews """


+ 6
- 5
edivorce/apps/poc/urls.py View File

@ -1,12 +1,13 @@
from django.conf.urls import url
from django.contrib.auth.decorators import login_required
from edivorce.apps.poc import views
from ..core.decorators import bceid_required
urlpatterns = [
url(r'scan', bceid_required(views.UploadScan.as_view()), name="poc-scan"),
url(r'hub', bceid_required(views.EfilingHubUpload.as_view()), name="poc-hub"),
url(r'storage/doc/(?P<document_id>\d+)', bceid_required(views.view_document_file), name="poc-storage-download"),
url(r'storage/delete/(?P<pk>\d+)', bceid_required(views.UploadStorageDelete.as_view()), name="poc-storage-delete"),
url(r'storage', bceid_required(views.UploadStorage.as_view()), name="poc-storage"),
url(r'scan', login_required(views.UploadScan.as_view()), name="poc-scan"),
url(r'hub', login_required(views.EfilingHubUpload.as_view()), name="poc-hub"),
url(r'storage/doc/(?P<document_id>\d+)', login_required(views.view_document_file), name="poc-storage-download"),
url(r'storage/delete/(?P<pk>\d+)', login_required(views.UploadStorageDelete.as_view()), name="poc-storage-delete"),
url(r'storage', login_required(views.UploadStorage.as_view()), name="poc-storage"),
]

+ 32
- 9
edivorce/settings/base.py View File

@ -11,6 +11,8 @@ https://docs.djangoproject.com/en/1.8/ref/settings/
"""
import os
from django.urls import reverse_lazy
from environs import Env
from unipath import Path
@ -45,6 +47,7 @@ INSTALLED_APPS = (
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.humanize',
'mozilla_django_oidc', # Load after auth
'rest_framework',
'debug_toolbar',
'corsheaders',
@ -62,7 +65,7 @@ if ENVIRONMENT in ['localdev', 'dev', 'test', 'minishift']:
)
MIDDLEWARE = (
'edivorce.apps.core.middleware.basicauth_middleware.BasicAuthMiddleware',
# 'edivorce.apps.core.middleware.basicauth_middleware.BasicAuthMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
@ -71,11 +74,15 @@ MIDDLEWARE = (
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'edivorce.apps.core.middleware.bceid_middleware.BceidMiddleware',
# 'edivorce.apps.core.middleware.bceid_middleware.BceidMiddleware',
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
)
AUTHENTICATION_BACKENDS = (
'edivorce.apps.core.middleware.keycloak.EDivorceKeycloakBackend',
)
ROOT_URLCONF = 'edivorce.urls'
TEMPLATES = [
@ -99,11 +106,11 @@ WSGI_APPLICATION = 'wsgi.application'
# need to disable auth in Django Rest Framework so it doesn't get triggered
# by presence of Basic Auth headers
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'edivorce.apps.core.authenticators.BCeIDAuthentication',
]
}
# REST_FRAMEWORK = {
# 'DEFAULT_AUTHENTICATION_CLASSES': [
# 'edivorce.apps.core.authenticators.BCeIDAuthentication',
# ]
# }
LOGGING = {
@ -117,7 +124,7 @@ LOGGING = {
'loggers': {
'': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
'level': env('DJANGO_LOG_LEVEL', 'INFO'),
},
},
}
@ -175,7 +182,7 @@ DEBUG_TOOLBAR_CONFIG = {
SECURE_BROWSER_XSS_FILTER = True
LOGOUT_URL = '/accounts/logout/'
# LOGOUT_URL = '/accounts/logout/'
# CLAMAV settings
@ -187,3 +194,19 @@ EFILING_HUB_CLIENT_SECRET = env('EFILING_HUB_CLIENT_SECRET', 'abc')
EFILING_HUB_API_BASE_URL = env('EFILING_HUB_API_BASE_URL', 'https://efiling.gov.bc.ca')
EFILING_BCEID = env.dict('EFILING_BCEID', '', subcast=str)
# Keycloak OpenID Connect settings
# Provided by mozilla-django-oidc
LOGIN_URL = reverse_lazy('oidc_authentication_init')
OIDC_RP_SIGN_ALGO = 'RS256'
OIDC_RP_SCOPES = 'openid email profile'
OIDC_AUTH_REQUEST_EXTRA_PARAMS = {'kc_idp_hint': 'bceid'} # this is needed to bypass the Keycloak login screen
# OIDC_CREATE_USER = False
OIDC_OP_JWKS_ENDPOINT = env('OIDC_OP_JWKS_ENDPOINT', '')
OIDC_RP_CLIENT_ID = env('OIDC_RP_CLIENT_ID', '')
OIDC_RP_CLIENT_SECRET = env('OIDC_RP_CLIENT_SECRET', '')
OIDC_OP_AUTHORIZATION_ENDPOINT = env('OIDC_OP_AUTHORIZATION_ENDPOINT', '')
OIDC_OP_TOKEN_ENDPOINT = env('OIDC_OP_TOKEN_ENDPOINT', '')
OIDC_OP_USER_ENDPOINT = env('OIDC_OP_USER_ENDPOINT', '')
LOGIN_REDIRECT_URL = env('LOGIN_REDIRECT_URL', '/')
LOGOUT_REDIRECT_URL = env('LOGOUT_REDIRECT_URL', '/')

+ 2
- 0
edivorce/urls.py View File

@ -22,6 +22,8 @@ if settings.ENVIRONMENT in ['localdev', 'minishift']:
urlpatterns.append(url(r'^404/$', main.page_not_found, {'exception': Exception()}))
urlpatterns.append(url(r'^500/$', main.server_error))
urlpatterns.append(url(r'^oidc/', include('mozilla_django_oidc.urls')))
urlpatterns.append(url(r'^', include('edivorce.apps.core.urls')))
handler404 = main.page_not_found


Loading…
Cancel
Save