External auto auth working

pull/1371/head
Piero Toffanin 2023-09-08 12:28:13 -04:00
rodzic 89a6aca5f0
commit 73052fb2ec
5 zmienionych plików z 124 dodań i 68 usunięć

Wyświetl plik

@ -0,0 +1,38 @@
from django.contrib.auth.models import User
from django.contrib.auth import login
from rest_framework.views import APIView
from rest_framework import exceptions, permissions, parsers
from rest_framework.response import Response
from app.auth.backends import get_user_from_external_auth_response
import requests
from webodm import settings
class ExternalTokenAuth(APIView):
permission_classes = (permissions.AllowAny,)
parser_classes = (parsers.JSONParser, parsers.FormParser,)
def post(self, request):
# This should never happen
if settings.EXTERNAL_AUTH_ENDPOINT == '':
return Response({'error': 'EXTERNAL_AUTH_ENDPOINT not set'})
token = request.COOKIES.get('external_access_token', '')
if token == '':
return Response({'error': 'external_access_token cookie not set'})
try:
r = requests.post(settings.EXTERNAL_AUTH_ENDPOINT, headers={
'Authorization': "Bearer %s" % token
})
res = r.json()
if res.get('user_id') is not None:
user = get_user_from_external_auth_response(res)
if user is not None:
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
return Response({'redirect': '/'})
else:
return Response({'error': 'Invalid credentials'})
else:
return Response({'error': res.get('message', 'Invalid external server response')})
except Exception as e:
return Response({'error': str(e)})

Wyświetl plik

@ -13,6 +13,7 @@ from .tiler import TileJson, Bounds, Metadata, Tiles, Export
from .potree import Scene, CameraView
from .workers import CheckTask, GetTaskResult
from .users import UsersList
from .externalauth import ExternalTokenAuth
from webodm import settings
router = routers.DefaultRouter()
@ -63,3 +64,6 @@ urlpatterns = [
if settings.ENABLE_USERS_API:
urlpatterns.append(url(r'users', UsersList.as_view()))
if settings.EXTERNAL_AUTH_ENDPOINT != '':
urlpatterns.append(url(r'^external-token-auth/', ExternalTokenAuth.as_view()))

Wyświetl plik

@ -8,6 +8,57 @@ import logging
logger = logging.getLogger('app.logger')
def get_user_from_external_auth_response(res):
if 'message' in res or 'error' in res:
return None
if 'user_id' in res and 'username' in res:
try:
user = User.objects.get(pk=res['user_id'])
# Update user info
if user.username != res['username']:
user.username = res['username']
user.save()
# Update quotas
maxQuota = -1
if 'maxQuota' in res:
maxQuota = res['maxQuota']
if 'node' in res and 'limits' in res['node'] and 'maxQuota' in res['node']['limits']:
maxQuota = res['node']['limits']['maxQuota']
if user.profile.quota != maxQuota:
user.profile.quota = maxQuota
user.save()
except User.DoesNotExist:
user = User(pk=res['user_id'], username=username)
user.save()
# Setup/update processing node
if ('api_key' in res or 'token' in res) and 'node' in res:
hostname = res['node']['hostname']
port = res['node']['port']
token = res['api_key'] if 'api_key' in res else res['token']
try:
node = ProcessingNode.objects.get(token=token)
if node.hostname != hostname or node.port != port:
node.hostname = hostname
node.port = port
node.save()
except ProcessingNode.DoesNotExist:
node = ProcessingNode(hostname=hostname, port=port, token=token)
node.save()
if not user.has_perm('view_processingnode', node):
assign_perm('view_processingnode', user, node)
return user
else:
return None
class ExternalBackend(ModelBackend):
def authenticate(self, request, username=None, password=None):
if EXTERNAL_AUTH_ENDPOINT == "":
@ -20,57 +71,7 @@ class ExternalBackend(ModelBackend):
}, headers={'Accept': 'application/json'})
res = r.json()
# logger.info(res)
if 'message' in res or 'error' in res:
return None
if 'user_id' in res:
try:
user = User.objects.get(pk=res['user_id'])
# Update user info
if user.username != username:
user.username = username
user.save()
# Update quotas
maxQuota = -1
if 'maxQuota' in res:
maxQuota = res['maxQuota']
if 'node' in res and 'limits' in res['node'] and 'maxQuota' in res['node']['limits']:
maxQuota = res['node']['limits']['maxQuota']
if user.profile.quota != maxQuota:
user.profile.quota = maxQuota
user.save()
except User.DoesNotExist:
user = User(pk=res['user_id'], username=username)
user.save()
# Setup/update processing node
if ('api_key' in res or 'token' in res) and 'node' in res:
hostname = res['node']['hostname']
port = res['node']['port']
token = res['api_key'] if 'api_key' in res else res['token']
try:
node = ProcessingNode.objects.get(token=token)
if node.hostname != hostname or node.port != port:
node.hostname = hostname
node.port = port
node.save()
except ProcessingNode.DoesNotExist:
node = ProcessingNode(hostname=hostname, port=port, token=token)
node.save()
if not user.has_perm('view_processingnode', node):
assign_perm('view_processingnode', user, node)
return user
else:
return None
return get_user_from_external_auth_response(res)
except:
return None

Wyświetl plik

@ -10,12 +10,12 @@
{% endif %}
{% is_single_user_mode as autologin %}
{% external_auth_endpoint as ext_auth_ep %}
{% has_external_auth as ext_auth %}
{% if autologin %}
<script>location.href='/';</script>
{% else %}
<form id="loginForm" {% if ext_auth_ep != "" %} style="display: none" {% endif %} action="{% url 'login' %}" method="post" class="form-horizontal" role="form">{% csrf_token %}
<form id="loginForm" {% if ext_auth %} style="display: none" {% endif %} action="{% url 'login' %}" method="post" class="form-horizontal" role="form">{% csrf_token %}
{% for field in form %}
{% include 'registration/form_field.html' %}
{% endfor %}
@ -36,34 +36,47 @@
</div>
</form>
{% if ext_auth_ep != '' %}
{% if ext_auth %}
<div class="text-center" id="authLoading">
<i class="fa fa-spin fa-circle-notch fa-spin fa-fw fa-2x"></i>
</div>
<script>
function getCookie(name) {
function getAutoLoginCookie() {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
var parts = value.split("; autologin=");
if (parts.length === 2) return parts.pop().split(';').shift();
}
function delCookie(name) {
document.cookie = name +'=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
function delAutoLoginCookie() {
var domain = getAutoLoginCookie();
document.cookie = 'autologin=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain=' + domain + ';';
}
function showLoginForm(){
$("#authLoading").hide();
$("#loginForm").show();
}
$(function(){
if (getCookie("autologin") !== undefined){
if (getAutoLoginCookie() !== undefined){
$.ajax({
url: "{{ ext_auth_ep }}",
url: "/api/external-token-auth/",
type: "POST",
xhrFields: {
withCredentials: true
},
}).done(function(res){
console.log(res);
// delCookie("autologin");
delAutoLoginCookie();
if (res.redirect){
location.href = res.redirect;
}else{
if (res.error) console.error(res.error);
showLoginForm();
}
}).fail(function(){
// delCookie("autologin");
delAutoLoginCookie();
showLoginForm();
console.error("Auto login failed");
});
}else{
$("#authLoading").hide();
$("#loginForm").show();
showLoginForm();
}
});
</script>

Wyświetl plik

@ -10,8 +10,8 @@ register = template.Library()
logger = logging.getLogger('app.logger')
@register.simple_tag
def external_auth_endpoint():
return settings.EXTERNAL_AUTH_ENDPOINT
def has_external_auth():
return settings.EXTERNAL_AUTH_ENDPOINT != ""
@register.filter
def disk_size(megabytes):