Keycloak login
This commit is contained in:
parent
70c36a44f5
commit
a612239083
9 changed files with 122 additions and 3 deletions
|
|
@ -41,16 +41,17 @@ ALLOWED_HOSTS = [
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'repapp_users.apps.RepappUsersConfig',
|
|
||||||
'repapp.apps.RepappConfig',
|
'repapp.apps.RepappConfig',
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
|
'mozilla_django_oidc',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'crispy_forms',
|
'crispy_forms',
|
||||||
'crispy_bootstrap4',
|
'crispy_bootstrap4',
|
||||||
|
'repapp_users.apps.RepappUsersConfig',
|
||||||
]
|
]
|
||||||
|
|
||||||
CRISPY_ALLOWED_TEMPLATE_PACKS = 'bootstrap4'
|
CRISPY_ALLOWED_TEMPLATE_PACKS = 'bootstrap4'
|
||||||
|
|
@ -154,6 +155,27 @@ EMAIL_USE_TLS = os.getenv("DJANGO_EMAIL_USE_TLS", 'true') in ('true', '1', 't')
|
||||||
|
|
||||||
AUTH_USER_MODEL = "repapp_users.CustomUser"
|
AUTH_USER_MODEL = "repapp_users.CustomUser"
|
||||||
AUTHENTICATION_BACKENDS = [
|
AUTHENTICATION_BACKENDS = [
|
||||||
"repapp_users.backends.EmailBackend", "django.contrib.auth.backends.ModelBackend"]
|
"repapp_users.backends.EmailBackend",
|
||||||
|
"django.contrib.auth.backends.ModelBackend",
|
||||||
|
# 'mozilla_django_oidc.auth.OIDCAuthenticationBackend',
|
||||||
|
'repapp_users.backends.KeycloakOIDCAB'
|
||||||
|
]
|
||||||
|
|
||||||
LOGIN_REDIRECT_URL = '/guest/profile/'
|
LOGIN_REDIRECT_URL = '/guest/profile/'
|
||||||
|
|
||||||
|
OIDC_RP_CLIENT_ID = "repapp"
|
||||||
|
OIDC_RP_CLIENT_SECRET = os.getenv("DJANGO_OIDC_RP_CLIENT_SECRET", None)
|
||||||
|
|
||||||
|
OIDC_RP_SIGN_ALGO = "RS256"
|
||||||
|
OIDC_OP_JWKS_ENDPOINT = "https://sso.makes-hacks-hip.de/realms/Makes-Hacks-Hip/protocol/openid-connect/certs"
|
||||||
|
|
||||||
|
OIDC_OP_AUTHORIZATION_ENDPOINT = "https://sso.makes-hacks-hip.de/realms/Makes-Hacks-Hip/protocol/openid-connect/auth"
|
||||||
|
OIDC_OP_TOKEN_ENDPOINT = "https://sso.makes-hacks-hip.de/realms/Makes-Hacks-Hip/protocol/openid-connect/token"
|
||||||
|
OIDC_OP_USER_ENDPOINT = "https://sso.makes-hacks-hip.de/realms/Makes-Hacks-Hip/protocol/openid-connect/userinfo"
|
||||||
|
|
||||||
|
if DEBUG:
|
||||||
|
LOGIN_REDIRECT_URL = "http://127.0.0.1:8000/"
|
||||||
|
LOGOUT_REDIRECT_URL = "http://127.0.0.1:8000/"
|
||||||
|
else:
|
||||||
|
LOGIN_REDIRECT_URL = "https://repapp.rc-hip.de/"
|
||||||
|
LOGOUT_REDIRECT_URL = "https://repapp.rc-hip.de/"
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ from django.conf.urls.static import static
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", include("repapp.urls")),
|
path("", include("repapp.urls")),
|
||||||
|
path('oidc/', include('mozilla_django_oidc.urls')),
|
||||||
path('accounts/', include('django.contrib.auth.urls')),
|
path('accounts/', include('django.contrib.auth.urls')),
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|
|
||||||
|
|
@ -34,5 +34,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<footer>
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<a href="{% url 'logout' %}">Gast Logout</a>
|
||||||
|
<a href="{% url 'member_login' %}">Mitarbeiter Logout</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url 'login' %}">Gast Login</a>
|
||||||
|
<a href="{% url 'member_login' %}">Mitarbeiter Login</a>
|
||||||
|
{% endif %}
|
||||||
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
26
rc_hip/repapp/templates/repapp/member_login.html
Normal file
26
rc_hip/repapp/templates/repapp/member_login.html
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
{% extends "repapp/base.html" %}
|
||||||
|
{% block title %}
|
||||||
|
- Mitarbeiter Login
|
||||||
|
{% endblock title %}
|
||||||
|
{% block content %}
|
||||||
|
<h1 class="mt-2">
|
||||||
|
Mitarbeiter
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
Logout
|
||||||
|
{% else %}
|
||||||
|
Login
|
||||||
|
{% endif %}
|
||||||
|
</h1>
|
||||||
|
<hr class="mt-0 mb-4">
|
||||||
|
<div>
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<p>Angemeldeter Benutzer: {{ user.email }}</p>
|
||||||
|
<form action="{% url 'oidc_logout' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button type="submit" class="btn btn-primary">Abmelden</button>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url 'oidc_authentication_init' %}">Anmelden mit Makes-Hacks-Hip</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -23,4 +23,6 @@ urlpatterns = [
|
||||||
views.device_view, name="view_device"),
|
views.device_view, name="view_device"),
|
||||||
path("guest/profile/",
|
path("guest/profile/",
|
||||||
views.profile, name="guest_profile"),
|
views.profile, name="guest_profile"),
|
||||||
|
path("member/login/",
|
||||||
|
views.member_login, name="member_login"),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,13 @@ def profile(request):
|
||||||
request,
|
request,
|
||||||
"repapp/guest_profile.html",
|
"repapp/guest_profile.html",
|
||||||
{
|
{
|
||||||
'user': user,
|
|
||||||
'guest': guest
|
'guest': guest
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def member_login(request):
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"repapp/member_login.html"
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
import unicodedata
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.backends import ModelBackend
|
from django.contrib.auth.backends import ModelBackend
|
||||||
|
from mozilla_django_oidc.auth import OIDCAuthenticationBackend
|
||||||
|
from repapp.models import Organisator, Reparateur
|
||||||
|
|
||||||
|
|
||||||
class EmailBackend(ModelBackend):
|
class EmailBackend(ModelBackend):
|
||||||
|
|
@ -13,3 +16,50 @@ class EmailBackend(ModelBackend):
|
||||||
if user.check_password(password):
|
if user.check_password(password):
|
||||||
return user
|
return user
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def generate_username(email):
|
||||||
|
# Using Python 3 and Django 1.11+, usernames can contain alphanumeric
|
||||||
|
# (ascii and unicode), _, @, +, . and - characters. So we normalize
|
||||||
|
# it and slice at 150 characters.
|
||||||
|
return unicodedata.normalize('NFKC', email)[:150]
|
||||||
|
|
||||||
|
|
||||||
|
def create_repapp_user(user):
|
||||||
|
organisator = Organisator.objects.filter(mail=user.email).first()
|
||||||
|
if not organisator:
|
||||||
|
reparateur = Reparateur.objects.filter(mail=user.email).first()
|
||||||
|
if not reparateur:
|
||||||
|
reparateur = Reparateur(
|
||||||
|
name=user.username,
|
||||||
|
mail=user.email,
|
||||||
|
)
|
||||||
|
reparateur.save()
|
||||||
|
else:
|
||||||
|
reparateur.name = user.username
|
||||||
|
reparateur.save()
|
||||||
|
else:
|
||||||
|
organisator.name = user.username
|
||||||
|
organisator.save()
|
||||||
|
|
||||||
|
|
||||||
|
class KeycloakOIDCAB(OIDCAuthenticationBackend):
|
||||||
|
def create_user(self, claims):
|
||||||
|
user = super(KeycloakOIDCAB, self).create_user(claims)
|
||||||
|
|
||||||
|
user.username = claims.get(
|
||||||
|
'preferred_username', generate_username(user.email))
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
create_repapp_user(user)
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
||||||
|
def update_user(self, user, claims):
|
||||||
|
user.username = claims.get(
|
||||||
|
'preferred_username', generate_username(user.email))
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
create_repapp_user(user)
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,5 @@ pylint-django==2.5.3
|
||||||
pylint-plugin-utils==0.7
|
pylint-plugin-utils==0.7
|
||||||
django-crispy-forms==2.0
|
django-crispy-forms==2.0
|
||||||
crispy-bootstrap4==2022.1
|
crispy-bootstrap4==2022.1
|
||||||
|
mozilla-django-oidc==3.0.0
|
||||||
|
djlint==1.23.3
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@ Django==4.2
|
||||||
gunicorn==20.1.0
|
gunicorn==20.1.0
|
||||||
django-crispy-forms==2.0
|
django-crispy-forms==2.0
|
||||||
crispy-bootstrap4==2022.1
|
crispy-bootstrap4==2022.1
|
||||||
|
mozilla-django-oidc==3.0.0
|
||||||
|
|
|
||||||
Reference in a new issue