local accounts authentication (#7066)
This commit is contained in:
parent
41862ed39d
commit
b3843f123f
|
@ -0,0 +1,14 @@
|
|||
from .organization.models import LocalAccount
|
||||
from datetime import datetime
|
||||
|
||||
class LocalAccountPasswordBackend(object):
|
||||
|
||||
def authenticate(self, login, password, organization):
|
||||
try:
|
||||
account = LocalAccount.objects.get(username=login, active=True,
|
||||
organization=organization)
|
||||
if account.password == password:
|
||||
if not account.expired:
|
||||
return account
|
||||
except LocalAccount.DoesNotExist:
|
||||
return None
|
|
@ -99,6 +99,7 @@ LDAP_CONF = {
|
|||
|
||||
AUTHENTICATION_BACKENDS = global_settings.AUTHENTICATION_BACKENDS + (
|
||||
'mellon.backends.SAMLBackend',
|
||||
'uauth.backends.LocalAccountPasswordBackend',
|
||||
)
|
||||
|
||||
MELLON_ATTRIBUTE_MAPPING = {
|
||||
|
|
|
@ -35,6 +35,10 @@ ul.login li, #guest-login ul li, #voucher-login ul li, .loginbox li {
|
|||
border-bottom: 1px solid #bbb;
|
||||
}
|
||||
|
||||
#login label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.loginbox {
|
||||
width: 300px;
|
||||
margin: 0 auto;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import logging
|
||||
import json
|
||||
from uuid import uuid4
|
||||
|
||||
try:
|
||||
import ldap
|
||||
|
@ -42,7 +43,9 @@ def get_ldap_connection(conf=settings.LDAP_CONF):
|
|||
return
|
||||
return conn
|
||||
|
||||
def create_radius_user(username, password, **kwargs):
|
||||
def create_radius_user(**kwargs):
|
||||
username = uuid4().get_hex()
|
||||
password = uuid4().get_hex()
|
||||
connection = get_ldap_connection()
|
||||
if connection:
|
||||
attrs = {'objectClass': ['radiusprofile', 'radiusObjectProfile'],
|
||||
|
@ -54,6 +57,6 @@ def create_radius_user(username, password, **kwargs):
|
|||
dn = 'uid=%s,%s' % (username, settings.LDAP_CONF['dn'])
|
||||
logger.debug('creating new radius user: %s' % dn)
|
||||
connection.add_s(dn, ldif)
|
||||
return True
|
||||
return username, password
|
||||
else:
|
||||
return False
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
import json
|
||||
from uuid import uuid4
|
||||
import requests
|
||||
from xml.etree import ElementTree
|
||||
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.views.generic import FormView
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.shortcuts import render_to_response
|
||||
from django.core import signing
|
||||
from django.http.request import QueryDict
|
||||
from django.contrib.auth import authenticate
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from mellon.views import LoginView as MellonLoginView
|
||||
|
||||
from .organization.models import Organization
|
||||
from .organization.models import Organization, LocalAccount
|
||||
from .forms import GuestLoginForm, VoucherLoginForm
|
||||
from .utils import create_radius_user, is_organization_idp, \
|
||||
get_idp_list
|
||||
|
@ -22,8 +24,29 @@ class HomeView(TemplateView):
|
|||
|
||||
homepage = HomeView.as_view()
|
||||
|
||||
class LoginMixin(object):
|
||||
def login(self, organization):
|
||||
context = {'organization': organization}
|
||||
result = create_radius_user()
|
||||
if result:
|
||||
username, password = result
|
||||
params = QueryDict(self.request.session[organization.slug], mutable=True)
|
||||
hotspot_url = organization.hotspot_url
|
||||
|
||||
class LoginView(MellonLoginView):
|
||||
if 'login_url' in params:
|
||||
hotspot_url = params.pop('login_url')[0]
|
||||
|
||||
context.update({'params': params.urlencode(),
|
||||
'hotspot_url': hotspot_url,
|
||||
'data': {'username': username,
|
||||
'password': password}
|
||||
})
|
||||
return render_to_response('uauth/%s_login_successful.html' % organization.hotspot_type,
|
||||
context)
|
||||
return render_to_response('uauth/login_failed.html', context)
|
||||
|
||||
|
||||
class LoginView(LoginMixin, MellonLoginView):
|
||||
|
||||
def authenticate(self, request, login, attributes):
|
||||
relayState = signing.loads(login.msgRelayState)
|
||||
|
@ -41,44 +64,38 @@ class LoginView(MellonLoginView):
|
|||
eduPersonTargetedID_NameQualifier = attributes['issuer']
|
||||
|
||||
if is_organization_idp(eduPersonTargetedID_NameQualifier, organization):
|
||||
username = uuid4().get_hex()
|
||||
password = uuid4().get_hex()
|
||||
context = {'organization': organization}
|
||||
if create_radius_user(username, password):
|
||||
params = QueryDict(self.request.session[organization.slug], mutable=True)
|
||||
hotspot_url = organization.hotspot_url
|
||||
|
||||
if 'login_url' in params:
|
||||
hotspot_url = params.pop('login_url')[0]
|
||||
|
||||
context.update({'params': params.urlencode(),
|
||||
'hotspot_url': hotspot_url,
|
||||
'data': {'username': username,
|
||||
'password': password
|
||||
}
|
||||
})
|
||||
return render_to_response('uauth/%s_login_successful.html' % organization.hotspot_type,
|
||||
context)
|
||||
return render_to_response('uauth/login_failed.html', context)
|
||||
return self.login(organization)
|
||||
|
||||
login = csrf_exempt(LoginView.as_view())
|
||||
|
||||
|
||||
class OrganizationPageView(TemplateView):
|
||||
class OrganizationPageView(LoginMixin, FormView):
|
||||
form_class = GuestLoginForm
|
||||
template_name = 'uauth/organization.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(OrganizationPageView, self).get_context_data(**kwargs)
|
||||
idps = get_idp_list()
|
||||
organization = Organization.objects.get(slug=kwargs['organization_slug'])
|
||||
organization = Organization.objects.get(slug=self.kwargs['organization_slug'])
|
||||
self.request.session[organization.slug] = self.request.GET.urlencode()
|
||||
relay = signing.dumps({'organization': organization.slug})
|
||||
context.update({'idps': idps,
|
||||
'guest_login_form': GuestLoginForm(),
|
||||
'voucher_login_form': VoucherLoginForm(),
|
||||
'guest_login_form': kwargs['form'],
|
||||
'relay': relay,
|
||||
'organization': organization
|
||||
'organization': organization,
|
||||
'voucher_login_form': VoucherLoginForm()
|
||||
})
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
data = form.cleaned_data
|
||||
organization = Organization.objects.get(slug=self.kwargs['organization_slug'])
|
||||
data.update({'organization': organization})
|
||||
user = authenticate(**data)
|
||||
if user:
|
||||
return self.login(organization)
|
||||
else:
|
||||
form.add_error(None, _('Unknown or inactive user'))
|
||||
return self.form_invalid(form)
|
||||
|
||||
organization = OrganizationPageView.as_view()
|
||||
|
|
Reference in New Issue