jbittel / django-mama-cas

A Django Central Authentication Service (CAS) single sign-on server
BSD 3-Clause "New" or "Revised" License
396 stars 112 forks source link

Sign on without ticket generation #93

Open Darinth opened 4 years ago

Darinth commented 4 years ago

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.

Darinth commented 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.

manelclos commented 4 years ago

@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.

Darinth commented 4 years ago

@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.

manelclos commented 4 years ago

@Darinth not really, they won't fight at all. Consider this scenario:

  1. I'm not logged into any app or cas server
  2. I login into the admin of the cas server using normal admin login
  3. I try to login into app X that uses the cas server
  4. I'm redirected to the cas server, and because I'm already logged in into the cas server (I have a valid cookie that autenticates me), I get redirected and automagically login into app X.

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.

Darinth commented 4 years ago

@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.

Darinth commented 4 years ago

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.

manelclos commented 4 years ago

@Darinth sounds fair. I'd be using Docker to avoid the compilation problems, if possible.

Darinth commented 4 years ago

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.

manelclos commented 4 years ago

Hi @Darinth, just curious, if you have problems with django-cas-ng, which library are you using on your clients?

Darinth commented 4 years ago

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.