Add javascript login function allow service A to log user to service B via javascript
CORS need to be correctly configured if not this can lead to security issues. Please do not put Access-Control-Allow-Origin: "*". You can use django-cors-headers to properly configure CORS
This commit is contained in:
parent
ee987f6d00
commit
9df1cd2e31
3 changed files with 149 additions and 25 deletions
53
cas_server/static/cas_server/cas.js
Normal file
53
cas_server/static/cas_server/cas.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
function cas_login(cas_server_login, service, login_service){
|
||||
url = cas_server_login + '?service=' + encodeURIComponent(service);
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url:url,
|
||||
beforeSend: function (request) {
|
||||
request.setRequestHeader("X-AJAX", "1");
|
||||
},
|
||||
xhrFields: {
|
||||
withCredentials: true
|
||||
},
|
||||
success: function(data, textStatus, request){
|
||||
if(data.status == 'success'){
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: data.url,
|
||||
xhrFields: {
|
||||
withCredentials: true
|
||||
},
|
||||
});
|
||||
} else {
|
||||
if(data.detail == "login required"){
|
||||
window.location.href = cas_server_login + '?service=' + encodeURIComponent(login_service);
|
||||
} else {
|
||||
alert('error: ' + data.messages[1].message);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function (request, textStatus, errorThrown) {},
|
||||
});
|
||||
}
|
||||
|
||||
function cas_logout(cas_server_logout){
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url:cas_server_logout,
|
||||
beforeSend: function (request) {
|
||||
request.setRequestHeader("X-AJAX", "1");
|
||||
},
|
||||
xhrFields: {
|
||||
withCredentials: true
|
||||
},
|
||||
error: function (request, textStatus, errorThrown) {},
|
||||
success: function(data, textStatus, request){
|
||||
if(data.status == 'error'){
|
||||
alert('error: ' + data.messages[1].message);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -14,11 +14,12 @@ from .default_settings import settings
|
|||
|
||||
from django.utils.importlib import import_module
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.http import HttpResponseRedirect, HttpResponse
|
||||
from django.contrib import messages
|
||||
|
||||
import random
|
||||
import string
|
||||
|
||||
import json
|
||||
|
||||
try:
|
||||
from urlparse import urlparse, urlunparse, parse_qsl
|
||||
|
@ -27,6 +28,13 @@ except ImportError:
|
|||
from urllib.parse import urlparse, urlunparse, parse_qsl, urlencode
|
||||
|
||||
|
||||
def JsonResponse(request, data):
|
||||
data["messages"] = []
|
||||
for msg in messages.get_messages(request):
|
||||
data["messages"].append({'message': msg.message, 'level': msg.level_tag})
|
||||
return HttpResponse(json.dumps(data), content_type="application/json")
|
||||
|
||||
|
||||
def import_attr(path):
|
||||
"""transform a python module.attr path to the attr"""
|
||||
if not isinstance(path, str):
|
||||
|
@ -42,6 +50,12 @@ def redirect_params(url_name, params=None):
|
|||
return HttpResponseRedirect(url + "?%s" % params)
|
||||
|
||||
|
||||
def reverse_params(url_name, params=None, **kwargs):
|
||||
url = reverse(url_name, **kwargs)
|
||||
params = urlencode(params if params else {})
|
||||
return url + "?%s" % params
|
||||
|
||||
|
||||
def update_url(url, params):
|
||||
"""update params in the `url` query string"""
|
||||
if not isinstance(url, bytes):
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
from .default_settings import settings
|
||||
|
||||
from django.shortcuts import render, redirect
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.contrib import messages
|
||||
from django.utils.decorators import method_decorator
|
||||
|
@ -30,6 +31,7 @@ import cas_server.utils as utils
|
|||
import cas_server.forms as forms
|
||||
import cas_server.models as models
|
||||
|
||||
from utils import JsonResponse
|
||||
from .models import ServiceTicket, ProxyTicket, ProxyGrantingTicket
|
||||
from .models import ServicePattern
|
||||
|
||||
|
@ -93,6 +95,7 @@ class LogoutView(View, LogoutMixin):
|
|||
self.request = request
|
||||
self.service = request.GET.get('service')
|
||||
self.url = request.GET.get('url')
|
||||
self.ajax = 'HTTP_X_AJAX' in request.META
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""methode called on GET request on this view"""
|
||||
|
@ -108,11 +111,19 @@ class LogoutView(View, LogoutMixin):
|
|||
# else redirect to login page
|
||||
else:
|
||||
if settings.CAS_REDIRECT_TO_LOGIN_AFTER_LOGOUT:
|
||||
|
||||
messages.add_message(request, messages.SUCCESS, _(u'Successfully logout'))
|
||||
return redirect("cas_server:login")
|
||||
if self.ajax:
|
||||
url = reverse("cas_server:login")
|
||||
data = {'status': 'success', 'detail': 'logout', 'url': url}
|
||||
return JsonResponse(request, data)
|
||||
else:
|
||||
return redirect("cas_server:login")
|
||||
else:
|
||||
return render(request, settings.CAS_LOGOUT_TEMPLATE)
|
||||
if self.ajax:
|
||||
data = {'status': 'success', 'detail': 'logout'}
|
||||
return JsonResponse(request, data)
|
||||
else:
|
||||
return render(request, settings.CAS_LOGOUT_TEMPLATE)
|
||||
|
||||
|
||||
class LoginView(View, LogoutMixin):
|
||||
|
@ -129,6 +140,7 @@ class LoginView(View, LogoutMixin):
|
|||
renew = None
|
||||
gateway = None
|
||||
method = None
|
||||
ajax = None
|
||||
|
||||
renewed = False
|
||||
warned = False
|
||||
|
@ -146,6 +158,7 @@ class LoginView(View, LogoutMixin):
|
|||
self.renew = True if request.POST.get('renew') else False
|
||||
self.gateway = request.POST.get('gateway')
|
||||
self.method = request.POST.get('method')
|
||||
self.ajax = 'HTTP_X_AJAX' in request.META
|
||||
|
||||
def check_lt(self):
|
||||
# save LT for later check
|
||||
|
@ -223,6 +236,7 @@ class LoginView(View, LogoutMixin):
|
|||
self.renew = True if request.GET.get('renew') else False
|
||||
self.gateway = request.GET.get('gateway')
|
||||
self.method = request.GET.get('method')
|
||||
self.ajax = 'HTTP_X_AJAX' in request.META
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""methode called on GET request on this view"""
|
||||
|
@ -265,40 +279,55 @@ class LoginView(View, LogoutMixin):
|
|||
_(u"Authentication has been required by service %(name)s (%(url)s)") %
|
||||
{'name': service_pattern.name, 'url': self.service}
|
||||
)
|
||||
return render(
|
||||
self.request,
|
||||
settings.CAS_WARN_TEMPLATE,
|
||||
{'service_ticket_url': self.user.get_service_url(
|
||||
self.service,
|
||||
service_pattern,
|
||||
renew=self.renew
|
||||
)}
|
||||
if self.ajax:
|
||||
data = {"status": "error", "detail": "confirmation needed"}
|
||||
return JsonResponse(request, data)
|
||||
else:
|
||||
return render(
|
||||
self.request,
|
||||
settings.CAS_WARN_TEMPLATE,
|
||||
{'service_ticket_url': self.user.get_service_url(
|
||||
self.service,
|
||||
service_pattern,
|
||||
renew=self.renew
|
||||
)}
|
||||
)
|
||||
else:
|
||||
# redirect, using method ?
|
||||
list(messages.get_messages(self.request)) # clean messages before leaving django
|
||||
return HttpResponseRedirect(
|
||||
self.user.get_service_url(self.service, service_pattern, renew=self.renew)
|
||||
redirect_url = self.user.get_service_url(
|
||||
self.service,
|
||||
service_pattern,
|
||||
renew=self.renew
|
||||
)
|
||||
if not self.ajax:
|
||||
return HttpResponseRedirect(redirect_url)
|
||||
else:
|
||||
data = {"status": "success", "detail": "auth", "url": redirect_url}
|
||||
return JsonResponse(self.request, data)
|
||||
except ServicePattern.DoesNotExist:
|
||||
error = 1
|
||||
messages.add_message(
|
||||
self.request,
|
||||
messages.ERROR,
|
||||
_(u'Service %(url)s non allowed.') % {'url': self.service}
|
||||
)
|
||||
except models.BadUsername:
|
||||
error = 2
|
||||
messages.add_message(
|
||||
self.request,
|
||||
messages.ERROR,
|
||||
_(u"Username non allowed")
|
||||
)
|
||||
except models.BadFilter:
|
||||
error = 3
|
||||
messages.add_message(
|
||||
self.request,
|
||||
messages.ERROR,
|
||||
_(u"User charateristics non allowed")
|
||||
)
|
||||
except models.UserFieldNotDefined:
|
||||
error = 4
|
||||
messages.add_message(
|
||||
self.request,
|
||||
messages.ERROR,
|
||||
|
@ -307,11 +336,19 @@ class LoginView(View, LogoutMixin):
|
|||
)
|
||||
|
||||
# if gateway is set and auth failed redirect to the service without authentication
|
||||
if self.gateway:
|
||||
if self.gateway and not self.ajax:
|
||||
list(messages.get_messages(self.request)) # clean messages before leaving django
|
||||
return HttpResponseRedirect(self.service)
|
||||
|
||||
return render(self.request, settings.CAS_LOGGED_TEMPLATE, {'session': self.request.session})
|
||||
if not self.ajax:
|
||||
return render(
|
||||
self.request,
|
||||
settings.CAS_LOGGED_TEMPLATE,
|
||||
{'session': self.request.session}
|
||||
)
|
||||
else:
|
||||
data = {"status": "error", "detail": "auth", "code": error}
|
||||
return JsonResponse(self.request, data)
|
||||
|
||||
def authenticated(self):
|
||||
"""Processing authenticated users"""
|
||||
|
@ -322,24 +359,36 @@ class LoginView(View, LogoutMixin):
|
|||
)
|
||||
except models.User.DoesNotExist:
|
||||
self.logout()
|
||||
return utils.redirect_params("cas_server:login", params=self.request.GET)
|
||||
if self.ajax:
|
||||
data = {
|
||||
"status": "error",
|
||||
"detail": "login required",
|
||||
"url": utils.reverse_params("cas_server:login", params=self.request.GET)
|
||||
}
|
||||
return JsonResponse(self.request, data)
|
||||
else:
|
||||
return utils.redirect_params("cas_server:login", params=self.request.GET)
|
||||
|
||||
# if login agains a service is self.requestest
|
||||
if self.service:
|
||||
return self.service_login()
|
||||
else:
|
||||
return render(
|
||||
self.request,
|
||||
settings.CAS_LOGGED_TEMPLATE,
|
||||
{'session': self.request.session}
|
||||
)
|
||||
if self.ajax:
|
||||
data = {"status": "success", "detail": "logged"}
|
||||
return JsonResponse(self.request, data)
|
||||
else:
|
||||
return render(
|
||||
self.request,
|
||||
settings.CAS_LOGGED_TEMPLATE,
|
||||
{'session': self.request.session}
|
||||
)
|
||||
|
||||
def not_authenticated(self):
|
||||
"""Processing non authenticated users"""
|
||||
if self.service:
|
||||
try:
|
||||
service_pattern = ServicePattern.validate(self.service)
|
||||
if self.gateway:
|
||||
if self.gateway and not self.ajax:
|
||||
# clean messages before leaving django
|
||||
list(messages.get_messages(self.request))
|
||||
return HttpResponseRedirect(self.service)
|
||||
|
@ -363,7 +412,15 @@ class LoginView(View, LogoutMixin):
|
|||
messages.ERROR,
|
||||
_(u'Service %s non allowed') % self.service
|
||||
)
|
||||
return render(self.request, settings.CAS_LOGIN_TEMPLATE, {'form': self.form})
|
||||
if self.ajax:
|
||||
data = {
|
||||
"status": "error",
|
||||
"detail": "login required",
|
||||
"url": utils.reverse_params("cas_server:login", params=self.request.GET)
|
||||
}
|
||||
return JsonResponse(self.request, data)
|
||||
else:
|
||||
return render(self.request, settings.CAS_LOGIN_TEMPLATE, {'form': self.form})
|
||||
|
||||
def common(self):
|
||||
"""Part execute uppon GET and POST request"""
|
||||
|
|
Loading…
Reference in a new issue