Class: Google::IdentityToolkit
- Inherits:
-
Object
- Object
- Google::IdentityToolkit
- Defined in:
- lib/google/identity_toolkit.rb,
lib/google/identity_toolkit/api.rb,
lib/google/identity_toolkit/errors.rb,
lib/google/identity_toolkit/helpers.rb,
lib/google/identity_toolkit/version.rb
Overview
Rack middleware for using the Google Identity Kit for federated login
Defined Under Namespace
Modules: Helpers Classes: Api, ApiError
Constant Summary collapse
- VERSION =
"0.0.1"
Instance Attribute Summary collapse
-
#api ⇒ Google::IdentityToolkit::Api
Get (and lazy init) the API client.
-
#api_key ⇒ Object
Returns the value of attribute api_key.
-
#app ⇒ Object
Returns the value of attribute app.
-
#callback_url(request = nil) ⇒ String
Get the callback URL for use in the javascript helpers.
-
#federated_signup_url ⇒ Object
Returns the value of attribute federated_signup_url.
-
#home_url ⇒ Object
Returns the value of attribute home_url.
-
#path ⇒ Object
Returns the value of attribute path.
-
#signup_url ⇒ Object
Returns the value of attribute signup_url.
Class Method Summary collapse
-
.api_key ⇒ String
Static method for fetching the API key from thread-local storage.
-
.callback_url ⇒ Hash
Static method for fetching the callback URL from thread-local storage.
-
.current_user ⇒ Hash
Static method for fetching the current user from thread-local storage.
- .env ⇒ Object
Instance Method Summary collapse
-
#build_mobile_html(status, data) ⇒ String
Renders boilerplate HTML for non-poup mobile UI.
-
#build_notify_html(status, data) ⇒ String
Renders boilerplate HTML for closing popups after login.
-
#call(env) ⇒ Array
Handles web requests for identity toolkit callbacks.
-
#callback(request) ⇒ String
Handles IDP responses during login.
- #env ⇒ Object
-
#handle_login(user) ⇒ Object
Log the user after either a successful assertion or password validation.
-
#initialize(app, &block) ⇒ IdentityToolkit
constructor
Creates the Identity toolkit middleware.
-
#login(request) ⇒ Hash
Handles authentication requests for non-federated users.
- #request ⇒ Object
- #session ⇒ Object
-
#status(request) ⇒ Hash
Checks the status of a user.
Constructor Details
#initialize(app, &block) ⇒ IdentityToolkit
Creates the Identity toolkit middleware. Requires defining a block to configure the API and define callback methods for loading & authenticating users.
end
45 46 47 48 49 50 |
# File 'lib/google/identity_toolkit.rb', line 45 def initialize(app, &block) @path = '/_gitkit' @callback_url = nil @app = app instance_eval(&block) if block_given? end |
Instance Attribute Details
#api ⇒ Google::IdentityToolkit::Api
Get (and lazy init) the API client
84 85 86 |
# File 'lib/google/identity_toolkit.rb', line 84 def api @api end |
#api_key ⇒ Object
Returns the value of attribute api_key.
19 20 21 |
# File 'lib/google/identity_toolkit.rb', line 19 def api_key @api_key end |
#app ⇒ Object
Returns the value of attribute app.
21 22 23 |
# File 'lib/google/identity_toolkit.rb', line 21 def app @app end |
#callback_url(request = nil) ⇒ String
Get the callback URL for use in the javascript helpers.
270 271 272 |
# File 'lib/google/identity_toolkit.rb', line 270 def callback_url @callback_url end |
#federated_signup_url ⇒ Object
Returns the value of attribute federated_signup_url.
24 25 26 |
# File 'lib/google/identity_toolkit.rb', line 24 def federated_signup_url @federated_signup_url end |
#home_url ⇒ Object
Returns the value of attribute home_url.
26 27 28 |
# File 'lib/google/identity_toolkit.rb', line 26 def home_url @home_url end |
#path ⇒ Object
Returns the value of attribute path.
20 21 22 |
# File 'lib/google/identity_toolkit.rb', line 20 def path @path end |
#signup_url ⇒ Object
Returns the value of attribute signup_url.
25 26 27 |
# File 'lib/google/identity_toolkit.rb', line 25 def signup_url @signup_url end |
Class Method Details
.api_key ⇒ String
Static method for fetching the API key from thread-local storage. Only valid for threads intercepted by the rack module. Use by helper methods rendering the login button.
57 58 59 |
# File 'lib/google/identity_toolkit.rb', line 57 def self.api_key env[:gitkit_api_key] end |
.callback_url ⇒ Hash
Static method for fetching the callback URL from thread-local storage. Only valid for threads intercepted by the rack module. Use by helper methods rendering the login button.
75 76 77 |
# File 'lib/google/identity_toolkit.rb', line 75 def self.callback_url env[:gitkit_callback_url] end |
.current_user ⇒ Hash
Static method for fetching the current user from thread-local storage. Only valid for threads intercepted by the rack module. Use by helper methods rendering the login button.
66 67 68 |
# File 'lib/google/identity_toolkit.rb', line 66 def self.current_user env[:gitkit_user] end |
.env ⇒ Object
282 283 284 |
# File 'lib/google/identity_toolkit.rb', line 282 def self.env Thread.current[:gitkit_rack_env] end |
Instance Method Details
#build_mobile_html(status, data) ⇒ String
Renders boilerplate HTML for non-poup mobile UI
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/google/identity_toolkit.rb', line 246 def build_mobile_html(status, data) html = "<script type='text/javascript'>" if status == STATUS_SUCCESS if data["registered"] html << "window.location = '#{home_url}';" else target = Addressable::URI.parse(signup_url) target.query_values = target.query_values.merge("email" => data["email"]) html << "window.location = '#{target}';" end else target = Addressable::URI.parse(login_url) target.query_values = target.query_values.merge("error" => status) html << "window.location = '#{login_url}';" end html << "</script>" end |
#build_notify_html(status, data) ⇒ String
Renders boilerplate HTML for closing popups after login
223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/google/identity_toolkit.rb', line 223 def build_notify_html(status, data) html = <<-EOF <script type='text/javascript' src='https://ajax.googleapis.com/jsapi'></script> <script type='text/javascript'>google.load("identitytoolkit", "1.0", {packages: ["notify"]});</script> <script type='text/javascript'> EOF case status when STATUS_SUCCESS html << "window.google.identitytoolkit.notifyFederatedSuccess(#{data.to_json});" else html << "window.google.identitytoolkit.notifyFederatedError('#{status}', #{data.to_json});" end html << "</script>" end |
#call(env) ⇒ Array
Handles web requests for identity toolkit callbacks
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/google/identity_toolkit.rb', line 95 def call(env) request = Rack::Request.new(env) env[:gitkit_api_key] = @api_key env[:gitkit_callback_url] = callback_url(request) env[:gitkit_user] = request.session[:git_user] Thread.current[:gitkit_rack_env] = env begin return @app.call(env) unless request.path == @path case request.params['rp_target'] when "callback" body = callback(request) [200, {CONTENT_TYPE => CONTENT_TYPE_HTML}, [body]] when "login" data = login(request) [200, {CONTENT_TYPE => CONTENT_TYPE_JSON}, [data.to_json]] when "userStatus" data = status(request) [200, {CONTENT_TYPE => CONTENT_TYPE_JSON}, [data.to_json]] end ensure Thread.current[:gitkit_rack_env] = nil end end |
#callback(request) ⇒ String
Handles IDP responses during login
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/google/identity_toolkit.rb', line 126 def callback(request) render_method = !!request.params['mobile'] ? :build_mobile_html : :build_notify_html begin assertion = api.verify_assertion(request.url, request.body) input_email = request.params['rp_input_email'] email = assertion['verifiedEmail'] return send(render_method, STATUS_INVALID_EMAIL, {}) if email.nil? return send(render_method, STATUS_ACCOUNT_MISMATCH, { "inputEmail" => input_email, "validatedEmail" => email }) unless input_email.nil? or input_email == email user = fetch_user(email, assertion) if user.nil? # Save the assertion for use in signup page request.session[:gitkit_assertion] = assertion unless session.nil? send(render_method, STATUS_SUCCESS, { "email" => email, "registered" => false, "displayName" => assertion["displayName"], "photoUrl" => assertion["photoUrl"] }) else # User exits, login upgrade_user(email) handle_login(user) send(render_method, STATUS_SUCCESS, { "email" => email, "registered" => true, "displayName" => assertion["displayName"], "photoUrl" => assertion["photoUrl"] }) end rescue Exception => e send(render_method, 'invalidAssertion', {}) end end |
#env ⇒ Object
286 287 288 |
# File 'lib/google/identity_toolkit.rb', line 286 def env Thread.current[:gitkit_rack_env] end |
#handle_login(user) ⇒ Object
Log the user after either a successful assertion or password validation
208 209 210 211 212 213 |
# File 'lib/google/identity_toolkit.rb', line 208 def handle_login(user) unless session.nil? request.session[:git_user] = user on_login(user) end end |
#login(request) ⇒ Hash
Handles authentication requests for non-federated users
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/google/identity_toolkit.rb', line 171 def login(request) user = fetch_user(request.params["email"]) if user.nil? {:status => "emailNotExist"} elsif user[:federated] {:status => "federated"} else if password_valid?(request.params["email"], request.params["password"]) user = fetch_user(request.params["email"]) handle_login(user) {:status => "OK"} else {:status => "passwordError"} end end end |
#request ⇒ Object
290 291 292 |
# File 'lib/google/identity_toolkit.rb', line 290 def request Rack::Request.new(env) end |
#session ⇒ Object
294 295 296 |
# File 'lib/google/identity_toolkit.rb', line 294 def session request.session end |
#status(request) ⇒ Hash
Checks the status of a user
195 196 197 198 199 200 |
# File 'lib/google/identity_toolkit.rb', line 195 def status(request) user = fetch_user(request.params["email"]) #referrer = request.params["referrer"] { "registered" => !!user, "legacy" => !(user && user[:federated]) } end |