Skip to content
Snippets Groups Projects
Commit d9ecf80a authored by Stefano Alberto Russo's avatar Stefano Alberto Russo
Browse files

Added support for OpenID Connect with mozilla-django-oidc==1.2.4. Minor...

Added support for OpenID Connect with mozilla-django-oidc==1.2.4. Minor refactoring of some user-related parts.
parent 6e7a544d
No related branches found
No related tags found
No related merge requests found
from mozilla_django_oidc.auth import OIDCAuthenticationBackend
from .core_app.utils import finalize_user_creation
# Setup logging
import logging
logger = logging.getLogger(__name__)
class RosettaOIDCAuthenticationBackend(OIDCAuthenticationBackend):
def create_user(self, claims):
# Call parent user creation function
user = super(RosettaOIDCAuthenticationBackend, self).create_user(claims)
# Add profile, keys etc.
finalize_user_creation(user)
return user
def get_userinfo(self, access_token, id_token, payload):
# Payload must contain the "email" key
return payload
import os
from django.conf import settings
def export_vars(request):
data = {}
if settings.OIDC_RP_CLIENT_ID:
data['OPENID_ENABLED'] = True
else:
data['OPENID_ENABLED'] = False
return data
\ No newline at end of file
......@@ -22,7 +22,7 @@
<b>Account ID</b>
</td>
<td>
{{data.user.username}} | <a href="/logout/">Logout</a>
{{data.user.username}}
</td>
</tr>
......@@ -99,9 +99,22 @@
</tr>
</table>
</form>
<div style="margin-left:10px; margin-top:40px">
{% if OPENID_ENABLED %}
<form action="{% url 'oidc_logout' %}" method="post">
{% csrf_token %}
<input type="submit" value="logout">
</form>
{% else %}
<form action="/logout/" method="get">
<input type="submit" value="logout">
</form>
{% endif %}
</div>
<br/>
<br/>
<br/>
......
......@@ -44,6 +44,8 @@
<input type="password" class="form-control" placeholder="Password" name='password'>
<input type='submit' class="btn btn-lg ha-btn-lg" value='Login' />
</form>
{% if OPENID %}
{% endif %}
</center>
</li>
<center>
......@@ -53,7 +55,23 @@
</div>
</center>
{% endif %}
{% if OPENID_ENABLED %}
<li>
{% if not user.is_authenticated %}
<a href="{% url 'oidc_authentication_init' %}">Login with OpenID Conn. &nbsp;</a>
{% endif %}
</li>
{% endif %}
</ul>
</nav>
{% endif %}
......@@ -134,6 +134,34 @@ def random_username():
return username
def finalize_user_creation(user):
from .models import Profile, KeyPair
# Create profile
logger.debug('Creating user profile for user "{}"'.format(user.email))
Profile.objects.create(user=user)
# Generate user keys
out = os_shell('mkdir -p /data/resources/keys/', capture=True)
if not out.exit_code == 0:
logger.error(out)
raise ErrorMessage('Something went wrong in creating user keys folder. Please contact support')
command= "/bin/bash -c \"ssh-keygen -q -t rsa -N '' -f /data/resources/keys/{}_id_rsa 2>/dev/null <<< y >/dev/null\"".format(user.username)
out = os_shell(command, capture=True)
if not out.exit_code == 0:
logger.error(out)
raise ErrorMessage('Something went wrong in creating user keys. Please contact support')
# Create key objects
KeyPair.objects.create(user = user,
default = True,
private_key_file = '/data/resources/keys/{}_id_rsa'.format(user.username),
public_key_file = '/data/resources/keys/{}_id_rsa.pub'.format(user.username))
def sanitize_shell_encoding(text):
return text.encode("utf-8", errors="ignore")
......
......@@ -9,7 +9,7 @@ from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.models import User
from django.shortcuts import redirect
from .models import Profile, LoginToken, Task, TaskStatuses, Container, Computing, KeyPair, ComputingSysConf, ComputingUserConf
from .utils import send_email, format_exception, timezonize, os_shell, booleanize, debug_param, get_tunnel_host, random_username, setup_tunnel
from .utils import send_email, format_exception, timezonize, os_shell, booleanize, debug_param, get_tunnel_host, random_username, setup_tunnel, finalize_user_creation
from .decorators import public_view, private_view
from .exceptions import ErrorMessage
......@@ -166,29 +166,7 @@ def register_view(request):
data['user'] = user
# Create profile
logger.debug('Creating user profile for user "{}"'.format(user.email))
Profile.objects.create(user=user)
# Generate user keys
out = os_shell('mkdir -p /data/resources/keys/', capture=True)
if not out.exit_code == 0:
logger.error(out)
raise ErrorMessage('Something went wrong in creating user keys folder. Please contact support')
command= "/bin/bash -c \"ssh-keygen -q -t rsa -N '' -f /data/resources/keys/{}_id_rsa 2>/dev/null <<< y >/dev/null\"".format(user.username)
out = os_shell(command, capture=True)
if not out.exit_code == 0:
logger.error(out)
raise ErrorMessage('Something went wrong in creating user keys. Please contact support')
# Create key objects
KeyPair.objects.create(user = user,
default = True,
private_key_file = '/data/resources/keys/{}_id_rsa'.format(user.username),
public_key_file = '/data/resources/keys/{}_id_rsa.pub'.format(user.username))
finalize_user_creation(user)
# Manually set the auth backend for the user
user.backend = 'django.contrib.auth.backends.ModelBackend'
......
......@@ -36,6 +36,7 @@ INSTALLED_APPS = [
'rosetta.core_app',
'django.contrib.admin',
'django.contrib.auth',
'mozilla_django_oidc',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
......@@ -67,6 +68,7 @@ TEMPLATES = [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'rosetta.context_processors.export_vars'
],
},
},
......@@ -225,3 +227,45 @@ LOGGING = {
#===============================
# Auth
#===============================
OIDC_RP_CLIENT_ID = os.environ.get('OIDC_RP_CLIENT_ID', None)
if OIDC_RP_CLIENT_ID:
# Add 'mozilla_django_oidc' authentication backend
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'rosetta.auth.RosettaOIDCAuthenticationBackend'
)
# Base
OIDC_RP_CLIENT_SECRET = os.environ.get('OIDC_RP_CLIENT_SECRET')
OIDC_OP_AUTHORIZATION_ENDPOINT = os.environ.get('OIDC_OP_AUTHORIZATION_ENDPOINT')
OIDC_OP_TOKEN_ENDPOINT = os.environ.get('OIDC_OP_TOKEN_ENDPOINT')
OIDC_OP_USER_ENDPOINT = os.environ.get('OIDC_OP_USER_ENDPOINT')
OIDC_RP_SIGN_ALGO = os.environ.get('OIDC_RP_SIGN_ALGO', 'RS256')
OIDC_RP_IDP_SIGN_KEY = os.environ.get('OIDC_RP_IDP_SIGN_KEY', None)
OIDC_OP_JWKS_ENDPOINT = os.environ.get('OIDC_OP_JWKS_ENDPOINT', None)
# Check
if OIDC_RP_SIGN_ALGO == 'RS256':
if not OIDC_RP_IDP_SIGN_KEY and not OIDC_OP_JWKS_ENDPOINT:
raise ImproperlyConfigured('RS256 OpenID requires OIDC_RP_IDP_SIGN_KEY or OIDC_OP_JWKS_ENDPOINT to be set')
# Optional
OIDC_USE_NONCE = booleanize(os.environ.get('OIDC_USE_NONCE', False))
OIDC_TOKEN_USE_BASIC_AUTH = booleanize(os.environ.get('OIDC_TOKEN_USE_BASIC_AUTH', True))
# Non-customizable stuff
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
LOGIN_REDIRECT_URL_FAILURE = '/'
......@@ -63,7 +63,10 @@ urlpatterns = [
# Custom APIs
path('api/v1/base/agent/', core_app_api.agent_api.as_view(), name='agent_api'),
# Open ID Connect Auth
path('oidc/', include('mozilla_django_oidc.urls')),
]
# This message here is quite useful when developing in autoreload mode
......
......@@ -5,3 +5,4 @@ djangorestframework==3.9.3
django-rest-swagger==2.2.0
dateutils==0.6.6
sendgrid==5.3.0
mozilla-django-oidc==1.2.4
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment