Пример #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 {} 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 = verify_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 {} to {!r}'.format(
        user, relay_state))
    return response
Пример #2
0
def logout_service():
    """SAML Logout Response endpoint
    The IdP will send the logout response to this view,
    which will process it with pysaml2 help and log the user
    out.
    Note that the IdP can request a logout even when
    we didn't initiate the process as a single logout
    request started by another SP.
    """
    current_app.logger.debug('Logout service started')

    state = StateCache(session)
    identity = IdentityCache(session)
    client = Saml2Client(current_app.saml2_config,
                         state_cache=state,
                         identity_cache=identity)

    logout_redirect_url = current_app.config.get('SAML2_LOGOUT_REDIRECT_URL')
    next_page = session.get('next', logout_redirect_url)
    next_page = request.args.get('next', next_page)
    next_page = request.form.get('RelayState', next_page)
    next_page = verify_relay_state(next_page, logout_redirect_url)

    if 'SAMLResponse' in request.form:  # we started the logout
        current_app.logger.debug('Receiving a logout response from the IdP')
        response = client.parse_logout_request_response(
            request.form['SAMLResponse'], BINDING_HTTP_REDIRECT)
        state.sync()
        if response and response.status_ok():
            session.clear()
            return redirect(next_page)
        else:
            current_app.logger.error('Unknown error during the logout')
            abort(400)

    # logout started by the IdP
    elif 'SAMLRequest' in request.form:
        current_app.logger.debug('Receiving a logout request from the IdP')
        subject_id = _get_name_id(session)
        if subject_id is None:
            current_app.logger.warning(
                'The session does not contain the subject id for user {0} '
                'Performing local logout'.format(
                    session['eduPersonPrincipalName']))
            session.clear()
            return redirect(next_page)
        else:
            http_info = client.handle_logout_request(
                request.form['SAMLRequest'],
                subject_id,
                BINDING_HTTP_REDIRECT,
                relay_state=request.form['RelayState'])
            state.sync()
            location = get_location(http_info)
            session.clear()
            return redirect(location)
    current_app.logger.error('No SAMLResponse or SAMLRequest parameter found')
    abort(400)
Пример #3
0
def logout():
    """
    SAML Logout Request initiator.
    This view initiates the SAML2 Logout request
    using the pysaml2 library to create the LogoutRequest.
    """
    eppn = session.get('user_eppn')

    if eppn is None:
        current_app.logger.info(
            'Session cookie has expired, no logout action needed')
        location = current_app.config.get('SAML2_LOGOUT_REDIRECT_URL')
        return redirect(location)

    user = current_app.central_userdb.get_user_by_eppn(eppn)

    current_app.logger.debug('Logout process started for user {}'.format(user))
    state = StateCache(session)
    identity = IdentityCache(session)

    client = Saml2Client(current_app.saml2_config,
                         state_cache=state,
                         identity_cache=identity)

    # The user doesn't have a SAML2 NameID in the session
    # after a token login from Signup into Dashboard.
    subject_id = _get_name_id(session)
    if subject_id is None:
        current_app.logger.warning('The session does not contain '
                                   'the subject id for user {}'.format(user))
        session.clear()
        location = current_app.config.get('SAML2_LOGOUT_REDIRECT_URL')

    else:
        logouts = client.global_logout(subject_id)
        loresponse = logouts.values()[0]
        # loresponse is a dict for REDIRECT binding, and LogoutResponse for SOAP binding
        if isinstance(loresponse, LogoutResponse):
            if loresponse.status_ok():
                current_app.logger.debug(
                    'Performing local logout for {}'.format(user))
                session.clear()
                location = current_app.config.get('SAML2_LOGOUT_REDIRECT_URL')
                location = verify_relay_state(
                    request.form.get('RelayState', location), location)
                return redirect(location)
            else:
                abort(500)
        headers_tuple = loresponse[1]['headers']
        location = headers_tuple[0][1]
        current_app.logger.info(
            'Redirecting to {!r} to continue the logout process '
            'for user {}'.format(location, user))

    state.sync()
    return redirect(location)
Пример #4
0
def _reauthn(reason, session_info, user):

    current_app.logger.info("Reauthenticating user {} 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 = verify_relay_state(request.form.get('RelayState', '/'))
    current_app.logger.debug('Redirecting to the RelayState: ' + relay_state)
    return redirect(location=relay_state)
Пример #5
0
def _authn(action, force_authn=False):
    redirect_url = current_app.config.get('SAML2_LOGIN_REDIRECT_URL', '/')
    relay_state = verify_relay_state(request.args.get('next', redirect_url),
                                     redirect_url)
    idps = current_app.saml2_config.getattr('idp')
    assert len(idps) == 1
    idp = idps.keys()[0]
    idp = request.args.get('idp', idp)
    loa = request.args.get('required_loa', None)
    authn_request = get_authn_request(current_app.config,
                                      session,
                                      relay_state,
                                      idp,
                                      required_loa=loa,
                                      force_authn=force_authn)
    schedule_action(action)
    current_app.logger.info('Redirecting the user to the IdP for ' + action)
    return redirect(get_location(authn_request))