def answer(self, allow, server_url=None, identity=None, claimed_id=None):
        """Respond to this request.

        @param allow: Allow this user to claim this identity, and allow the
            consumer to have this information?
        @type allow: bool

        @param server_url: DEPRECATED.  Passing C{op_endpoint} to the
            L{Server} constructor makes this optional.

            When an OpenID 1.x immediate mode request does not succeed,
            it gets back a URL where the request may be carried out
            in a not-so-immediate fashion.  Pass my URL in here (the
            fully qualified address of this server's endpoint, i.e.
            C{http://example.com/server}), and I will use it as a base for the
            URL for a new request.

            Optional for requests where C{CheckIDRequest.immediate} is C{False}
            or C{allow} is C{True}.

        @type server_url: str

        @param identity: The OP-local identifier to answer with.  Only for use
            when the relying party requested identifier selection.
        @type identity: str or None

        @param claimed_id: The claimed identifier to answer with, for use
            with identifier selection in the case where the claimed identifier
            and the OP-local identifier differ, i.e. when the claimed_id uses
            delegation.

            If C{identity} is provided but this is not, C{claimed_id} will
            default to the value of C{identity}.  When answering requests
            that did not ask for identifier selection, the response
            C{claimed_id} will default to that of the request.

            This parameter is new in OpenID 2.0.
        @type claimed_id: str or None

        @returntype: L{OpenIDResponse}

        @change: Version 2.0 deprecates C{server_url} and adds C{claimed_id}.

        @raises NoReturnError: when I do not have a return_to.
        """
        assert self.message is not None

        if not self.return_to:
            raise NoReturnToError

        if not server_url:
            if not self.message.isOpenID1() and not self.op_endpoint:
                # In other words, that warning I raised in Server.__init__?
                # You should pay attention to it now.
                raise RuntimeError("%s should be constructed with op_endpoint "
                                   "to respond to OpenID 2.0 messages." %
                                   (self,))
            server_url = self.op_endpoint

        if allow:
            mode = 'id_res'
        elif self.message.isOpenID1():
             if self.immediate:
                 mode = 'id_res'
             else:
                 mode = 'cancel'
        else:
            if self.immediate:
                mode = 'setup_needed'
            else:
                mode = 'cancel'

        response = OpenIDResponse(self)

        if claimed_id and self.message.isOpenID1():
            namespace = self.message.getOpenIDNamespace()
            raise VersionError("claimed_id is new in OpenID 2.0 and not "
                               "available for %s" % (namespace,))

        if allow:
            if self.identity == IDENTIFIER_SELECT:
                if not identity:
                    raise ValueError(
                        "This request uses IdP-driven identifier selection."
                        "You must supply an identifier in the response.")
                response_identity = identity
                response_claimed_id = claimed_id or identity

            elif self.identity:
                if identity and (self.identity != identity):
                    normalized_request_identity = urinorm(self.identity)
                    normalized_answer_identity = urinorm(identity)

                    if (normalized_request_identity !=
                        normalized_answer_identity):
                        raise ValueError(
                            "Request was for identity %r, cannot reply "
                            "with identity %r" % (self.identity, identity))

                # The "identity" value in the response shall always be
                # the same as that in the request, otherwise the RP is
                # likely to not validate the response.
                response_identity = self.identity
                response_claimed_id = self.claimed_id
            else:
                if identity:
                    raise ValueError(
                        "This request specified no identity and you "
                        "supplied %r" % (identity,))
                response_identity = None

            if self.message.isOpenID1() and response_identity is None:
                raise ValueError(
                    "Request was an OpenID 1 request, so response must "
                    "include an identifier."
                    )

            response.fields.updateArgs(OPENID_NS, {
                'mode': mode,
                'return_to': self.return_to,
                'response_nonce': mkNonce(),
                })

            if server_url:
                response.fields.setArg(OPENID_NS, 'op_endpoint', server_url)

            if response_identity is not None:
                response.fields.setArg(
                    OPENID_NS, 'identity', response_identity)
                if self.message.isOpenID2():
                    response.fields.setArg(
                        OPENID_NS, 'claimed_id', response_claimed_id)
        else:
            response.fields.setArg(OPENID_NS, 'mode', mode)
            if self.immediate:
                if self.message.isOpenID1() and not server_url:
                    raise ValueError("setup_url is required for allow=False "
                                     "in OpenID 1.x immediate mode.")
                # Make a new request just like me, but with immediate=False.
                setup_request = self.__class__(
                    self.identity, self.return_to, self.trust_root,
                    immediate=False, assoc_handle=self.assoc_handle,
                    op_endpoint=self.op_endpoint, claimed_id=self.claimed_id)

                # XXX: This API is weird.
                setup_request.message = self.message

                setup_url = setup_request.encodeToURL(server_url)
                response.fields.setArg(OPENID_NS, 'user_setup_url', setup_url)

        return response
Respond to this request.

        @param allow: Allow this user to claim this identity, and allow the
            consumer to have this information?
        @type allow: bool

        @param server_url: DEPRECATED.  Passing C{op_endpoint} to the
            L{Server} constructor makes this optional.

            When an OpenID 1.x immediate mode request does not succeed,
            it gets back a URL where the request may be carried out
            in a not-so-immediate fashion.  Pass my URL in here (the
            fully qualified address of this server's endpoint, i.e.
            C{http://example.com/server}), and I will use it as a base for the
            URL for a new request.

            Optional for requests where C{CheckIDRequest.immediate} is C{False}
            or C{allow} is C{True}.

        @type server_url: str

        @param identity: The OP-local identifier to answer with.  Only for use
            when the relying party requested identifier selection.
        @type identity: str or None

        @param claimed_id: The claimed identifier to answer with, for use
            with identifier selection in the case where the claimed identifier
            and the OP-local identifier differ, i.e. when the claimed_id uses
            delegation.

            If C{identity} is provided but this is not, C{claimed_id} will
            default to the value of C{identity}.  When answering requests
            that did not ask for identifier selection, the response
            C{claimed_id} will default to that of the request.

            This parameter is new in OpenID 2.0.
        @type claimed_id: str or None

        @returntype: L{OpenIDResponse}

        @change: Version 2.0 deprecates C{server_url} and adds C{claimed_id}.

        @raises NoReturnError: when I do not have a return_to.