Example #1
0
def login_begin(request, attribute_set='default'):
    """Begin an MojeID login request."""

    if mojeid_settings.MOJEID_SESSION_NEXT_PAGE_ATTR in request.session:
        del request.session[mojeid_settings.MOJEID_SESSION_NEXT_PAGE_ATTR]

    # create consumer, start login process
    consumer = MojeIDConsumer(DjangoOpenIDStore())
    openid_request = consumer.begin(create_service())

    # Request user details.
    attributes = get_attribute_query(attribute_set)
    # save settings set name for response handler
    request.session[SESSION_ATTR_SET_KEY] = attribute_set

    fetch_request = ax.FetchRequest()
    for attribute, required in attributes:
        fetch_request.add(attribute.generate_ax_attrinfo(required))

    if attributes:
        openid_request.addExtension(fetch_request)

    if mojeid_settings.MOJEID_LOGIN_METHOD != 'ANY' or \
            mojeid_settings.MOJEID_MAX_AUTH_AGE is not None:
        # set authentication method to OTP or CERT
        if mojeid_settings.MOJEID_LOGIN_METHOD == "OTP":
            auth_method = [pape.AUTH_MULTI_FACTOR]
        elif mojeid_settings.MOJEID_LOGIN_METHOD == "CERT":
            auth_method = [pape.AUTH_PHISHING_RESISTANT]
        else:
            auth_method = None

        pape_request = pape.Request(
            preferred_auth_policies=auth_method,
            max_auth_age=mojeid_settings.MOJEID_MAX_AUTH_AGE,
        )
        openid_request.addExtension(pape_request)

    # Construct the request completion URL
    return_to = request.build_absolute_uri(reverse(login_complete))

    # get 'next page' and save it to the session
    redirect_to = sanitise_redirect_url(OpenIDBackend.get_redirect_to(request))
    if redirect_to:
        request.session[mojeid_settings.MOJEID_SESSION_NEXT_PAGE_ATTR] = redirect_to

    # Realm should be always something like 'https://example.org/openid/'
    realm = getattr(settings, 'MOJEID_REALM', None)
    if not realm:
        realm = request.build_absolute_uri(reverse(top))

    # we always use POST request
    form_html = openid_request.htmlMarkup(
        realm, return_to, form_tag_attrs={'id': 'openid_message'})
    return HttpResponse(form_html, content_type='text/html; charset=UTF-8')
Example #2
0
def login_complete(request):
    # Get addres where to redirect after the login
    redirect_to = sanitise_redirect_url(
        request.session.get(mojeid_settings.MOJEID_SESSION_NEXT_PAGE_ATTR))
    attribute_set = request.session.get(SESSION_ATTR_SET_KEY, 'default')

    # clean the session
    if mojeid_settings.MOJEID_SESSION_NEXT_PAGE_ATTR in request.session:
        del request.session[mojeid_settings.MOJEID_SESSION_NEXT_PAGE_ATTR]

    if SESSION_ATTR_SET_KEY in request.session:
        del request.session[SESSION_ATTR_SET_KEY]

    # Get OpenID response and test whether it is valid

    endpoint = create_service()
    message = Message.fromPostArgs(request.REQUEST)
    consumer = MojeIDConsumer(DjangoOpenIDStore())

    try:
        openid_response = consumer.complete(
            message, endpoint, request.build_absolute_uri())
    except HTTPFetchingError:
        # if not using association and can't contact MojeID server
        return render_failure(request, errors.EndpointError())

    # Check whether the user is already logged in
    user_orig = OpenIDBackend.get_user_from_request(request)
    user_model = get_user_model()

    if openid_response.status == SUCCESS:

        try:
            if user_orig:
                # Send a signal to obtain HttpResponse
                resp = associate_user.send(
                    sender=__name__, request=request, openid_response=openid_response,
                    attribute_set=attribute_set, redirect=redirect_to
                )
                resp = [r[1] for r in resp if isinstance(r[1], HttpResponse)]
                if resp:
                    # Return first valid response
                    return resp[0]

                # Create association with currently logged in user
                OpenIDBackend.associate_openid_response(user_orig, openid_response)
            else:
                # Authenticate mojeID user.
                # Send a signal to obtain HttpResponse
                resp = authenticate_user.send(
                    sender=__name__, request=request, openid_response=openid_response,
                    attribute_set=attribute_set, redirect=redirect_to
                )
                resp = [r[1] for r in resp if isinstance(r[1], HttpResponse)]
                if resp:
                    # Return first valid response
                    return resp[0]

                # Perform a default action
                user_new = OpenIDBackend.authenticate_using_all_backends(
                    openid_response=openid_response, attribute_set=attribute_set)
                if not user_new:
                    # Failed to create a user
                    return render_failure(request, errors.UnknownUser())
                if not OpenIDBackend.is_user_active(user_new):
                    # user is deactivated
                    return render_failure(request, errors.DisabledAccount(user_new))
                # Create an association with the new user
                OpenIDBackend.associate_user_with_session(request, user_new)
        except DjangoOpenIDException as e:
            # Something went wrong
            user_id = None
            try:
                # Try to get user id
                user_id = UserOpenID.objects.get(claimed_id=openid_response.identity_url).user_id
            except (UserOpenID.DoesNotExist, user_model.DoesNotExist):
                # Report an error with identity_url
                user_login_report.send(
                    sender=__name__, request=request, username=openid_response.identity_url,
                    method='openid', success=False
                )

            # Report an error with the username
            user_login_report.send(
                sender=__name__, request=request, username=openid_response.identity_url,
                user_id=user_id, method='openid', success=False
            )

            # Render the failure page
            return render_failure(request, errors.AuthenticationFailed(e))

        response = HttpResponseRedirect(redirect_to)

        # Send signal to log the successful login attempt
        user_login_report.send(
            sender=__name__, request=request,
            user_id=user_orig.id if user_orig else user_new.id, method='openid', success=True
        )

        return response

    # Render other failures
    elif openid_response.status == FAILURE:
        user_login_report.send(
            sender=__name__, request=request, username=openid_response.identity_url,
            method='openid', success=False
        )
        return render_failure(request, errors.OpenIDAuthenticationFailed(openid_response))

    elif openid_response.status == CANCEL:
        user_login_report.send(
            sender=__name__, request=request, username=openid_response.identity_url,
            method='openid', success=False
        )
        return render_failure(request, errors.OpenIDAuthenticationCanceled())
    else:
        user_login_report.send(
            sender=__name__, request=request, username=openid_response.identity_url,
            method='openid', success=False
        )
        return render_failure(request, errors.OpenIDUnknownResponseType(openid_response))