# File lib/openid/server.rb, line 657
      def answer(allow, server_url=nil, identity=nil, claimed_id=nil)
        if !@return_to
          raise NoReturnToError
        end

        if !server_url
          if @message.is_openid2 and !@op_endpoint
            # In other words, that warning I raised in
            # Server.__init__?  You should pay attention to it now.
            raise RuntimeError, ("#{self} should be constructed with "\
                                 "op_endpoint to respond to OpenID 2.0 "\
                                 "messages.")
          end

          server_url = @op_endpoint
        end

        if allow
          mode = 'id_res'
        elsif @message.is_openid1
          if @immediate
            mode = 'id_res'
          else
            mode = 'cancel'
          end
        else
          if @immediate
            mode = 'setup_needed'
          else
            mode = 'cancel'
          end
        end

        response = OpenIDResponse.new(self)

        if claimed_id and @message.is_openid1
          raise VersionError, ("claimed_id is new in OpenID 2.0 and not "\
                               "available for #{@message.get_openid_namespace}")
        end

        if identity and !claimed_id
          claimed_id = identity
        end

        if allow
          if @identity == IDENTIFIER_SELECT
            if !identity
              raise ArgumentError, ("This request uses IdP-driven "\
                                    "identifier selection.You must supply "\
                                    "an identifier in the response.")
            end

            response_identity = identity
            response_claimed_id = claimed_id

          elsif @identity
            if identity and (@identity != identity)
              raise ArgumentError, ("Request was for identity #{@identity}, "\
                                    "cannot reply with identity #{identity}")
            end

            response_identity = @identity
            response_claimed_id = @claimed_id
          else
            if identity
              raise ArgumentError, ("This request specified no identity "\
                                    "and you supplied #{identity}")
            end
            response_identity = nil
          end

          if @message.is_openid1 and !response_identity
            raise ArgumentError, ("Request was an OpenID 1 request, so "\
                                  "response must include an identifier.")
          end

          response.fields.update_args(OPENID_NS, {
                'mode' => mode,
                'op_endpoint' => server_url,
                'return_to' => @return_to,
                'response_nonce' => Nonce.mk_nonce(),
                })

          if response_identity
            response.fields.set_arg(OPENID_NS, 'identity', response_identity)
            if @message.is_openid2
              response.fields.set_arg(OPENID_NS,
                                      'claimed_id', response_claimed_id)
            end
          end
        else
          response.fields.set_arg(OPENID_NS, 'mode', mode)
          if @immediate
            if @message.is_openid1 and !server_url
              raise ArgumentError, ("setup_url is required for allow=false "\
                                    "in OpenID 1.x immediate mode.")
            end

            # Make a new request just like me, but with
            # immediate=false.
            setup_request = self.class.new(@identity, @return_to,
                                           @op_endpoint, @trust_root, false,
                                           @assoc_handle, @claimed_id)
            setup_request.message = Message.new(@message.get_openid_namespace)
            setup_url = setup_request.encode_to_url(server_url)
            response.fields.set_arg(OPENID_NS, 'user_setup_url', setup_url)
          end
        end

        return response
      end