1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
require 'omniauth'
require 'rack/openid'
require 'openid/store/memory'
module OmniAuth
module Strategies
# OmniAuth strategy for connecting via OpenID. This allows for connection
# to a wide variety of sites, some of which are listed [on the OpenID website](http://openid.net/get-an-openid/).
class OpenID
include OmniAuth::Strategy
AX = {
:email => 'http://axschema.org/contact/email',
:name => 'http://axschema.org/namePerson',
:nickname => 'http://axschema.org/namePerson/friendly',
:first_name => 'http://axschema.org/namePerson/first',
:last_name => 'http://axschema.org/namePerson/last',
:city => 'http://axschema.org/contact/city/home',
:state => 'http://axschema.org/contact/state/home',
:website => 'http://axschema.org/contact/web/default',
:image => 'http://axschema.org/media/image/aspect11'
}
option :name, :open_id
option :required, [AX[:email], AX[:name], AX[:first_name], AX[:last_name], 'email', 'fullname']
option :optional, [AX[:nickname], AX[:city], AX[:state], AX[:website], AX[:image], 'postcode', 'nickname']
option :store, ::OpenID::Store::Memory.new
option :identifier, nil
option :identifier_param, 'openid_url'
def dummy_app
lambda{|env| [401, {"WWW-Authenticate" => Rack::OpenID.build_header(
:identifier => identifier,
:return_to => callback_url,
:required => options.required,
:optional => options.optional,
:method => 'post'
)}, []]}
end
def identifier
i = options.identifier || request.params[options.identifier_param.to_s]
i = nil if i == ''
i
end
def request_phase
identifier ? start : get_identifier
end
def start
openid = Rack::OpenID.new(dummy_app, options[:store])
response = openid.call(env)
case env['rack.openid.response']
when Rack::OpenID::MissingResponse, Rack::OpenID::TimeoutResponse
fail!(:connection_failed)
else
response
end
end
def get_identifier
f = OmniAuth::Form.new(:title => 'OpenID Authentication')
f.label_field('OpenID Identifier', options.identifier_param)
f.input_field('url', options.identifier_param)
f.to_response
end
uid { openid_response.display_identifier }
info do
sreg_user_info.merge(ax_user_info)
end
extra do
{'response' => openid_response}
end
def callback_phase
return fail!(:invalid_credentials) unless openid_response && openid_response.status == :success
super
end
def openid_response
unless @openid_response
openid = Rack::OpenID.new(lambda{|env| [200,{},[]]}, options[:store])
openid.call(env)
@openid_response = env.delete('rack.openid.response')
end
@openid_response
end
def sreg_user_info
sreg = ::OpenID::SReg::Response.from_success_response(openid_response)
return {} unless sreg
{
'email' => sreg['email'],
'name' => sreg['fullname'],
'location' => sreg['postcode'],
'nickname' => sreg['nickname']
}.reject{|k,v| v.nil? || v == ''}
end
def ax_user_info
ax = ::OpenID::AX::FetchResponse.from_success_response(openid_response)
return {} unless ax
{
'email' => ax.get_single(AX[:email]),
'first_name' => ax.get_single(AX[:first_name]),
'last_name' => ax.get_single(AX[:last_name]),
'name' => (ax.get_single(AX[:name]) || [ax.get_single(AX[:first_name]), ax.get_single(AX[:last_name])].join(' ')).strip,
'location' => ("#{ax.get_single(AX[:city])}, #{ax.get_single(AX[:state])}" if Array(ax.get_single(AX[:city])).any? && Array(ax.get_single(AX[:state])).any?),
'nickname' => ax.get_single(AX[:nickname]),
'urls' => ({'Website' => Array(ax.get_single(AX[:website])).first} if Array(ax.get_single(AX[:website])).any?)
}.inject({}){|h,(k,v)| h[k] = Array(v).first; h}.reject{|k,v| v.nil? || v == ''}
end
end
end
end
OmniAuth.config.add_camelization 'openid', 'OpenID'
OmniAuth.config.add_camelization 'open_id', 'OpenID'
|