forked from livingsocial/rails-googleapps-auth
/
googleapps_auth.rb
115 lines (97 loc) · 3.28 KB
/
googleapps_auth.rb
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
require "railtie" if defined?(::Rails::Railtie)
require 'openid'
require 'openid/store/memory'
require 'openid/extensions/ax'
module GoogleAppsAuth
ID_PREFIX = "https://www.google.com/accounts/o8/site-xrds?hd="
XRDS_PREFIX = "https://www.google.com/accounts/o8/user-xrds?uri="
AX_SCHEMAS = {
:email => "http://schema.openid.net/contact/email",
:firstname => "http://axschema.org/namePerson/first",
:lastname => "http://axschema.org/namePerson/last",
:language => "http://axschema.org/pref/language"
}
def self.certificate_authority_file=(path)
OpenID.fetcher.ca_file = path
end
class Result
attr_reader :error
def initialize(status, error=nil, attrs=nil)
@status = status
@error = error
@attrs = attrs
@attrs ||= {}
end
def [](attr)
@attrs[attr]
end
def succeeded?
@status == :success
end
def canceled?
@status == :canceled
end
def failed?
@status == :failed
end
end
protected
def google_apps_authenticate(appname, return_action = 'finish', get_attrs = nil)
get_attrs ||= []
begin
oidreq = consumer.begin GoogleAppsAuth::ID_PREFIX + appname
return_to = url_for :action => return_action, :only_path => false
realm = request.protocol + request.host_with_port
ax = OpenID::AX::FetchRequest.new
get_attrs.each { |attr|
ax.add OpenID::AX::AttrInfo.new(GoogleAppsAuth::AX_SCHEMAS[attr], attr.to_s, true)
}
oidreq.add_extension(ax)
redirect_to oidreq.redirect_url(realm, return_to, false)
rescue OpenID::OpenIDError => e
if block_given?
yield
else
flash[:notice] = "Discovery failed."
redirect_to :action => 'index'
end
end
end
def google_apps_handle_auth
current_url = url_for(:action => request.symbolized_path_parameters[:action], :only_path => false)
parameters = params.reject { |k, v| request.symbolized_path_parameters[k.to_sym] }
oidresp = consumer.complete(parameters, current_url)
case oidresp.status
when OpenID::Consumer::FAILURE
GoogleAppsAuth::Result.new :failed, oidresp.message
when OpenID::Consumer::CANCEL
GoogleAppsAuth::Result.new :canceled, "Authentication canceled."
when OpenID::Consumer::SUCCESS
resp = OpenID::AX::FetchResponse.from_success_response(oidresp)
attrs = {}
GoogleAppsAuth::AX_SCHEMAS.each { |name,schema|
attrs[name] = resp.data[schema] if not resp.data[schema].nil?
}
GoogleAppsAuth::Result.new :success, nil, attrs
else
GoogleAppsAuth::Result.new :failed, "Unknown error."
end
end
def store
OpenID::Store::Memory.new
end
def consumer
@consumer ||= OpenID::Consumer.new(session, store)
end
end
## TemplateURI's are not followed by the openid gem - so we have to trick it
class OpenID::Consumer::IdResHandler
def verify_discovery_results
oldid = @message.get_arg(OpenID::OPENID_NS, 'identity', nil)
@message.set_arg(OpenID::OPENID_NS, 'identity', GoogleAppsAuth::XRDS_PREFIX + oldid)
@message.set_arg(OpenID::OPENID_NS, 'claimed_id', GoogleAppsAuth::XRDS_PREFIX + oldid)
verify_discovery_results_openid2
@message.set_arg(OpenID::OPENID_NS, 'identity', oldid)
@message.set_arg(OpenID::OPENID_NS, 'claimed_id', oldid)
end
end