Open Darinth opened 4 years ago
from django.shortcuts import redirect
from django.utils.datastructures import MultiValueDictKeyError
from mama_cas.cas import validate_service_ticket
from mama_cas.exceptions import ValidationError
import logging
logger = logging.getLogger(__name__)
class StripCasTicketMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
try:
ticket_id = request.GET["ticket"]
except MultiValueDictKeyError:
return self.get_response(request)
try:
st, attributes, pgt = validate_service_ticket(request.path, ticket_id, pgturl=None, renew=None)
except ValidationError as e:
logger.warning("%s %s" % (e.code, e))
new_query = request.GET.copy()
new_query.pop("ticket")
if len(new_query) > 0:
return redirect(request.path + "?" + new_query.urlencode())
else:
return redirect(request.path)
For reference, that's the piece of middleware I've written to consume tickets when they happen to be present. If anybody more familiar with mama cas is willing to look at it to tell me if I'm doing anything obviously dangerous, I'd appreciate it. I expect that I'll need to use something else for the service URL once service URL validating is turned on. I don't think mama cas will appreciate the relative URLs I'm using at the moment.
@Darinth I'm curious about if you tried to configure the same application as a server using mama-cas and a client using django-cas-ng, and which problems you had while doing so.
@manelclos I had not, though I contemplated doing so. The main reason I did not do so was due to an expected problem, though I don't know for certain how it'd all run together. Essentially I'd expect to run into issues with Django-cas-ng and mama-cas fighting, because both of them want to control the session user.
Essentially, I'd expect that if app A wants a user to log in and forwards them to django-cas-ng which then forwards them to mama-cas where they log in, they're now logged in since mama-cas shares login/user information with the rest of the django server, so when it gets forwarded back over to cas-ng to handle the new login, I have no clue how it'll react to the fact that the user they're now supposed to log in is already logged in.
@Darinth not really, they won't fight at all. Consider this scenario:
I used that in the past without problems.
The fact I don't use the CAS login on the CAS app is because in the event you run into problems with the CAS login, you want an easy way to login into the CAS app, like the admin page. You can always style the admin login page like the cas one or vice versa.
Also, the CAS app is an important piece and I think it should only have that responsibility. After all, users only see the login page, everything else are redirects and requests behind the scenes. You can easily separate whatever you want to do into some other app.
But anyway, I'd love to hear about configuration problems if you try django-mama-cas + django-cas-ng in the same app. I don't foresee any problem.
@manelclos I'll give it a shot. I was mostly concerned issues about what cas-ng was going to do when it received tickets to login users who're already been logged in. Still seems like a bit of overkill to to install a second apps to handle local app login, and styling the CAS/admin login pages to look like each other is very anti-DRY so I'd rather only have to worry about maintaining one login page. But if cas-ng and mama-cas being installed on the same django project will respond gracefully I'm good.
So, ultimately, django-cas-ng is a bust... because I don't actually have the necessary toolchain to install lxml without manually compiling libxml2 and libxslt (which require compiling zlib and iconv as well) on the command line.
On windows lxml doesn't install easily through pip, it wants to run a manual compilation of C code with the visual studio build tools. There are no precompiled visual studio libraries for libxml and libxslt (there may be for zlib/iconv, I didn't look especially hard for those) which means compiling them, I don't have access to visual studio and the company I work for doesn't qualify for the community version. I'll probably get a copy of visual studio at some point, but paying for a license for visual studio right now just to compile a C++ library to be able to install django-cas-ng seems a bit... overkill when honestly I think there are better methods. I've take a look at mama-cas' login view and am probably going to just make the modification to allow it to perform logins without ticket generation. At this point... that modification actually seems far less work than trying to go through the process needed to install lxml on windows. And honestly will probably produce a product I'm happier with.
@Darinth sounds fair. I'd be using Docker to avoid the compilation problems, if possible.
PR Submitted #94
FYI on the unlikely offchance that anybody sees my middleware posted above, don't use it. While it could be modified to work still, it causes issues with at least the MAMA_CAS_ALLOW_AUTH_WARN
setting by stripping off the ticket from the warn page before it can be forwarded.
Hi @Darinth, just curious, if you have problems with django-cas-ng, which library are you using on your clients?
The CAS implementation was setup for third party platform implementation, not for use with other django apps unfortunately. While I suspect that at some point we may want to integrate other django apps, that's a bridge I'll have to worry about when I get there and will probably involve acquiring a license for visual studio and compiling those C libraries unless there's another CAS client implementation for django that doesn't involve them.
Some capability to utilize mama cas to perform sign on without ticket generation would be a nice enhancement. It would allow the CAS login page to be used as a 'local' website login in addition to it's usage as a CAS provider. Right now, I've achieved this through a little bit of brute force by using the login_required django decorator to force them over to CAS' login page with the correct service URL, which once logged in will successfully send them back to the original page but creates a service ticket and places that ticket in the URL. To combat this, I ended up writing a short piece of middleware that just checks for CAS tickets and if present A: consumes the ticket to invalidate it and B: forwards them back to the correct page without the CAS ticket number present in the url query.