Beispiel #1
0
def login_action(session_info, user):
    """
    Upon successful login in the IdP, store login info in the session
    and redirect back to the app that asked for authn.

    :param session_info: the SAML session info
    :type session_info: dict

    :param user: the authenticated user
    :type user: eduid_userdb.User
    """
    current_app.logger.info("User {!r} logging in.".format(user))
    session['_saml2_session_name_id'] = code(session_info['name_id'])
    session['eduPersonPrincipalName'] = user.eppn
    session['user_eppn'] = user.eppn
    loa = get_loa(current_app.config.get('AVAILABLE_LOA'), session_info)
    session['eduPersonAssurance'] = loa
    session.persist()

    # redirect the user to the view where he came from
    relay_state = request.form.get('RelayState', '/')
    current_app.logger.debug('Redirecting to the RelayState: ' + relay_state)
    response = redirect(location=relay_state)
    session.set_cookie(response)
    current_app.logger.info('Redirecting user {!r} to {!r}'.format(
        user, relay_state))
    return response
Beispiel #2
0
def schedule_action(action_key):
    """
    Schedule an action to be executed after an IdP responds to a SAML request.
    This is called just before the SAML request is sent.

    :param action_key: the key for the given action
    :type action_key: str
    """
    logger.debug('Scheduling acs action ' + action_key)
    session['post-authn-action'] = action_key
    session.persist()
Beispiel #3
0
def _reauthn(reason, session_info, user):

    current_app.logger.info("Reauthenticating user {!r} for {!r}.".format(
        user, reason))
    session['_saml2_session_name_id'] = code(session_info['name_id'])
    session[reason] = int(time())
    session.persist()

    # redirect the user to the view where he came from
    relay_state = request.form.get('RelayState', '/')
    current_app.logger.debug('Redirecting to the RelayState: ' + relay_state)
    return redirect(location=relay_state)
Beispiel #4
0
def token_login():
    current_app.logger.debug('Starting token login')
    location_on_fail = current_app.config.get(
        'TOKEN_LOGIN_FAILURE_REDIRECT_URL')
    location_on_success = current_app.config.get(
        'TOKEN_LOGIN_SUCCESS_REDIRECT_URL')

    eppn = request.form.get('eppn')
    token = request.form.get('token')
    nonce = request.form.get('nonce')
    timestamp = request.form.get('ts')
    loa = get_loa(current_app.config.get('AVAILABLE_LOA'),
                  None)  # With no session_info lowest loa will be returned

    if verify_auth_token(eppn=eppn,
                         token=token,
                         nonce=nonce,
                         timestamp=timestamp):
        try:
            user = current_app.central_userdb.get_user_by_eppn(eppn)
            if user.locked_identity.count > 0:
                # This user has previously verified their account and is not new, this should not happen.
                current_app.logger.error(
                    'Not new user {} tried to log in using token login'.format(
                        user))
                return redirect(location_on_fail)
            session['eduPersonPrincipalName'] = user.eppn
            session['user_eppn'] = user.eppn
            session['eduPersonAssurance'] = loa
            session.persist()

            response = redirect(location_on_success)
            session.set_cookie(response)
            current_app.logger.info(
                'Successful token login, redirecting user {} to {}'.format(
                    user, location_on_success))
            return response
        except current_app.central_userdb.exceptions.UserDoesNotExist:
            current_app.logger.error(
                'No user with eduPersonPrincipalName = {} found'.format(eppn))
        except current_app.central_userdb.exceptions.MultipleUsersReturned:
            current_app.logger.error(
                "There are more than one user with eduPersonPrincipalName = {}"
                .format(eppn))

    current_app.logger.info(
        'Token login failed, redirecting user to {}'.format(location_on_fail))
    return redirect(location_on_fail)
Beispiel #5
0
    def __call__(self, environ, start_response):
        next_url = get_current_url(environ)
        next_path = list(urlparse.urlparse(next_url))[2]
        whitelist = self.config.get('NO_AUTHN_URLS', [])
        for regex in whitelist:
            m = re.match(regex, next_path)
            if m is not None:
                return super(AuthnApp, self).__call__(environ, start_response)

        cookie = parse_cookie(environ)
        cookie_name = self.config.get('SESSION_COOKIE_NAME')
        if cookie and cookie_name in cookie:
            try:
                return super(AuthnApp, self).__call__(environ, start_response)
            except NoSessionDataFoundException:
                del environ['HTTP_COOKIE']  # Force relogin
                # If HTTP_COOKIE is not removed self.request_context(environ) below
                # will try to look up the Session data in the backend

        ts_url = self.config.get('TOKEN_SERVICE_URL')
        ts_url = urlparse.urljoin(ts_url, 'login')

        params = {'next': next_url}

        url_parts = list(urlparse.urlparse(ts_url))
        query = urlparse.parse_qs(url_parts[4])
        query.update(params)

        url_parts[4] = urlencode(query)
        location = urlparse.urlunparse(url_parts)

        with self.request_context(environ):

            headers = [('Location', location)]
            cookie = dump_cookie(
                cookie_name,
                session._session.token,
                max_age=int(self.config.get('PERMANENT_SESSION_LIFETIME')),
                path=self.config.get('SESSION_COOKIE_PATH'),
                domain=self.config.get('SESSION_COOKIE_DOMAIN'),
                secure=self.config.get('SESSION_COOKIE_SECURE'),
                httponly=self.config.get('SESSION_COOKIE_HTTPONLY'))
            session.persist()
            headers.append(('Set-Cookie', cookie))

            start_response('302 Found', headers)
            return []
Beispiel #6
0
def login_action(session_info, user):

    logger.info("User {!r} logging in (eduPersonPrincipalName: {!r})".format(
        user.user_id,
        user.eppn))
    session['_saml2_session_name_id'] = code(session_info['name_id'])
    session['eduPersonPrincipalName'] = user.eppn
    loa = get_loa(current_app.config.get('AVAILABLE_LOA'), session_info)
    session['eduPersonAssurance'] = loa
    session.persist()

    # redirect the user to the view where he came from
    relay_state = request.form.get('RelayState', '/')
    logger.debug('Redirecting to the RelayState: ' + relay_state)
    response = redirect(location=relay_state)
    session.set_cookie(response)
    return response
Beispiel #7
0
    def add_outstanding_query(self, came_from):
        """
        Add a SAML2 authentication query to the queries cache.
        To be used before accessing the assertion consumer service.

        :param came_from: url to redirect back the client
                          after finishing with the authn service.
        :type came_from: str

        :return: the session token corresponding to the query
        :rtype: str
        """
        with self.app.test_request_context('/login'):
            self.app.dispatch_request()
            oq_cache = OutstandingQueriesCache(session)
            oq_cache.set(session.token, came_from)
            session.persist()
            return session.token
Beispiel #8
0
    def test_logout_service_startingIDP_no_subject_id(self):

        eppn = 'hubba-bubba'
        came_from = '/afterlogin/'
        session_id = self.add_outstanding_query(came_from)
        cookie = self.dump_session_cookie(session_id)

        saml_response = auth_response(session_id, eppn)

        # Log in through IDP SAMLResponse
        with self.app.test_request_context('/saml2-acs',
                                           method='POST',
                                           headers={'Cookie': cookie},
                                           data={
                                               'SAMLResponse':
                                               base64.b64encode(saml_response),
                                               'RelayState':
                                               'testing-relay-state',
                                           }):
            response = self.app.dispatch_request()

        with self.app.test_request_context('/saml2-ls',
                                           method='POST',
                                           headers={'Cookie': cookie},
                                           data={
                                               'SAMLRequest':
                                               deflate_and_base64_encode(
                                                   logout_request(session_id)),
                                               'RelayState':
                                               'testing-relay-state',
                                           }):
            del session['_saml2_session_name_id']
            session.persist()
            response = self.app.dispatch_request()

            self.assertEqual(response.status, '302 FOUND')
            self.assertIn('testing-relay-state', response.location)