set up oauth and fixed login flow

This commit is contained in:
CDaut 2022-12-16 22:21:35 +01:00 committed by CDaut
parent b09897a39c
commit dba4e12032
7 changed files with 90 additions and 4 deletions

View file

@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/4.0/ref/settings/
""" """
import os import os
from pathlib import Path from pathlib import Path
from authlib.integrations.django_client import OAuth
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
@ -147,3 +148,20 @@ MFA_ISSUER_NAME = 'MDBlog'
# Configure mail here # Configure mail here
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
AUTHLIB_OAUTH_CLIENTS = {}
if os.environ['ENABLE_NEXTCLOUD_OAUTH'] == "True":
AUTHLIB_OAUTH_CLIENTS['nextcloud'] = {
'client_id': os.environ['NC_OAUTH_CLIENT_ID'], # "Client Identifier" in Nextcloud
'client_secret': os.environ['NC_OAUTH_CLIENT_SECRET'], # "Secret" in Nextcloud
'request_token_url': os.environ['NC_BASE_URL'] + '/index.php/apps/oauth2/api/v1/token',
'request_token_params': None,
'access_token_url': os.environ['NC_BASE_URL'] + '/index.php/apps/oauth2/api/v1/token',
'access_token_params': None,
'refresh_token_url': None,
'authorize_url': os.environ['NC_BASE_URL'] + '/index.php/apps/oauth2/authorize',
'api_base_url': None,
'client_kwargs': None
}

View file

@ -0,0 +1,9 @@
.round-corner {
border-radius: 5px;
}
.oauth-option {
background-color: #35aca1;
font-size: 1.1em;
color: #ffffff;
}

View file

@ -61,7 +61,8 @@
</li> </li>
<li class="no-liststyle"><a class="waves-effect" href="{% url 'admin:index' %}"><i class="material-icons"> <li class="no-liststyle"><a class="waves-effect" href="{% url 'admin:index' %}"><i class="material-icons">
admin_panel_settings</i>Admin panel</a></li> admin_panel_settings</i>Admin panel</a></li>
<li class="no-liststyle"><a class="waves-effect" href="{% url 'django_2fa:devices' %}"><i class="material-icons"> <li class="no-liststyle"><a class="waves-effect" href="{% url 'django_2fa:devices' %}"><i
class="material-icons">
vpn_key</i>Manage 2FA</a></li> vpn_key</i>Manage 2FA</a></li>
<li class="no-liststyle"><a class="waves-effect" href="{% url 'logout' %}"><i <li class="no-liststyle"><a class="waves-effect" href="{% url 'logout' %}"><i
class="material-icons">logout</i>Logout</a></li> class="material-icons">logout</i>Logout</a></li>
@ -100,6 +101,10 @@
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
const elems = document.querySelectorAll('.sidenav'); const elems = document.querySelectorAll('.sidenav');
M.Sidenav.init(elems); M.Sidenav.init(elems);
if ("{{ error }}" !== "") {
M.toast({html: '{{ error }}'});
}
}); });
</script> </script>
{% block scripts %}{% endblock %} {% block scripts %}{% endblock %}

View file

@ -1,14 +1,39 @@
{% extends 'base/base.html' %} {% extends 'base/base.html' %}
{% load static %}
{% block title %} {% block title %}
Log-in Log-in
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="col s8 offset-s2"> <link rel="stylesheet" href="{% static 'login.css' %}">
<div class="col s8 offset-s3">
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}
<button type="submit" class="waves-effect waves-light btn">Log In<i class="material-icons right">send</i> <div class="row">
<div class="input-field col s6">
<input id="username" type="text" class="validate" name="username">
<label for="username">Username</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<input id="password" type="password" class="validate" name="password">
<label for="password">Password</label>
</div>
</div>
<button type="submit" class="waves-effect waves-light btn">Log In<i
class="material-icons right">send</i>
</button> </button>
</form> </form>
{% for auth_method in AUTHLIB_OAUTH_CLIENTS %}
<div class="row mt-3">
<a href="#">
<div class="col s6 z-depth-3 round-corner oauth-option">
<p class="oauth-option">Log in via {{ auth_method }}</p>
</div> </div>
</a>
</div>
{% endfor %}
</div>
{% endblock %} {% endblock %}

View file

@ -1,11 +1,13 @@
from django.contrib import admin from django.contrib import admin
from django.urls import path, include from django.urls import path, include
from markdownblog.views import login_view
import django_2fa.urls import django_2fa.urls
urlpatterns = [ urlpatterns = [
path('', include('blog.urls')), path('', include('blog.urls')),
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('accounts/login/', login_view),
path('accounts/', include('django.contrib.auth.urls')), path('accounts/', include('django.contrib.auth.urls')),
path('accounts/2fa/', include(django_2fa.urls)), path('accounts/2fa/', include(django_2fa.urls)),
] ]

View file

@ -0,0 +1,25 @@
from django.conf import settings
from django.contrib.auth.views import LoginView
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
def login_view(request):
context = {'AUTHLIB_OAUTH_CLIENTS': settings.AUTHLIB_OAUTH_CLIENTS, 'form': LoginView.authentication_form}
# handle user login if standard login is used
if request.method == 'POST':
if 'username' not in request.POST or 'password' not in request.POST:
context['error'] = 'Please enter a username and a password'
else:
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect(settings.LOGIN_REDIRECT_URL)
else:
context['error'] = "Invalid credentials"
return render(request, 'registration/login.html', context)

View file

@ -8,3 +8,5 @@ django-2fa==0.9.0
django-extensions==3.1.5 django-extensions==3.1.5
Werkzeug==2.1.2 Werkzeug==2.1.2
pyOpenSSL==22.0.0 pyOpenSSL==22.0.0
authlib==1.2.0
requests==2.28.1