browserid-auth-rails 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Greg Look
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,194 @@
1
+ Modified fork of [https://github.com/mvxcvi/browserid-rails](https://github.com/mvxcvi/browserid-rails) to be compatible with Devise.
2
+
3
+ # BrowserID::Rails
4
+
5
+ This gem provides a lightweight single-sign-on authentication structure to a
6
+ Rails application based on
7
+ [Mozilla's Persona service](https://login.persona.org/about). Persona
8
+ authenticates clients uniquely by their email address using the BrowserID
9
+ protocol, without exposing clients' browsing behaviors to the identity provider.
10
+ This also frees the application from needing to securely handle and store user
11
+ credentials.
12
+
13
+ ## Overview
14
+
15
+ BrowserID affords a very easy SSO experience for clients. A simplified version
16
+ of the authentication flow goes like this:
17
+
18
+ 1. The user clicks a login link on the site.
19
+ 2. A pop-up window directs the user to authenticate with their identity
20
+ provider. This will either be their email provider or Mozilla's fall-back
21
+ Persona service.
22
+ 3. If the authentication is successful, the browser acquires a certificate
23
+ proving that the client owns the email address in question. This only needs
24
+ to be done once for an email address across any number of domains; after
25
+ that the user can just click a button to use that address to authenticate.
26
+ 4. The browser then uses the certificate to sign an authentication assertion
27
+ for the site (given by the `audience` parameter).
28
+ 5. The browser POSTs the signed assertion to a session creation URL for
29
+ verification. If the assertion is valid, the authenticated email is stored
30
+ in the client's session and the page is reloaded.
31
+
32
+ At this point, the `browserid_email` method will return the stored email
33
+ address, and `browserid_current_user` will look up the authenticated user model.
34
+ See below for more detailed documentation of the available controller and helper
35
+ methods.
36
+
37
+ Logging out is also straightforward:
38
+
39
+ 1. The (authenticated) user clicks a logout link on the site.
40
+ 2. The browser clears its stored assertion for the site and POSTs a
41
+ request to the server to clear its login state.
42
+ 3. The server removes the authenticated email stored in the client's session
43
+ and reloads the page.
44
+
45
+ ## Installation
46
+
47
+ Add this line to your application's Gemfile:
48
+
49
+ gem 'browserid-rails'
50
+
51
+ And then execute:
52
+
53
+ $ bundle
54
+
55
+ Or install it yourself as:
56
+
57
+ $ gem install browserid-rails
58
+
59
+ ## Usage
60
+
61
+ To use this gem once it is installed, it must be integrated into your Rails
62
+ application. The following sections cover the gem configuration, controller
63
+ integration, and view integration.
64
+
65
+ ### Configuration
66
+
67
+ There are several configuration options available. There are a number of default
68
+ assumptions about the application, which may be overridden as needed.
69
+ Configuration settings are properties of `config.browserid`.
70
+
71
+ * `user_model` - The name of the ActiveModel class for application users.
72
+ The default is `"User"`.
73
+ * `email_field` - The attribute of the user model which contains the user's
74
+ email. The default is `:email`.
75
+ * `session_variable` - The location the authenticated email is stored in the
76
+ client's session. The default is `:browserid_email`.
77
+ * `verifier` - The type of verifier to use to authenticate client BrowserID
78
+ assertions. The default is `:persona`, which sends the request to Mozilla's
79
+ Persona verification service. In the future, `:local` will enable local
80
+ verification code. Alternately, this configuration option may be set to any
81
+ object which responds to `#verify(assertion, audience)` with the verified
82
+ email and identity provider on success and raises an error on failure.
83
+ * `audience` - The BrowserID audience to authenticate to. This should consist
84
+ of a URI string containing the scheme (protocol), authority, and port of the
85
+ service (e.g., `"https://app.example.com:443"`). By default, the audience is
86
+ not hardcoded and the properties of the request object are used to construct
87
+ it dynamically. This gives greater flexibility while developing, but is also
88
+ a minor security risk. In production, this should be configured to a fixed
89
+ value.
90
+
91
+ Additionally, there are two sub-structures `login` and `logout` for configuring
92
+ the associated paths and default link text. They have the following properties:
93
+
94
+ * `text` - The default text to give login and logout links.
95
+ * `path` - The target to give links and the path to `POST` authentication
96
+ requests to. Defaults to `"/login"` and `"/logout"` respectively.
97
+
98
+ So, if you wanted the application to use 'signin' and 'signout' instead, you
99
+ could do the following:
100
+
101
+ config.browserid.login.text = "Sign-in"
102
+ config.browserid.login.path = '/signin'
103
+ config.browserid.logout.text = "Sign-out"
104
+ config.browserid.logout.path = '/signout'
105
+
106
+ ### Controller Integration
107
+
108
+ The `BrowserID::Rails::Base` module makes several controller methods available
109
+ to interact with the authentication system. To access information, use one of:
110
+
111
+ * `browserid_email` - Returns the BrowserID-authenticated email address, if any.
112
+ * `browserid_current_user` - Retrieves the model for the currently authenticated
113
+ user, if there is an authenticated email and a matching user exists.
114
+ * `browserid_authenticated?` - Returns true if there is a current user.
115
+
116
+ These methods are also available in views as helpers.
117
+
118
+ To control authentication, the app should have a `SessionsController` which
119
+ connects the in-browser authentication code to the server. The gem provides
120
+ these methods:
121
+
122
+ * `login_browserid` - Sets the given string as the authenticated email.
123
+ * `logout_browserid` - Clears the current authenticated email.
124
+ * `verify_browserid` - Uses the configured verifier to confirm a BrowserID
125
+ assertion is correct for the service audience.
126
+ * `respond_to_browserid` - Wraps `verify_browserid` in logging and error
127
+ handling logic and generates controller responses to a `POST` assertion.
128
+
129
+ Implementing the required methods for `SessionsController` is straightforward:
130
+
131
+ # POST /login
132
+ def create
133
+ respond_to_browserid
134
+ end
135
+
136
+ # POST /logout
137
+ def destroy
138
+ logout_browserid
139
+ head :ok
140
+ end
141
+
142
+ ### Layout Integration
143
+
144
+ The BrowserID javascript library needs to be loaded on your application pages.
145
+ There are two steps to accomplish this:
146
+
147
+ First, the coffeescript asset file needs to be loaded. In the
148
+ `app/assets/javascripts/application.js` manifest, add the following line:
149
+
150
+ //= require browserid
151
+
152
+ Second, the scripts need to be setup in your pages' `<head>` section. The
153
+ `setup_browserid` helper method takes care of this for you and gives a couple
154
+ of ways to control its behavior:
155
+
156
+ <!-- Perform basic BrowserID setup in the head section -->
157
+ <%= setup_browserid %>
158
+
159
+ <!-- Setup BrowserID with alert debugging -->
160
+ <%= setup_browserid debug: true %>
161
+
162
+ <!-- Setup BrowserID with a custom handler -->
163
+ <%= setup_browserid do %>
164
+ browserid.onLogin = function (data, status, xhr) {
165
+ // ...
166
+ }
167
+ <% end %>
168
+
169
+ Once that's accomplished, the app is ready to use BrowserID for authentication.
170
+ To add login and logout links to the site, use the `login_link` and
171
+ `logout_link` helpers. These accept an optional link text as a parameter:
172
+
173
+ <%= logout_link %>
174
+
175
+ <%= login_link "Login with Persona" %>
176
+
177
+ The coffeescript asset adds on-click handlers to the links which trigger the
178
+ Persona code to request new assertions or destroy existing ones.
179
+
180
+ ## Contributing
181
+
182
+ 1. Fork it
183
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
184
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
185
+ 4. Push to the branch (`git push origin my-new-feature`)
186
+ 5. Create new Pull Request
187
+
188
+ ## Future Work
189
+
190
+ * In the future, it would be nice to have a generator to create routes and
191
+ session controller skeletons. This would simplify setup and integration with
192
+ new apps quite a bit.
193
+ * Another to-do item is to incorporate the Persona branding assets and add more
194
+ helpers for generating login buttons.
@@ -0,0 +1,84 @@
1
+ # BrowserID javascript functions
2
+
3
+ @browserid = browserid =
4
+
5
+ ### PROPERTIES ###
6
+
7
+ # Public: Path used to verify browserID authentication assertions. Assertions
8
+ # are POSTed to this path.
9
+ loginPath: '/login'
10
+
11
+ # Public: Path used to unset persisted authentication state when logging out.
12
+ # This should clear the currently-logged-in user email.
13
+ logoutPath: '/logout'
14
+
15
+ # Internal: Debugging toggle - if true, the results of logins will be alert
16
+ # dialogs instead of page refreshes. This is useful to set if the application
17
+ # starts going into a refresh loop.
18
+ debug: false
19
+
20
+
21
+
22
+ ### HANDLERS ###
23
+
24
+ # Public: This method is called when a user successfully authenticates. By
25
+ # default, it reloads the current page.
26
+ onLogin: (data, status, xhr) ->
27
+ if @debug
28
+ alert("Login: #{status}\n#{data}")
29
+ else
30
+ window.location.reload()
31
+
32
+ # Public: This method is called when a user fails to authenticate.
33
+ onLoginError: (xhr, status, err) ->
34
+ alert("Login: #{status} #{err}\n#{xhr.responseText}")
35
+
36
+ # Public: This method is called when a user clears their authentication. By
37
+ # default, it reloads the current page.
38
+ onLogout: (data, status, xhr) ->
39
+ if @debug
40
+ alert("Logout: #{status}\n#{data}")
41
+ else
42
+ window.location.reload()
43
+
44
+ # Public: This method is called when a user fails to clear their
45
+ # authentication.
46
+ onLogoutError: (xhr, status, err) ->
47
+ alert("Logout: #{status} #{err}\n#{xhr.responseText}")
48
+
49
+
50
+ ### INITIALIZATION ###
51
+
52
+ # Public: Watches the authentication state and takes action when the user
53
+ # logs in or logs out. This method MUST be called on every page of the
54
+ # application.
55
+ setup: (currentUser = null) ->
56
+ navigator.id.watch
57
+ loggedInUser: currentUser
58
+ onlogin: (assertion) =>
59
+ $.ajax
60
+ type: 'POST'
61
+ url: @loginPath
62
+ data: { assertion: assertion }
63
+ success: (data, status, xhr) => @onLogin(data, status, xhr)
64
+ error: (xhr, status, err) => @onLoginError(xhr, status, err)
65
+ onlogout: =>
66
+ $.ajax
67
+ type: 'POST'
68
+ url: @logoutPath
69
+ success: (data, status, xhr) => @onLogout(data, status, xhr)
70
+ error: (xhr, status, err) => @onLogoutError(xhr, status, err)
71
+
72
+
73
+
74
+ ### Behavior Binding ###
75
+
76
+ jQuery ->
77
+ $('.browserid_login').click ->
78
+ navigator.id.request()
79
+ false
80
+
81
+ jQuery ->
82
+ $('.browserid_logout').click ->
83
+ navigator.id.logout()
84
+ false
@@ -0,0 +1,12 @@
1
+ <script src="https://login.persona.org/include.js"></script>
2
+ <script type="text/javascript">
3
+ <% if options[:login_path] %>browserid.loginPath = "<%= options[:login_path] %>";<% end %>
4
+ <% if options[:logout_path] %>browserid.logoutPath = "<%= options[:logout_path] %>";<% end %>
5
+ <% if options[:debug] %>browserid.debug = true;<% end %>
6
+ <%= yield :browserid_setup %>
7
+ <% if browserid_email %>
8
+ browserid.setup("<%= browserid_email %>");
9
+ <% else %>
10
+ browserid.setup();
11
+ <% end %>
12
+ </script>
@@ -0,0 +1 @@
1
+ require 'browserid-rails'
@@ -0,0 +1,56 @@
1
+ require 'browserid/rails/base'
2
+ require 'browserid/rails/helpers'
3
+ require 'browserid/rails/version'
4
+
5
+ module BrowserID
6
+ module Rails
7
+ # This class defines a Rails engine which extends the base controller with
8
+ # the library methods. The presence of this engine also causes assets to
9
+ # be included when the gem is added as a dependency.
10
+ class Engine < ::Rails::Engine
11
+ # Initialize the engine configuration.
12
+ config.before_configuration do
13
+ BrowserIDConfig = Struct.new :user_model, :email_field, :session_variable, :verifier, :audience, :login, :logout
14
+ BrowserIDLinkConfig = Struct.new :text, :path
15
+
16
+ config.browserid = BrowserIDConfig.new.tap do |cfg|
17
+ cfg.user_model = 'User'
18
+ cfg.email_field = :email
19
+ cfg.session_variable = :browserid_email
20
+ cfg.verifier = :persona
21
+ # audience should only be set in production
22
+
23
+ cfg.login = BrowserIDLinkConfig.new.tap do |link|
24
+ link.text = "Login"
25
+ link.path = '/login'
26
+ end
27
+
28
+ cfg.logout = BrowserIDLinkConfig.new.tap do |link|
29
+ link.text = "Logout"
30
+ link.path = '/logout'
31
+ end
32
+ end
33
+ end
34
+
35
+ # Mix in the controller and view helper methods.
36
+ config.before_initialize do
37
+ ActionController::Base.send :include, BrowserID::Rails::Base
38
+ ActionView::Base.send :include, BrowserID::Rails::Helpers
39
+ end
40
+
41
+ # Create the assertion verifier.
42
+ config.after_initialize do
43
+ cfg = config.browserid
44
+
45
+ # Replace type symbol with constructed verifier.
46
+ if cfg.verifier == :persona
47
+ cfg.verifier = BrowserID::Verifier::Persona.new
48
+ elsif cfg.verifier == :local
49
+ raise "Local BrowserID verification is not supported yet" # TODO
50
+ elsif !cfg.verifier.respond_to?(:verify)
51
+ raise "Unknown BrowserID verifier type #{cfg.verifier}"
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,131 @@
1
+ require 'browserid/verifier/persona'
2
+
3
+ module BrowserID
4
+ module Rails
5
+ # Public: Base module for inclusion into a controller. This module includes
6
+ # methods for dealing with BrowserID user authentication.
7
+ module Base
8
+
9
+ ##### INTERNAL METHODS #####
10
+
11
+ # Internal: Modifies the controller this module is included in to provide
12
+ # authentication-related helper methods
13
+ #
14
+ # base - The Class this module is being included in.
15
+ def self.included(base)
16
+ base.send :helper_method, :browserid_config, :browserid_email, :browserid_current_user, :browserid_authenticated?
17
+ end
18
+
19
+ # Internal: Gets the application configuration for this gem.
20
+ #
21
+ # Returns the app config structure.
22
+ def browserid_config
23
+ ::Rails.application.config.browserid
24
+ end
25
+
26
+
27
+
28
+ ##### HELPER METHODS #####
29
+
30
+ # Public: Gets the email address of the currently-authenticated user.
31
+ #
32
+ # Returns the authenticated email address String.
33
+ def browserid_email
34
+ session[browserid_config.session_variable]
35
+ end
36
+
37
+ # Public: Retrieves the user for the authenticated email address. This
38
+ # method uses the `browserid.user_model` and `browserid.email_field`
39
+ # config settings, which default to `User` and `email`.
40
+ #
41
+ # Returns the current authenticated user, or nil if no user exists.
42
+ def browserid_current_user
43
+ if browserid_email.nil?
44
+ nil
45
+ elsif @browserid_current_user
46
+ @browserid_current_user
47
+ else
48
+ config = browserid_config
49
+ user_model = config.user_model.constantize
50
+ find_method = "find_by_#{config.email_field}".intern
51
+
52
+ @browserid_current_user = user_model.send find_method, browserid_email
53
+ end
54
+ end
55
+
56
+ # Public: Determines whether the current client is authenticated as a
57
+ # registered User.
58
+ #
59
+ # Returns true if the client is authenticated and registered.
60
+ def browserid_authenticated?
61
+ !browserid_current_user.nil?
62
+ end
63
+
64
+
65
+
66
+ ##### AUTHENTICATION METHODS #####
67
+
68
+ # Public: Sets the given email address as the currently-authenticated user.
69
+ # The address is saved in the client's session.
70
+ #
71
+ # email - The String email address to consider authenticated.
72
+ def login_browserid(email)
73
+ session[browserid_config.session_variable] = email
74
+ end
75
+
76
+ # Public: Clears the saved email address for the currently-authenticated
77
+ # user. It is important to note that this does not remove the BrowserID
78
+ # assertion in the client's browser.
79
+ def logout_browserid
80
+ session[browserid_config.session_variable] = nil
81
+ end
82
+
83
+ # Public: Uses the configured verifier to check that a provided assertion
84
+ # is correct for the site audience.
85
+ #
86
+ # Returns the verified email, identity issuer, and audience on success.
87
+ # Raises an error with a failure message if the client was not
88
+ # successfully authenticated.
89
+ #
90
+ # Examples
91
+ #
92
+ # verify_browserid(assertion)
93
+ # # => "user@example.com", "persona.mozilla.com", "https://app.example.com:443"
94
+ #
95
+ def verify_browserid(assertion)
96
+ audience = browserid_config.audience
97
+ audience ||= "%s%s:%d" % [request.protocol, request.host, request.port]
98
+ browserid_config.verifier.verify(assertion, audience)
99
+ end
100
+
101
+ # Public: Handles a POST-ed BrowserID assertion, responding appropriately
102
+ # to the request. If successful, this logs-in the authenticated email and
103
+ # returns an OK status. If unsuccessful, it returns FORBIDDEN and an
104
+ # error message in the response body.
105
+ #
106
+ # Returns nothing.
107
+ #
108
+ # Examples
109
+ #
110
+ # # POST /login
111
+ # def create
112
+ # respond_to_browserid
113
+ # end
114
+ #
115
+ def respond_to_browserid
116
+ if params[:assertion].blank?
117
+ head :bad_request
118
+ else
119
+ email, issuer, audience = verify_browserid params[:assertion]
120
+ logger.info "Verified BrowserID assertion for #{email} issued by #{issuer} on #{audience}"
121
+ login_browserid email
122
+ head :ok
123
+ end
124
+ rescue StandardError => e
125
+ # TODO: distinguish between process failures and invalid assertions
126
+ logger.warn "Failed to verify BrowserID assertion: #{e.message}"
127
+ render status: :forbidden, text: e.message
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,67 @@
1
+ module BrowserID
2
+ module Rails
3
+ # Public: Rails view helpers for use with BrowserID code.
4
+ module Helpers
5
+ # Public: Renders a layout partial which initializes the BrowserID
6
+ # system. This should be called in the head of the application layout.
7
+ #
8
+ # options - Hash used to adjust the browserid asset setup (default: {}).
9
+ # :login_path - String giving the path to POST assertions to
10
+ # for verification. Defaults to the configured
11
+ # `browserid.login.path`.
12
+ # :logout_path - String giving the path to POST logout
13
+ # notifications to. Defaults to the configured
14
+ # `browserid.logout.path`.
15
+ # :debug - Boolean determining whether the browserid
16
+ # javascript will refresh the page or show an
17
+ # alert dialog.
18
+ # block - An optional block which can be used to provide additional
19
+ # content to be rendered inside the browserid setup script tag.
20
+ #
21
+ # Examples
22
+ #
23
+ # <!-- Perform basic BrowserID setup in the head section -->
24
+ # <%= setup_browserid %>
25
+ #
26
+ # <!-- Setup BrowserID with alert debugging -->
27
+ # <%= setup_browserid debug: true %>
28
+ #
29
+ # <!-- Setup BrowserID with a custom handler -->
30
+ # <%= setup_browserid do %>
31
+ # browserid.onLogin = function (data, status, xhr) {
32
+ # // ...
33
+ # }
34
+ # <% end %>
35
+ #
36
+ def setup_browserid(options={}, &block)
37
+ defaults = { login_path: browserid_config.login.path, logout_path: browserid_config.logout.path }
38
+ content_for :browserid_setup, capture(&block) if block_given?
39
+ render 'shared/browserid', options: defaults.merge(options)
40
+ end
41
+
42
+ # Public: Renders a login link which will request a new authentication
43
+ # assertion from the BrowserID javascript code. The default link text is
44
+ # configurable with `config.browserid.login.text`. The link target is
45
+ # similarly configurable with `config.browserid.login.path`.
46
+ #
47
+ # text - Optional String to use as link text (default: configured value).
48
+ def login_link(text=nil)
49
+ text ||= browserid_config.login.text
50
+ target = browserid_config.login.path || '#'
51
+ link_to text, target, class: :browserid_login
52
+ end
53
+
54
+ # Public: Renders a logout link which will clear the current BrowserID
55
+ # authentication status. The default link text is configurable with
56
+ # `config.browserid.logout.text`. The link target is similarly
57
+ # configurable with `config.browserid.logout.path`.
58
+ #
59
+ # text - Optional String to use as link text (default: configured value).
60
+ def logout_link(text=nil)
61
+ text ||= browserid_config.logout.text
62
+ target = browserid_config.logout.path || '#'
63
+ link_to text, target, class: :browserid_logout
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,5 @@
1
+ module BrowserID
2
+ module Rails
3
+ VERSION = "0.5.3"
4
+ end
5
+ end
@@ -0,0 +1,85 @@
1
+ require 'json'
2
+ require 'net/https'
3
+
4
+ module BrowserID
5
+ module Verifier
6
+ # Public: This class sends the assertion to Mozilla's Persona server for
7
+ # verification.
8
+ class Persona
9
+ attr_accessor :server, :path
10
+
11
+ # Public: String defining the endpoint of the server to perform Persona
12
+ # verifications against.
13
+ VERIFICATION_SERVER = 'verifier.login.persona.org'
14
+
15
+ # Public: String defining the normal path to POST assertion verifications
16
+ # to.
17
+ VERIFICATION_PATH = '/verify'
18
+
19
+ # Public: Constructs a new Persona verifier.
20
+ #
21
+ # server - Domain String of the server to send assertions to for
22
+ # verifications (default: VERIFICATION_SERVER).
23
+ # path - Path String to POST to on the server (default:
24
+ # VERIFICATION_PATH).
25
+ #
26
+ def initialize(server=VERIFICATION_SERVER, path=VERIFICATION_PATH)
27
+ @server = server
28
+ @path = path
29
+ end
30
+
31
+ # Public: Verifies a Persona assertion for a given audience.
32
+ #
33
+ # assertion - Persona authentication assertion.
34
+ # audience - Audience String to verify assertion against. This should be
35
+ # the URI of the service with scheme, authority, and port.
36
+ #
37
+ # Returns the authenticated email address String and the issuing domain
38
+ # if the assertion is valid.
39
+ # Raises an exception with a failure message if the client was not
40
+ # successfully authenticated.
41
+ #
42
+ # Examples
43
+ #
44
+ # verify(assertion, "https://app.example.com:443")
45
+ # # => "user@example.com", "persona.mozilla.com"
46
+ #
47
+ def verify(assertion, audience)
48
+ http = Net::HTTP.new(@server, 443)
49
+ http.use_ssl = true
50
+
51
+ verification = Net::HTTP::Post.new(@path)
52
+ verification.set_form_data(assertion: assertion, audience: audience)
53
+
54
+ response = http.request(verification)
55
+ raise "Unsuccessful response from #{@server}: #{response}" unless response.kind_of? Net::HTTPSuccess
56
+ authentication = JSON.parse(response.body)
57
+
58
+ # Authentication response is a JSON hash which must contain a 'status'
59
+ # of "okay" or "failure".
60
+ status = authentication['status']
61
+ raise "Unknown authentication status '#{status}'" unless %w{okay failure}.include? status
62
+
63
+ # An unsuccessful authentication response should contain a reason string.
64
+ raise "Assertion failure: #{authentication['reason']}" unless status == "okay"
65
+
66
+ # A successful response looks like the following:
67
+ # {
68
+ # "status": "okay",
69
+ # "email": "user@example.com",
70
+ # "audience": "https://service.example.com:443",
71
+ # "expires": 1234567890,
72
+ # "issuer": "persona.mozilla.com"
73
+ # }
74
+
75
+ auth_audience = authentication['audience']
76
+ raise "Persona assertion audience '#{auth_audience}' does not match verifier audience '#{audience}'" unless auth_audience == audience
77
+
78
+ expires = authentication['expires'] && Time.at(authentication['expires'].to_i/1000.0)
79
+ raise "Persona assertion expired at #{expires}" if expires && expires < Time.now
80
+
81
+ [authentication['email'], authentication['issuer']]
82
+ end
83
+ end
84
+ end
85
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: browserid-auth-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Greg Look
9
+ - Alex Kravets
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-03-04 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: railties
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '3.2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '3.2'
31
+ - !ruby/object:Gem::Dependency
32
+ name: rspec-rails
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: '2.11'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '2.11'
47
+ - !ruby/object:Gem::Dependency
48
+ name: simplecov
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: tzinfo
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: jquery-rails
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ type: :runtime
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ description: ! " This gem provides a lightweight single-sign-on authentication
96
+ framework to\n a Rails application based on Mozilla's Persona service (see:\n
97
+ \ https://login.persona.org/about). Persona identifies users by email address\n
98
+ \ and authenticates them using the BrowserID protocol. This lets a client\n prove
99
+ they own an email address without exposing their browsing behaviors to\n the
100
+ identity provider. This also frees the application from needing to\n securely
101
+ handle and store user credentials.\n"
102
+ email:
103
+ - alex@slatestudio.com
104
+ executables: []
105
+ extensions: []
106
+ extra_rdoc_files: []
107
+ files:
108
+ - app/assets/javascripts/browserid.js.coffee
109
+ - app/views/shared/_browserid.html.erb
110
+ - lib/browserid/rails/base.rb
111
+ - lib/browserid/rails/helpers.rb
112
+ - lib/browserid/rails/version.rb
113
+ - lib/browserid/verifier/persona.rb
114
+ - lib/browserid-auth-rails.rb
115
+ - lib/browserid-rails.rb
116
+ - LICENSE
117
+ - README.md
118
+ homepage: https://github.com/alexkravets/browserid-auth-rails
119
+ licenses: []
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ! '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ segments:
131
+ - 0
132
+ hash: -465273068887906201
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ segments:
140
+ - 0
141
+ hash: -465273068887906201
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 1.8.24
145
+ signing_key:
146
+ specification_version: 3
147
+ summary: Lightweight Rails authentication framework using the BrowserID protocol.
148
+ test_files: []