Exemple #1
0
def login_begin(request, attribute_set='default', form_class=OpenIDLoginForm):
    """Begin an OpenID login request, possibly asking for an identity URL."""
    redirect_to = OpenIDBackend.get_redirect_to(request)

    openid_url = getattr(settings, 'MOJEID_ENDPOINT_URL', MOJEID_ENDPOINT_URL)

    login_form = form_class(data=request.POST)
    if login_form.is_valid():
        openid_url = login_form.cleaned_data['openid_identifier']

    consumer = make_consumer(request)
    
    # Set response handler (define the settings set)
    consumer.session['attribute_set'] = attribute_set

    # Set the language
    consumer.session['stored_lang'] = request.POST.get('lang', get_language())
    request.session.save()

    try:
        openid_request = consumer.begin(openid_url)
    except DiscoveryFailure as exc:
        return render_failure(request, errors.DiscoveryError(exc))

    # Request user details.
    attributes = get_attribute_query(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 getattr(settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False):
        preferred_auth = [
            pape.AUTH_MULTI_FACTOR_PHYSICAL,
        ]
        pape_request = pape.Request(preferred_auth_policies=preferred_auth)
        openid_request.addExtension(pape_request)

    # Construct the request completion URL, including the page we
    # should redirect to.
    return_to = request.build_absolute_uri(reverse(login_complete))
    if redirect_to:
        if '?' in return_to:
            return_to += '&'
        else:
            return_to += '?'
        # Django gives us Unicode, which is great.  We must encode URI.
        # urllib enforces str. We can't trust anything about the default
        # encoding inside  str(foo) , so we must explicitly make foo a str.
        return_to += urlencode(
            {OpenIDBackend.get_redirect_field_name(): redirect_to.encode("UTF-8")})

    return render_openid_request(request, openid_request, return_to)
Exemple #2
0
def authenticate_user(**kwargs):
    """ Display user forms prefilled with data from mojeID """
    request = kwargs['request']
    openid_response = kwargs['openid_response']
    redirect_to = kwargs['redirect']
    user_model = get_user_model()

    # Get the user
    try:
        # Authenticate user
        user_openid = UserOpenID.objects.get(
            claimed_id__exact=openid_response.identity_url)
        try:
            user = user_model.objects.get(pk=user_openid.user_id)
            if OpenIDBackend.is_user_authenticated(user):
                OpenIDBackend.associate_user_with_session(request, user)
        except user_model.DoesNotExist:
            pass

        # Update all updatable attributes
        #attrs = OpenIDBackend.update_user_from_openid(user_id, openid_response)
        # Or Just display the updatable attributes to be updated
        attrs = OpenIDBackend.get_model_changes(openid_response,
                                                only_updatable=True)

        # Set url path
        path = reverse(display_user)

    except UserOpenID.DoesNotExist:
        # Create user

        # Get attributes for the new User model
        attrs = OpenIDBackend.get_model_changes(openid_response)

        # Set url path
        path = reverse(new_user)

    # set the params for redirect
    qd = QueryDict('').copy()
    params = attrs.get(get_user_model(), {})
    params['next'] = redirect_to
    if 'user_id_field_name' in params:
        del params['user_id_field_name']
    qd.update(params)
    # TODO claimed_id as a param!

    url = "%s?%s" % (path, qd.urlencode())
    return redirect(url)
Exemple #3
0
def authenticate_user(**kwargs):
    """ Display user forms prefilled with data from mojeID """
    request = kwargs['request']
    openid_response = kwargs['openid_response']
    redirect_to = kwargs['redirect']
    user_model = get_user_model()

    # Get the user
    try:
        # Authenticate user
        user_openid = UserOpenID.objects.get(
            claimed_id__exact=openid_response.identity_url)
        try:
            user = user_model.objects.get(pk=user_openid.user_id)
            if OpenIDBackend.is_user_authenticated(user):
                OpenIDBackend.associate_user_with_session(request, user)
        except user_model.DoesNotExist:
            pass

        # Update all updatable attributes
        #attrs = OpenIDBackend.update_user_from_openid(user_id, openid_response)
        # Or Just display the updatable attributes to be updated
        attrs = OpenIDBackend.get_model_changes(openid_response, only_updatable=True)

        # Set url path
        path = reverse(display_user)

    except UserOpenID.DoesNotExist:
        # Create user

        # Get attributes for the new User model
        attrs = OpenIDBackend.get_model_changes(openid_response)

        # Set url path
        path = reverse(new_user)

    # set the params for redirect
    qd = QueryDict('').copy()
    params = attrs.get(get_user_model(), {})
    params['next'] = redirect_to
    if 'user_id_field_name' in params:
        del params['user_id_field_name']
    qd.update(params)
    # TODO claimed_id as a param!

    url = "%s?%s" % (path, qd.urlencode())
    return redirect(url)
Exemple #4
0
def login(request):
    # Get the redirect field from url
    redirect = OpenIDBackend.get_redirect_to(request)

    # If the redirect is not in url get the defualt
    redirect = redirect if redirect else getattr(settings, "LOGIN_REDIRECT_URL", None)

    return render(request, 'login.html', {'redirect': redirect})
Exemple #5
0
def login(request):
    # Get the redirect field from url
    redirect = OpenIDBackend.get_redirect_to(request)

    # If the redirect is not in url get the defualt
    redirect = redirect if redirect else getattr(settings,
                                                 "LOGIN_REDIRECT_URL", None)

    return render(request, 'login.html', {'redirect': redirect})
Exemple #6
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')
Exemple #7
0
def disassociate(request):
    """
        Disassociate current user with OpenID
    """

    # Get the User
    user = OpenIDBackend.get_user_from_request(request)
    if not user:
        raise Http404

    # Get OpenID association
    association = OpenIDBackend.get_user_association(user)
    if not association:
        raise Http404

    # Remove the association
    association.delete()

    # Redirect back
    redirect = OpenIDBackend.get_redirect_to(request)
    redirect = redirect if redirect else getattr(settings, 'LOGIN_REDIRECT_URL', '/')
    return HttpResponseRedirect(sanitise_redirect_url(redirect))
Exemple #8
0
def disassociate(request):
    """
        Disassociate current user with OpenID
    """

    # Get the User
    user = OpenIDBackend.get_user_from_request(request)
    if not user:
        raise Http404

    # Get OpenID association
    association = OpenIDBackend.get_user_association(user)
    if not association:
        raise Http404

    # Remove the association
    association.delete()

    # Redirect back
    redirect = OpenIDBackend.get_redirect_to(request)
    redirect = redirect if redirect else getattr(settings, 'LOGIN_REDIRECT_URL', '/')
    return HttpResponseRedirect(sanitise_redirect_url(redirect))
Exemple #9
0
def index(request):
    extra = None
    user = None
    if request.user.is_authenticated():
        user = request.user
        if request.user.userextraattributes_set.exists():
            extra = request.user.userextraattributes_set.all()[0]

    return render(
        request, 'index.html', {
            'user': user,
            'association': OpenIDBackend.get_user_association(user),
            'extra': extra,
            'attribute_set': 'default',
        })
Exemple #10
0
def login_show(request, login_template='openid/login.html',
               associate_template='openid/associate.html',
               form_class=OpenIDLoginForm):
    """
    Render a template to show the login/associate form form.
    """

    redirect_to = OpenIDBackend.get_redirect_to(request)

    login_form = form_class(request.POST or None)

    user = OpenIDBackend.get_user_from_request(request)

    template_name = associate_template if user else login_template

    return render_to_response(
        template_name,
        {
            'form': login_form,
            'action': reverse('openid-init'),
            OpenIDBackend.get_redirect_field_name(): redirect_to
        },
        context_instance=RequestContext(request)
    )
Exemple #11
0
def index(request):
    extra = None
    user = None
    if request.user.is_authenticated():
        user = request.user
        if request.user.userextraattributes_set.exists():
            extra = request.user.userextraattributes_set.all()[0]

    return render(request, 'index.html',
                  {
                      'user': user,
                      'association': OpenIDBackend.get_user_association(user),
                      'extra': extra,
                      'attribute_set': 'default',
                  }
    )
Exemple #12
0
def associate_user(**kwargs):
    """ Display associate forms prefilled with data from mojeID """
    request = kwargs['request']
    openid_response = kwargs['openid_response']
    redirect_to = kwargs['redirect']
    claimed_id = openid_response.endpoint.claimed_id
    user_associated = None
    claimed_associated = None

    # Check whether the claimed_id is already associated
    if UserOpenID.objects.filter(claimed_id__exact=claimed_id).exists():
        path = reverse(display_disassociate)
        user_associated = User.objects.get(pk=UserOpenID.objects.get(
            claimed_id__exact=claimed_id).user_id)
    else:
        if UserOpenID.objects.filter(user_id=request.user.id).exists():
            path = reverse(display_disassociate)
            claimed_associated = UserOpenID.objects.get(
                user_id=request.user.id).claimed_id
        else:
            path = reverse(display_associate)
            # Associate the user
            #OpenIDBackend.associate_openid_response(request.user, openid_response)

    # Update all updatable attributes
    #attrs = OpenIDBackend.update_user_from_openid(user_id, openid_response)
    # Or Just display the updatable attributes to be updated
    attrs = OpenIDBackend.get_model_changes(openid_response,
                                            only_updatable=True)

    # set the params for redirect
    qd = QueryDict('').copy()
    params = attrs.get(User, {})
    params['next'] = redirect_to
    params['claimed_id'] = claimed_id
    if user_associated:
        params['user_associated'] = user_associated
    if claimed_associated:
        params['claimed_associated'] = claimed_associated
    if 'user_id_field_name' in params:
        del params['user_id_field_name']
    qd.update(params)

    url = "%s?%s" % (path, qd.urlencode())
    return redirect(url)
Exemple #13
0
def associate_user(**kwargs):
    """ Display associate forms prefilled with data from mojeID """
    request = kwargs['request']
    openid_response = kwargs['openid_response']
    redirect_to = kwargs['redirect']
    claimed_id = openid_response.endpoint.claimed_id
    user_associated = None
    claimed_associated = None

    # Check whether the claimed_id is already associated
    if UserOpenID.objects.filter(claimed_id__exact=claimed_id).exists():
        path = reverse(display_disassociate)
        user_associated = User.objects.get(pk=UserOpenID.objects.get(
            claimed_id__exact=claimed_id).user_id)
    else:
        if UserOpenID.objects.filter(user_id=request.user.id).exists():
            path = reverse(display_disassociate)
            claimed_associated = UserOpenID.objects.get(user_id=request.user.id).claimed_id
        else:
            path = reverse(display_associate)
            # Associate the user
            #OpenIDBackend.associate_openid_response(request.user, openid_response)

    # Update all updatable attributes
    #attrs = OpenIDBackend.update_user_from_openid(user_id, openid_response)
    # Or Just display the updatable attributes to be updated
    attrs = OpenIDBackend.get_model_changes(openid_response, only_updatable=True)

    # set the params for redirect
    qd = QueryDict('').copy()
    params = attrs.get(User, {})
    params['next'] = redirect_to
    params['claimed_id'] = claimed_id
    if user_associated:
        params['user_associated'] = user_associated
    if claimed_associated:
        params['claimed_associated'] = claimed_associated
    if 'user_id_field_name' in params:
        del params['user_id_field_name']
    qd.update(params)

    url = "%s?%s" % (path, qd.urlencode())
    return redirect(url)
Exemple #14
0
def registration(request, attribute_set='default',
                 template_name='openid/registration_form.html',
                 form_class=OpenIDLoginForm):
    """ Try to submit all the registration attributes for mojeID registration"""

    registration_url = getattr(settings, 'MOJEID_REGISTRATION_URL',
                               MOJEID_REGISTRATION_URL)

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

    user = OpenIDBackend.get_user_from_request(request)
    user_id = user.pk if user else None

    # Create Nonce
    nonce = Nonce(server_url=realm, user_id=user_id)
    nonce.save()

    fields = []
    attributes = [x for x in get_attributes(attribute_set) if x.type == 'attribute']
    # Append attributes to creation request if user is valid
    if user:
        for attribute in attributes:
            form_attr = attribute.registration_form_attrs_html(user_id)
            if form_attr:
                fields.append(form_attr)

    # Render the redirection template
    return render_to_response(
        template_name,
        {
            'fields': fields,
            'action': registration_url,
            'realm': realm,
            'nonce': nonce.registration_nonce,
        },
        context_instance=RequestContext(request)
    )
Exemple #15
0
def registration(request, attribute_set='default',
                 template_name='openid/registration_form.html'):
    """ Try to submit all the registration attributes for mojeID registration"""

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

    user = OpenIDBackend.get_user_from_request(request)
    user_id = user.pk if user else None

    # Create Nonce
    nonce = Nonce(server_url=realm, user_id=user_id,
                  timestamp=time.time(), salt=randomString(35, NONCE_CHARS))
    nonce.save()

    fields = []
    attributes = [x for x in get_attributes(attribute_set) if x.type == 'attribute']
    # Append attributes to creation request if user is valid
    if user:
        for attribute in attributes:
            form_attr = attribute.registration_form_attrs_html(user_id)
            if form_attr:
                fields.append(form_attr)

    # Render the redirection template
    return render_to_response(
        template_name,
        {
            'fields': fields,
            'action': get_registration_url(),
            'realm': realm,
            'nonce': nonce.registration_nonce,
        },
        context_instance=RequestContext(request)
    )
Exemple #16
0
def assertion(request):
    """
    mojeID server connects here to propagate a response to the registration
    """
    def _reject(request, error):
        """ Reject response """
        return HttpResponse(dictToKV({'mode': 'reject', 'reason': error}))

    def _accept(request):
        """ Accept response """
        return HttpResponse(dictToKV({'mode': 'accept'}))

    # Accept only post
    if not request.method == 'POST':
        return _reject(request, Assertion.ErrorString.BAD_REQUEST)

    # Accept only valid status
    status = request.POST.get('status', None)
    if not status:
        return _reject(request, Assertion.ErrorString.MISSING_STATUS)
    if not status in Assertion.StatusCodes:
        return _reject(request, Assertion.ErrorString.INVALID_STATUS)

    # TODO check whether this request is from mojeID server and uses https with a proper certificate

    # Test calimed ID
    claimed_id = request.POST.get('claimed_id')
    if not claimed_id:
        return _reject(request, Assertion.ErrorString.MISSING_CLAIMED_ID)

    # The user was registered for mojeID
    if status == Assertion.StatusCodes.REGISTERED:
        registration_nonce = request.POST.get('registration_nonce')
        if registration_nonce is None:
            return _reject(request, Assertion.ErrorString.MISSING_NONCE)

        # check nonce
        try:
            nonce = Nonce.get_registration_nonce(registration_nonce)
        except Nonce.DoesNotExist:
            return _reject(request, Assertion.ErrorString.INVALID_NONCE)

        user_id = nonce.user_id
        nonce.delete()

        # Fetch the user
        user_model = get_user_model()
        try:
            user = user_model.objects.get(pk=user_id)
            # Create association
            OpenIDBackend.associate_openid(user, claimed_id)
        except (user_model.DoesNotExist, IdentityAlreadyClaimed):
            # Don't associte the user when the user doesn't exist or is already claimed
            # And assume that server sent us a valid claimed_id
            #
            # Note that user might been deleted before this assertion is triggered
            # Or the newly created mojeID account might been already associated
            # with a local account by the client
            #
            # Both of these cases are not considered as errors
            pass

    return _accept(request)
Exemple #17
0
def login_complete(request):
    # Get addres where to redirect after the login
    redirect_to = sanitise_redirect_url(OpenIDBackend.get_redirect_to(request))

    # Get OpenID response and test whether it is valid
    attribute_set, lang, openid_response = parse_openid_response(request)

    # Set language
    activate_lang(lang)

    if not openid_response:
        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))
Exemple #18
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))
Exemple #19
0
def assertion(request):
    """
    mojeID server connects here to propagate a response to the registration
    """
    def _reject(request, error):
        """ Reject response """
        return HttpResponse(dictToKV({'mode': 'reject', 'reason': error}))

    def _accept(request):
        """ Accept response """
        return HttpResponse(dictToKV({'mode': 'accept'}))

    # Accept only post
    if not request.method == 'POST':
        return _reject(request, Assertion.ErrorString.BAD_REQUEST)

    # Accept only valid status
    status = request.POST.get('status', None)
    if not status:
        return _reject(request, Assertion.ErrorString.MISSING_STATUS)
    if status not in Assertion.StatusCodes:
        return _reject(request, Assertion.ErrorString.INVALID_STATUS)

    # TODO check whether this request is from mojeID server and uses https with a proper certificate

    # Test calimed ID
    claimed_id = request.POST.get('claimed_id')
    if not claimed_id:
        return _reject(request, Assertion.ErrorString.MISSING_CLAIMED_ID)

    # The user was registered for mojeID
    if status == Assertion.StatusCodes.REGISTERED:
        registration_nonce = request.POST.get('registration_nonce')
        if registration_nonce is None:
            return _reject(request, Assertion.ErrorString.MISSING_NONCE)

        # check nonce
        try:
            nonce = Nonce.get_registration_nonce(registration_nonce)
        except Nonce.DoesNotExist:
            return _reject(request, Assertion.ErrorString.INVALID_NONCE)

        user_id = nonce.user_id
        nonce.delete()

        # Try to associate the user with mojeID
        if user_id:
            # Fetch the user
            user_model = get_user_model()
            try:
                user = user_model.objects.get(pk=user_id)
                # Create association
                OpenIDBackend.associate_openid(user, claimed_id)
            except (user_model.DoesNotExist, IdentityAlreadyClaimed):
                # Don't associte the user when the user doesn't exist or is already claimed
                # And assume that server sent us a valid claimed_id
                #
                # Note that user might been deleted before this assertion is triggered
                # Or the newly created mojeID account might been already associated
                # with a local account by the client
                #
                # Both of these cases are not considered as errors
                pass

    return _accept(request)