def test_authenticated_user__authenticated(self):
        from webidentity.views.user import authenticated_user

        self.config.testing_securitypolicy(userid=u"dokai")
        session = DBSession()

        user = User("dokai", "secret", "*****@*****.**")
        session.add(user)

        request = testing.DummyRequest()
        self.assertEquals(user, authenticated_user(request))
Esempio n. 2
0
def get_ax_attributes(request):
    """Returns a dictionary of type_uri => value mappings containing the AX
    attributes for the currently authenticated user.
    """
    user = authenticated_user(request)
    if user is None:
        return {}

    session = DBSession()
    # TODO: Should we convert persona_id to an integer first?
    persona = session.query(Persona)\
                .join(User)\
                .filter(User.id == user.id)\
                .filter(Persona.id == request.params.get('persona', ''))\
                .first()
    if persona is None:
        return {}

    # Get the attribute values from the selected persona.
    return dict((a.type_uri, a.value) for a in persona.attributes)
    def test_authenticated_user__authenticated_model_missing(self):
        from webidentity.views.user import authenticated_user

        self.config.testing_securitypolicy(userid=u"dokai")
        request = testing.DummyRequest()
        self.failUnless(authenticated_user(request) is None)
    def test_authenticated_user__anonymous(self):
        from webidentity.views.user import authenticated_user

        request = testing.DummyRequest()
        self.failUnless(authenticated_user(request) is None)
Esempio n. 5
0
def confirm(request):
    """Confirmation for an OpenID authentication request."""
    user = authenticated_user(request)
    if user is not None and 'form.submitted' in request.params:
        if request.POST.get('csrf_token') != request.session.get_csrf_token():
            raise Forbidden

        session = DBSession()
        result = session.query(CheckIdRequest)\
                    .filter_by(key=request.environ.get('repoze.browserid', ''))\
                    .first()

        if result is not None:
            openid_request = result.request
            session.delete(result)
        else:
            # TODO: Return an error message
            return HTTPBadRequest('Invalid confirmation request')

        if 'accept' in request.params:
            ax_attributes = get_ax_attributes(request)

            visit = session.query(VisitedSite)\
                        .join(User)\
                        .filter(User.id == user.id)\
                        .filter(VisitedSite.trust_root == openid_request.trust_root)\
                        .first()
            if visit is None:
                # This is the first time the user is visiting this RP
                visit = VisitedSite(openid_request.trust_root)
                user.visited_sites.append(visit)

            visit.remember = 'remember' in request.params

            try:
                persona_id = int(request.params.get('persona'))
                # Make sure that the referenced persona actually belongs to the user
                persona = session.query(Persona)\
                            .join(User)\
                            .filter(User.id == user.id)\
                            .filter(Persona.id == persona_id)\
                            .first()
                if persona is not None:
                    visit.persona = persona
            except (TypeError, ValueError):
                pass

            session.add(visit)

            identity = identity_url(request, user.username)
            openid_response = openid_request.answer(True, identity=identity)
            add_ax_response(openid_request, openid_response, ax_attributes)
            add_sreg_response(openid_request, openid_response, ax_attributes)

            if visit.remember:
                log_activity(request, Activity.AUTHORIZE, openid_request.trust_root)
            else:
                log_activity(request, Activity.AUTHORIZE_ONCE, openid_request.trust_root)

        else:
            log_activity(request, Activity.DENY, openid_request.trust_root)
            openid_response = openid_request.answer(False)

        store = AlchemyStore(session)
        openid_server = server.Server(store, route_url('openid_endpoint', request))

        response = webob_response(openid_server.encodeResponse(openid_response), request)
        response.headerlist.extend(forget(request))

        return response

    return HTTPBadRequest('Invalid confirmation request')
Esempio n. 6
0
def auth_decision(request, openid_request):
    """Renders the appropriate page that allows the user to make a decision
    about the OpenID authentication request.

    The possible scenarios are:

    1. The user is logged in to the OP and RP wants OP to select the id
    2. The user is logged in to the OP and her identity matches the claimed id.
    3. The user is logged in to the OP and her identity does not match the claimed id.
    4. The user is not logged in and RP wants OP to select the id.
    5. The user is not logged in and RP sent a claimed id.

    In cases 1) and 2) the user can simply make the decision on allowing the
    authentication to proceed (and AX related decisions.)

    In cases 3), 4) and 5) the user needs to log in to the OP first.
    """
    user = authenticated_user(request)
    expected_user = extract_local_id(request, openid_request.identity)
    session = DBSession()
    log = logging.getLogger('webidentity')

    # Persist the OpenID request so we can continue processing it after the
    # user has authenticated overriding any previous request.
    cidrequest = session.query(CheckIdRequest).get(request.environ['repoze.browserid'])
    if cidrequest is None:
        cidrequest = CheckIdRequest(request.environ['repoze.browserid'], openid_request)
    else:
        # Unconditionally overwrite any existing checkid request.
        cidrequest.request = openid_request
        cidrequest.issued = int(time.time())

    session.add(cidrequest)
    # Clean up dangling requests for roughly 10% of the time.
    # We do not do this on every call to reduce the possibility of a database
    # deadlock as rows need to be locked.
    if random.randint(0, 100) < 10:
        threshold = int(time.time()) - 3600
        session.query(CheckIdRequest).filter(CheckIdRequest.issued < threshold).delete()
        log.info('Cleaned up dangling OpenID authentication requests.')

    options = {
        'title': _(u'Approve OpenID request?'),
        'action_url': route_url('openid_confirm', request),
        'trust_root': openid_request.trust_root,
        #'reset_url': route_url('reset_password', request),
    }

    if user is not None:
        ax_request = ax.FetchRequest.fromOpenIDRequest(openid_request)
        sreg_request = sreg.SRegRequest.fromOpenIDRequest(openid_request)

        if ax_request is not None or sreg_request is not None:
            # Prepare the user attributes for an SReg/AX request.

            # Mapping of attributes the RP has requested from the user.
            requested_attributes = {}

            if sreg_request.wereFieldsRequested():
                requested_attributes.update(dict(
                    (SREG_TO_AX.get(field), field in sreg_request.required)
                    for field
                    in sreg_request.allRequestedFields()))

            # The AX request takes precedence over SReg if both are requested.
            if ax_request is not None:
                requested_attributes.update(dict(
                    (type_uri, attrinfo.required)
                    for type_uri, attrinfo
                    in ax_request.requested_attributes.iteritems()))

            # Set of attributes that the RP has marked mandatory
            required_attributes = set(
                type_uri
                for type_uri, required
                in requested_attributes.iteritems()
                if required)

            for persona in user.personas:
                available_attributes = set(a.type_uri for a in persona.attributes)
                options.setdefault('personas', []).append({
                    'id': persona.id,
                    'name': persona.name,
                    'attributes': [
                        dict(type_uri=a.type_uri, value=a.value)
                        for a in persona.attributes
                        if a.type_uri in requested_attributes],
                    'missing': required_attributes - available_attributes,
                })

        if openid_request.idSelect():
            # Case 1.
            # The Relying Party has requested us to select an identifier.
            options.update({
                'identity': identity_url(request, user.username),
                'csrf_token': request.session.get_csrf_token(),
            })
            request.add_response_callback(disable_caching)
            return render_to_response('templates/openid_confirm.pt', options, request)
        elif user.username == expected_user:
            # Case 2.
            # A logged-in user that matches the user in the claimed identifier.
            options.update({
                'identity': openid_request.identity,
                'csrf_token': request.session.get_csrf_token(),
            })
            request.add_response_callback(disable_caching)
            return render_to_response('templates/openid_confirm.pt', options, request)
        else:
            # Case 3
            # TODO: Implement case 3
            raise NotImplementedError
    else:
        # Cases 4 and 5.
        options.update({
            'action_url': route_url('openid_confirm_login', request),
            'login_name': expected_user if not openid_request.idSelect() else None,
            'csrf_token': request.session.get_csrf_token(),
        })
        return render_to_response('templates/openid_confirm_login.pt', options, request)