Redmine/vendor/gems/ruby-openid-2.1.4/lib/openid/consumer/checkid_request.rb

187 lines
7.1 KiB
Ruby

require "openid/message"
require "openid/util"
module OpenID
class Consumer
# An object that holds the state necessary for generating an
# OpenID authentication request. This object holds the association
# with the server and the discovered information with which the
# request will be made.
#
# It is separate from the consumer because you may wish to add
# things to the request before sending it on its way to the
# server. It also has serialization options that let you encode
# the authentication request as a URL or as a form POST.
class CheckIDRequest
attr_accessor :return_to_args, :message
attr_reader :endpoint
# Users of this library should not create instances of this
# class. Instances of this class are created by the library
# when needed.
def initialize(assoc, endpoint)
@assoc = assoc
@endpoint = endpoint
@return_to_args = {}
@message = Message.new(endpoint.preferred_namespace)
@anonymous = false
end
attr_reader :anonymous
# Set whether this request should be made anonymously. If a
# request is anonymous, the identifier will not be sent in the
# request. This is only useful if you are making another kind of
# request with an extension in this request.
#
# Anonymous requests are not allowed when the request is made
# with OpenID 1.
def anonymous=(is_anonymous)
if is_anonymous && @message.is_openid1
raise ArgumentError, ("OpenID1 requests MUST include the "\
"identifier in the request")
end
@anonymous = is_anonymous
end
# Add an object that implements the extension interface for
# adding arguments to an OpenID message to this checkid request.
#
# extension_request: an OpenID::Extension object.
def add_extension(extension_request)
extension_request.to_message(@message)
end
# Add an extension argument to this OpenID authentication
# request. You probably want to use add_extension and the
# OpenID::Extension interface.
#
# Use caution when adding arguments, because they will be
# URL-escaped and appended to the redirect URL, which can easily
# get quite long.
def add_extension_arg(namespace, key, value)
@message.set_arg(namespace, key, value)
end
# Produce a OpenID::Message representing this request.
#
# Not specifying a return_to URL means that the user will not be
# returned to the site issuing the request upon its completion.
#
# If immediate mode is requested, the OpenID provider is to send
# back a response immediately, useful for behind-the-scenes
# authentication attempts. Otherwise the OpenID provider may
# engage the user before providing a response. This is the
# default case, as the user may need to provide credentials or
# approve the request before a positive response can be sent.
def get_message(realm, return_to=nil, immediate=false)
if !return_to.nil?
return_to = Util.append_args(return_to, @return_to_args)
elsif immediate
raise ArgumentError, ('"return_to" is mandatory when using '\
'"checkid_immediate"')
elsif @message.is_openid1
raise ArgumentError, ('"return_to" is mandatory for OpenID 1 '\
'requests')
elsif @return_to_args.empty?
raise ArgumentError, ('extra "return_to" arguments were specified, '\
'but no return_to was specified')
end
message = @message.copy
mode = immediate ? 'checkid_immediate' : 'checkid_setup'
message.set_arg(OPENID_NS, 'mode', mode)
realm_key = message.is_openid1 ? 'trust_root' : 'realm'
message.set_arg(OPENID_NS, realm_key, realm)
if !return_to.nil?
message.set_arg(OPENID_NS, 'return_to', return_to)
end
if not @anonymous
if @endpoint.is_op_identifier
# This will never happen when we're in OpenID 1
# compatibility mode, as long as is_op_identifier()
# returns false whenever preferred_namespace returns
# OPENID1_NS.
claimed_id = request_identity = IDENTIFIER_SELECT
else
request_identity = @endpoint.get_local_id
claimed_id = @endpoint.claimed_id
end
# This is true for both OpenID 1 and 2
message.set_arg(OPENID_NS, 'identity', request_identity)
if message.is_openid2
message.set_arg(OPENID2_NS, 'claimed_id', claimed_id)
end
end
if @assoc
message.set_arg(OPENID_NS, 'assoc_handle', @assoc.handle)
assoc_log_msg = "with assocication #{@assoc.handle}"
else
assoc_log_msg = 'using stateless mode.'
end
Util.log("Generated #{mode} request to #{@endpoint.server_url} "\
"#{assoc_log_msg}")
return message
end
# Returns a URL with an encoded OpenID request.
#
# The resulting URL is the OpenID provider's endpoint URL with
# parameters appended as query arguments. You should redirect
# the user agent to this URL.
#
# OpenID 2.0 endpoints also accept POST requests, see
# 'send_redirect?' and 'form_markup'.
def redirect_url(realm, return_to=nil, immediate=false)
message = get_message(realm, return_to, immediate)
return message.to_url(@endpoint.server_url)
end
# Get html for a form to submit this request to the IDP.
#
# form_tag_attrs is a hash of attributes to be added to the form
# tag. 'accept-charset' and 'enctype' have defaults that can be
# overridden. If a value is supplied for 'action' or 'method',
# it will be replaced.
def form_markup(realm, return_to=nil, immediate=false,
form_tag_attrs=nil)
message = get_message(realm, return_to, immediate)
return message.to_form_markup(@endpoint.server_url, form_tag_attrs)
end
# Get a complete HTML document that autosubmits the request to the IDP
# with javascript. This method wraps form_markup - see that method's
# documentation for help with the parameters.
def html_markup(realm, return_to=nil, immediate=false,
form_tag_attrs=nil)
Util.auto_submit_html(form_markup(realm,
return_to,
immediate,
form_tag_attrs))
end
# Should this OpenID authentication request be sent as a HTTP
# redirect or as a POST (form submission)?
#
# This takes the same parameters as redirect_url or form_markup
def send_redirect?(realm, return_to=nil, immediate=false)
if @endpoint.compatibility_mode
return true
else
url = redirect_url(realm, return_to, immediate)
return url.length <= OPENID1_URL_LIMIT
end
end
end
end
end