Example #1
0
def validate_oauth_token(token, request=None):
    """
    Validates the token attached to the request (SessionStorage, GET/POST)
    On every request, ask OAuth to authorize the token
    """
    # Authorization test
    user_profile = cas_profile_for_token(token)
    if not user_profile:
        return False
    username = user_profile.get("id")
    attrs = user_profile.get("attributes")
    if not username or not attrs:
        logger.info("Invalid Profile:%s does not have username/attributes" %
                    user_profile)
        return False
    # TEST 1 : Must be in the group 'atmo-user'
    # NOTE: Test 1 will be IGNORED until we can verify it returns 'entitlement'
    #  EVERY TIME!
    # if not cas_profile_contains(attrs, 'atmo-user'):
    #    raise Unauthorized("User %s is not a member of group 'atmo-user'"
    #                       % username)
    # TODO: TEST 2 : Must have an identity (?)
    if not AtmosphereUser.objects.filter(username=username):
        raise Unauthorized("User %s does not exist as an AtmosphereUser" %
                           username)
    auth_token = obtainOAuthToken(username, token)
    # logger.info("OAuthToken Obtained for %s:%s" % (username, auth_token))
    if not auth_token:
        return False
    return True
Example #2
0
def ldap_formatAttrs(ldap_attrs):
    """
    Formats attrs into a unified dict to ease in user creation
    """
    logger.info(ldap_attrs)
    try:
        return {
            'email': ldap_attrs['mail'][0],
            'firstName': ldap_attrs['givenName'][0],
            'lastName': ldap_attrs['sn'][0],
        }
    except KeyError as nokey:
        logger.exception(nokey)
        return None
Example #3
0
def ldap_formatAttrs(ldap_attrs):
    """
    Formats attrs into a unified dict to ease in user creation
    """
    logger.info(ldap_attrs)
    try:
        return {
            'email': ldap_attrs['mail'][0],
            'firstName': ldap_attrs['givenName'][0],
            'lastName': ldap_attrs['sn'][0],
        }
    except KeyError as nokey:
        logger.exception(nokey)
        return None
Example #4
0
    def authenticate(self, request):
        token_key = None
        auth = request.META.get('HTTP_AUTHORIZATION', '').split()
        if len(auth) == 2 and auth[0].lower() == "token":
            token_key = auth[1]

        if not token_key and 'token' in request.session:
            token_key = request.session['token']
        if validate_token(token_key):
            token = self.model.objects.get(key=token_key)
            logger.info("AuthToken Obtained for %s:%s" %
                        (token.user.username, token_key))
            if token.user.is_active:
                return (token.user, token)
        return None
Example #5
0
    def atmo_login(request, *args, **kwargs):
        if not request:
            logger.debug("[NOREQUEST] User is being logged out because request"
                         " is empty")
            logger.debug("%s\n%s\n%s\n%s" % (request, args, kwargs, func))
            return HttpResponseRedirect(settings.SERVER_URL + "/logout/")

        if not request.session:
            logger.debug("[NOSESSION] User is being logged out because session"
                         " object does not exist in request")
            logger.debug("%s\n%s\n%s\n%s" % (request, args, kwargs, func))
            return HttpResponseRedirect(settings.SERVER_URL + "/logout/")

        if not request.session.get('username'):
            logger.debug("[NOUSER] User is being logged out because session"
                         " did not include a username")
            logger.debug("%s\n%s\n%s\n%s" % (request, args, kwargs, func))
            return HttpResponseRedirect(settings.SERVER_URL + "/logout/")

        # logger.info('atmo_login_required session info: %s'
        #             % request.session.__dict__)
        logger.info(
            'atmo_login_required authentication: %s' %
            request.session.get('username', '<Username not in session>'))
        username = request.session.get('username', None)
        token = request.session.get('token', None)
        redirect = kwargs.get('redirect', request.get_full_path())
        emulator = request.session.get('emulated_by', None)

        if emulator:
            # logger.info("%s\n%s\n%s" % (username, redirect, emulator))
            logger.info("Test emulator %s instead of %s" %
                        (emulator, username))
            logger.debug(request.session.__dict__)
            # Authenticate the user (Force a CAS test)
            user = authenticate(username=emulator,
                                password="",
                                auth_token=token,
                                request=request)
            # AUTHORIZED STAFF ONLY
            if not user or not user.is_staff:
                return HttpResponseRedirect(settings.SERVER_URL + "/logout/")
            logger.info("Emulate success - Logging in %s" % user.username)
            django_login(request, user)
            return func(request, *args, **kwargs)

        user = authenticate(username=username,
                            password="",
                            auth_token=token,
                            request=request)
        if not user:
            logger.info("Could not authenticate user %s" % username)
            # logger.debug("%s\n%s\n%s\n%s" % (request, args, kwargs, func))
            return cas_loginRedirect(request, redirect)
        django_login(request, user)
        return func(request, *args, **kwargs)
Example #6
0
 def authenticate(self, username=None, password=None, request=None):
     """
     Return user if validated by CAS
     Return None otherwise.
     """
     # logger.debug("CASBackend -- U:%s P:%s R:%s"
     #              % (username, password, request))
     if not username:
         logger.debug("CAS Authentication skipped - No Username.")
         return None
     (success, cas_response) = cas_validateUser(username)
     logger.info("Authenticate by CAS: %s - %s %s"
                 % (username, success, cas_response))
     if not success:
         logger.debug("CAS Authentication failed - "+username)
         return None
     attributes = cas_response.attributes
     return get_or_create_user(username, attributes)
Example #7
0
 def authenticate(self, username=None, password=None, request=None):
     """
     Return user if validated by CAS
     Return None otherwise.
     """
     # logger.debug("CASBackend -- U:%s P:%s R:%s"
     #              % (username, password, request))
     if not username:
         logger.debug("CAS Authentication skipped - No Username.")
         return None
     (success, cas_response) = cas_validateUser(username)
     logger.info("Authenticate by CAS: %s - %s %s" %
                 (username, success, cas_response))
     if not success:
         logger.debug("CAS Authentication failed - " + username)
         return None
     attributes = cas_response.attributes
     return get_or_create_user(username, attributes)
Example #8
0
    def atmo_login(request, *args, **kwargs):
        if not request:
            logger.debug("[NOREQUEST] User is being logged out because request"
                         " is empty")
            logger.debug("%s\n%s\n%s\n%s" % (request, args, kwargs, func))
            return HttpResponseRedirect(settings.SERVER_URL+"/logout/")

        if not request.session:
            logger.debug("[NOSESSION] User is being logged out because session"
                         " object does not exist in request")
            logger.debug("%s\n%s\n%s\n%s" % (request, args, kwargs, func))
            return HttpResponseRedirect(settings.SERVER_URL+"/logout/")

        if not request.session.get('username'):
            logger.debug("[NOUSER] User is being logged out because session"
                         " did not include a username")
            logger.debug("%s\n%s\n%s\n%s" % (request, args, kwargs, func))
            return HttpResponseRedirect(settings.SERVER_URL+"/logout/")

        # logger.info('atmo_login_required session info: %s'
        #             % request.session.__dict__)
        logger.info('atmo_login_required authentication: %s'
                    % request.session.get('username',
                                          '<Username not in session>'))
        username = request.session.get('username', None)
        token = request.session.get('token', None)
        redirect = kwargs.get('redirect', request.get_full_path())
        emulator = request.session.get('emulated_by', None)

        if emulator:
            # logger.info("%s\n%s\n%s" % (username, redirect, emulator))
            logger.info("Test emulator %s instead of %s" %
                        (emulator, username))
            logger.debug(request.session.__dict__)
            # Authenticate the user (Force a CAS test)
            user = authenticate(username=emulator, password="",
                                auth_token=token, request=request)
            # AUTHORIZED STAFF ONLY
            if not user or not user.is_staff:
                return HttpResponseRedirect(settings.SERVER_URL+"/logout/")
            logger.info("Emulate success - Logging in %s" % user.username)
            django_login(request, user)
            return func(request, *args, **kwargs)

        user = authenticate(username=username, password="", auth_token=token,
                            request=request)
        if not user:
            logger.info("Could not authenticate user %s" % username)
            # logger.debug("%s\n%s\n%s\n%s" % (request, args, kwargs, func))
            return cas_loginRedirect(request, redirect)
        django_login(request, user)
        return func(request, *args, **kwargs)
Example #9
0
def validate_token(token, request=None):
    """
    Validates the token attached to the request (SessionStorage, GET/POST)
    If token has expired,
    CAS will attempt to reauthenticate the user and refresh token.
    Expired Tokens can be used for GET requests ONLY!
    """

    # Existence test
    try:
        auth_token = AuthToken.objects.get(key=token)
        user = auth_token.user
    except AuthToken.DoesNotExist:
        logger.info("AuthToken Retrieved:%s Does not exist." % (token, ))
        return False
    if auth_token.is_expired():
        if request and request.META['REQUEST_METHOD'] != 'GET':
            # See if the user (Or the user who is emulating a user) can be
            # re-authed.
            user_to_auth = request.session.get('emulated_by', user)
            if cas_validateUser(user_to_auth):
                # logger.debug("Reauthenticated user -- Token updated")
                auth_token.update_expiration()
                auth_token.save()
                return True
            else:
                logger.info("Token %s expired, User %s "
                            "could not be reauthenticated in CAS" %
                            (token, user))
                return False
        else:
            logger.debug(
                "Token %s EXPIRED, but allowing User %s to GET data.." %
                (token, user))
            return True
    else:
        return True
Example #10
0
def saml_validateTicket(request):
    """
    Method expects 2 GET parameters: 'ticket' & 'sendback'
    After a CAS Login:
    Redirects the request based on the GET param 'ticket'
    Unauthorized Users are redirected to '/' In the event of failure.
    Authorized Users are redirected to the GET param 'sendback'
    """

    redirect_logout_url = settings.REDIRECT_URL + "/login/"
    no_user_url = settings.REDIRECT_URL + "/no_user/"
    logger.debug('GET Variables:%s' % request.GET)
    ticket = request.GET.get('ticket', None)

    if not ticket:
        logger.info("No Ticket received in GET string "
                    "-- Logout user: %s" % redirect_logout_url)
        return HttpResponseRedirect(redirect_logout_url)

    logger.debug("ServiceValidate endpoint includes a ticket."
                 " Ticket must now be validated with SAML")

    # ReturnLocation set, apply on successful authentication

    saml_client = get_saml_client()
    saml_response = saml_client.saml_serviceValidate(ticket)
    if not saml_response.success:
        logger.debug("CAS Server did NOT validate ticket:%s"
                     " and included this response:%s"
                     % (ticket, saml_response.xml))
        return HttpResponseRedirect(redirect_logout_url)

    try:
        user = User.objects.get(username=saml_response.user)
    except User.DoesNotExist:
        return HttpResponseRedirect(no_user_url)
    auth_token = create_session_token(None, user, request)
    if auth_token is None:
        logger.info("Failed to create AuthToken")
        HttpResponseRedirect(redirect_logout_url)
    return_to = request.GET.get('sendback')
    if not return_to:
        return HttpResponse(saml_response.response,
                            content_type="text/xml; charset=utf-8")
    return_to += "?token=%s" % auth_token
    logger.info("Session token created, return to: %s" % return_to)
    return HttpResponseRedirect(return_to)
Example #11
0
def token_auth(request):
    """
    VERSION 2 AUTH
    Authentication is based on the POST parameters:
    * Username (Required)
    * Password (Not Required if CAS authenticated previously)

    NOTE: This authentication is SEPARATE from
    django model authentication
    Use this to give out tokens to access the API
    """
    logger.info('Request to auth')
    #logger.info(request)

    token = request.POST.get('token', None)

    username = request.POST.get('username', None)
    # CAS authenticated user already has session data
    # without passing any parameters
    if not username:
        username = request.session.get('username', None)

    password = request.POST.get('password', None)
    # LDAP Authenticate if password provided.
    if username and password:
        if ldap_validate(username, password):
            logger.info("LDAP User %s validated. Creating auth token"
                        % username)
            token = createAuthToken(username)
            expireTime = token.issuedTime + TOKEN_EXPIRY_TIME
            auth_json = {
                'token': token.key,
                'username': token.user.username,
                'expires': expireTime.strftime("%b %d, %Y %H:%M:%S")
            }
            return HttpResponse(
                content=json.dumps(auth_json),
                status=201,
                content_type='application/json')
        else:
            logger.debug("[LDAP] Failed to validate %s" % username)
            return HttpResponse("LDAP login failed", status=401)

    # if request.session and request.session.get('token'):
    #    logger.info("User %s already authenticated, renewing token"
    #                % username)
    #    token = validateToken(username, request.session.get('token'))

    # ASSERT: Token exists here
    if token:
        expireTime = token.issuedTime + TOKEN_EXPIRY_TIME
        auth_json = {
            'token': token.key,
            'username': token.user.username,
            'expires': expireTime.strftime("%b %d, %Y %H:%M:%S")
        }
        return HttpResponse(
            content=json.dumps(auth_json),
            content_type='application/json')

    if not username and not password:
        # The user and password were not found
        # force user to login via CAS
        return cas_loginRedirect(request, '/auth/')

    # CAS Authenticate by Proxy (Password not necessary):
    if cas_validateUser(username):
        logger.info("CAS User %s validated. Creating auth token" % username)
        token = createAuthToken(username)
        expireTime = token.issuedTime + TOKEN_EXPIRY_TIME
        auth_json = {
            'token': token.key,
            'username': token.user.username,
            'expires': expireTime.strftime("%b %d, %Y %H:%M:%S")
        }
        return HttpResponse(
            content=json.dumps(auth_json),
            content_type='application/json')
    else:
        logger.debug("[CAS] Failed to validate - %s" % username)
        return HttpResponse("CAS Login Failure", status=401)
Example #12
0
def token_auth(request):
    """
    VERSION 2 AUTH
    Authentication is based on the POST parameters:
    * Username (Required)
    * Password (Not Required if CAS authenticated previously)

    NOTE: This authentication is SEPARATE from
    django model authentication
    Use this to give out tokens to access the API
    """
    logger.info('Request to auth')
    #logger.info(request)

    token = request.POST.get('token', None)

    username = request.POST.get('username', None)
    # CAS authenticated user already has session data
    # without passing any parameters
    if not username:
        username = request.session.get('username', None)

    password = request.POST.get('password', None)
    # LDAP Authenticate if password provided.
    if username and password:
        if ldap_validate(username, password):
            logger.info("LDAP User %s validated. Creating auth token" %
                        username)
            token = createAuthToken(username)
            expireTime = token.issuedTime + TOKEN_EXPIRY_TIME
            auth_json = {
                'token': token.key,
                'username': token.user.username,
                'expires': expireTime.strftime("%b %d, %Y %H:%M:%S")
            }
            return HttpResponse(content=json.dumps(auth_json),
                                status=201,
                                content_type='application/json')
        else:
            logger.debug("[LDAP] Failed to validate %s" % username)
            return HttpResponse("LDAP login failed", status=401)

    # if request.session and request.session.get('token'):
    #    logger.info("User %s already authenticated, renewing token"
    #                % username)
    #    token = validateToken(username, request.session.get('token'))

    # ASSERT: Token exists here
    if token:
        expireTime = token.issuedTime + TOKEN_EXPIRY_TIME
        auth_json = {
            'token': token.key,
            'username': token.user.username,
            'expires': expireTime.strftime("%b %d, %Y %H:%M:%S")
        }
        return HttpResponse(content=json.dumps(auth_json),
                            content_type='application/json')

    if not username and not password:
        # The user and password were not found
        # force user to login via CAS
        return cas_loginRedirect(request, '/auth/')

    # CAS Authenticate by Proxy (Password not necessary):
    if cas_validateUser(username):
        logger.info("CAS User %s validated. Creating auth token" % username)
        token = createAuthToken(username)
        expireTime = token.issuedTime + TOKEN_EXPIRY_TIME
        auth_json = {
            'token': token.key,
            'username': token.user.username,
            'expires': expireTime.strftime("%b %d, %Y %H:%M:%S")
        }
        return HttpResponse(content=json.dumps(auth_json),
                            content_type='application/json')
    else:
        logger.debug("[CAS] Failed to validate - %s" % username)
        return HttpResponse("CAS Login Failure", status=401)
Example #13
0
def cas_validateTicket(request):
    """
    Method expects 2 GET parameters: 'ticket' & 'sendback'
    After a CAS Login:
    Redirects the request based on the GET param 'ticket'
    Unauthorized Users are redirected to '/' In the event of failure.
    Authorized Users are redirected to the GET param 'sendback'
    """

    redirect_logout_url = settings.REDIRECT_URL + "/login/"
    no_user_url = settings.REDIRECT_URL + "/no_user/"
    logger.debug('GET Variables:%s' % request.GET)
    ticket = request.GET.get('ticket', None)
    sendback = request.GET.get('sendback', None)

    if not ticket:
        logger.info("No Ticket received in GET string "
                    "-- Logout user: %s" % redirect_logout_url)
        return HttpResponseRedirect(redirect_logout_url)

    logger.debug("ServiceValidate endpoint includes a ticket."
                 " Ticket must now be validated with CAS")

    # ReturnLocation set, apply on successful authentication

    caslib = get_cas_client()
    caslib.service_url = _set_redirect_url(sendback, request)

    cas_response = caslib.cas_serviceValidate(ticket)
    if not cas_response.success:
        logger.debug("CAS Server did NOT validate ticket:%s"
                     " and included this response:%s (Err:%s)"
                     % (ticket, cas_response.object, cas_response.error_str))
        return HttpResponseRedirect(redirect_logout_url)
    if not cas_response.user:
        logger.debug("User attribute missing from cas response!"
                     "This may require a fix to caslib.py")
        return HttpResponseRedirect(redirect_logout_url)
    if not cas_response.proxy_granting_ticket:
        logger.error("""Proxy Granting Ticket missing!
        Atmosphere requires CAS proxy as a service to authenticate users.
            Possible Causes:
              * ServerName variable is wrong in /etc/apache2/apache2.conf
              * Proxy URL does not exist
              * Proxy URL is not a valid RSA-2/VeriSigned SSL certificate
              * /etc/host and hostname do not match machine.""")
        return HttpResponseRedirect(redirect_logout_url)

    updated = updateUserProxy(
        cas_response.user, cas_response.proxy_granting_ticket)
    if not updated:
        return HttpResponseRedirect(redirect_logout_url)
    logger.info("Updated proxy for <%s> -- Auth success!" % cas_response.user)

    try:
        user = User.objects.get(username=cas_response.user)
    except User.DoesNotExist:
        return HttpResponseRedirect(no_user_url)
    auth_token = create_session_token(None, user, request)
    if auth_token is None:
        logger.info("Failed to create AuthToken")
        HttpResponseRedirect(redirect_logout_url)
    return_to = request.GET['sendback']
    logger.info("Session token created, User logged in, return to: %s"
                % return_to)
    return HttpResponseRedirect(return_to)