passwordless 0.8.2 → 0.9.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b19e22b9a7152b299c8f639339709ebeaa3616ecfd7a85f461af205d8f6ad635
4
- data.tar.gz: 8858c326d1457db832e08909957948d49d525bde1d45effa52e4d8e9b22f0374
3
+ metadata.gz: 906aa2b5a4bf5184d18d837c68565897bbeaa110550e875f44aaa71c8fee4c01
4
+ data.tar.gz: b0155e0411c6f1ffca21b22f5f38da4f656c61770280bb3f0afa9ba9d1f6f737
5
5
  SHA512:
6
- metadata.gz: 146b741cd502a702a10ed5169575eb5d6e9c47b0be8469e74b4e2369d2ecb82c1845624afe04aac2cac4e701deb6ea726e916dc1019007bdacd48e510272c9b7
7
- data.tar.gz: f95c455c20f127c1a86c0df6763afdf2f90312afd429b81f96b8dd1e0901ac17c7cb3e8c1ff38d858d5208149eedf8257eff0b1e40809aa58c2189df58d1f90b
6
+ metadata.gz: 19718426b946b054f327c13c00570a3ded2aba29d06f8b70cd446185ca2b92f969aee23faab8bda77a9f66f54aae6b7b493193d18f696ceaca427ec624b8d51c
7
+ data.tar.gz: 95dbb1810540c40de5e1a828d61477f0786698e79ea47a5c65b5efba23108791aefa9c2a747550b8e46e56256f0281ad61d1b34ceb06f13f28d8063affde4469
data/README.md CHANGED
@@ -14,17 +14,19 @@ Add authentication to your Rails app without all the icky-ness of passwords.
14
14
 
15
15
  * [Installation](#installation)
16
16
  * [Usage](#usage)
17
- * [Getting the current user, restricting access, the usual](#getting-the-current-user-restricting-access-the-usual)
18
- * [Providing your own templates](#providing-your-own-templates)
19
- * [Claming tokens](#claiming-tokens)
20
- * [Overrides](#overrides)
21
- * [Registering new users](#registering-new-users)
22
- * [Generating tokens](#generating-tokens)
23
- * [Token and Session Expiry](#token-and-session-expiry)
24
- * [Redirecting back after sign-in](#redirecting-back-after-sign-in)
25
- * [URLs and links](#urls-and-links)
26
- * [Customize the way to send magic link](#customize-the-way-to-send-magic-link)
27
- * [E-mail security](#e-mail-security)
17
+ * [Getting the current user, restricting access, the usual](#getting-the-current-user-restricting-access-the-usual)
18
+ * [Providing your own templates](#providing-your-own-templates)
19
+ * [Registering new users](#registering-new-users)
20
+ * [URLs and links](#urls-and-links)
21
+ * [Customize the way to send magic link](#customize-the-way-to-send-magic-link)
22
+ * [Generate your own magic links](#generate-your-own-magic-links)
23
+ * [Overrides](#overrides)
24
+ * [Configuration](#configuration)
25
+ * [Customising token generation](#generating-tokens)
26
+ * [Token and Session Expiry](#token-and-session-expiry)
27
+ * [Redirecting back after sign-in](#redirecting-back-after-sign-in)
28
+ * [Claiming tokens](#claiming-tokens)
29
+ * [E-mail security](#e-mail-security)
28
30
  * [License](#license)
29
31
 
30
32
  ## Installation
@@ -90,7 +92,7 @@ class ApplicationController < ActionController::Base
90
92
 
91
93
  def require_user!
92
94
  return if current_user
93
- redirect_to root_path, flash: {error: 'You are not worthy!'}
95
+ redirect_to root_path, flash: { error: 'You are not worthy!' }
94
96
  end
95
97
  end
96
98
  ```
@@ -136,7 +138,7 @@ class UsersController < ApplicationController
136
138
 
137
139
  if @user.save
138
140
  sign_in @user # <-- This!
139
- redirect_to @user, flash: {notice: 'Welcome!'}
141
+ redirect_to @user, flash: { notice: 'Welcome!' }
140
142
  else
141
143
  render :new
142
144
  end
@@ -146,7 +148,97 @@ class UsersController < ApplicationController
146
148
  end
147
149
  ```
148
150
 
149
- ### Generating tokens
151
+ ### URLs and links
152
+
153
+ By default, Passwordless uses the resource name given to `passwordless_for` to generate its routes and helpers.
154
+
155
+ ```ruby
156
+ passwordless_for :users
157
+ # <%= users.sign_in_path %> # => /users/sign_in
158
+
159
+ passwordless_for :users, at: '/', as: :auth
160
+ # <%= auth.sign_in_path %> # => /sign_in
161
+ ```
162
+
163
+ Also be sure to [specify ActionMailer's `default_url_options.host`](http://guides.rubyonrails.org/action_mailer_basics.html#generating-urls-in-action-mailer-views).
164
+
165
+ ### Customize the way to send magic link
166
+
167
+ By default, magic link will send by email. You can customize this method. For example, you can send magic link via SMS.
168
+
169
+ config/initializers/passwordless.rb
170
+
171
+ ```
172
+ Passwordless.after_session_save = lambda do |session, request|
173
+ # Default behavior is
174
+ # Passwordless::Mailer.magic_link(session).deliver_now
175
+
176
+ # You can change behavior to do something with session model. For example,
177
+ # session.authenticatable.send_sms
178
+ end
179
+ ```
180
+
181
+ You can access user model through authenticatable.
182
+
183
+ ### Generate your own magic links
184
+
185
+ Currently there is not an officially supported way to generate your own magic links to send in your own mailers.
186
+
187
+ However, you can accomplish this with the following snippet of code.
188
+
189
+ ```
190
+ session = Passwordless::Session.new({
191
+ authenticatable: @manager,
192
+ user_agent: 'Command Line',
193
+ remote_addr: 'unknown',
194
+ })
195
+ session.save!
196
+ @magic_link = send(Passwordless.mounted_as).token_sign_in_url(session.token)
197
+ ```
198
+
199
+ You can further customize this URL by specifying the destination path to be redirected to after the user has logged in. You can do this by adding the `destination_path` query parameter to the end of the URL. For example
200
+ ```
201
+ @magic_link = "#{@magic_link}?destination_path=/your-custom-path"
202
+ ```
203
+
204
+ ### Overrides
205
+
206
+ By default `passwordless` uses the `passwordless_with` column to _case insensitively_ fetch the resource.
207
+
208
+ You can override this and provide your own customer fetcher by defining a class method `fetch_resource_for_passwordless` in your passwordless model. The method will be called with the downcased email and should return an `ActiveRecord` instance of the model.
209
+
210
+ Example time:
211
+
212
+ Let's say we would like to fetch the record and if it doesn't exist, create automatically.
213
+
214
+ ```ruby
215
+ class User < ApplicationRecord
216
+ def self.fetch_resource_for_passwordless(email)
217
+ find_or_create_by(email: email)
218
+ end
219
+ end
220
+ ```
221
+
222
+ ## Configuration
223
+
224
+ The following configuration parameters are supported. It is recommended to set these in `initializers/passwordless.rb`. The default values are shown below.
225
+
226
+ ```ruby
227
+ Passwordless.default_from_address = "CHANGE_ME@example.com"
228
+ Passwordless.token_generator = UrlSafeBase64Generator.new # Used to generate magic link tokens.
229
+ Passwordless.restrict_token_reuse = false # By default a magic link token can be used multiple times.
230
+ Passwordless.redirect_back_after_sign_in = true # When enabled the user will be redirected to their previous page, or a page specified by the `destination_path` query parameter, if available.
231
+
232
+ Passwordless.expires_at = lambda { 1.year.from_now } # How long until a magic link expires.
233
+ Passwordless.timeout_at = lambda { 1.hour.from_now } # How long until a passwordless session expires.
234
+
235
+ # Default redirection paths
236
+ Passwordless.success_redirect_path = '/' # When a user succeeds in logging in.
237
+ Passwordless.failure_redirect_path = '/' # When a a login is failed for any reason.
238
+ Passwordless.sign_out_redirect_path = '/' # When a user logs out.
239
+ ```
240
+
241
+ ### Customizing token generation
150
242
 
151
243
  By default Passwordless generates tokens using `SecureRandom.urlsafe_base64` but you can change that by setting `Passwordless.token_generator` to something else that responds to `call(session)` eg.:
152
244
 
@@ -204,39 +296,6 @@ end
204
296
 
205
297
  This can be turned off with `Passwordless.redirect_back_after_sign_in = false` but if you just don't save the previous destination, you'll be fine.
206
298
 
207
- ### URLs and links
208
-
209
- By default, Passwordless uses the resource name given to `passwordless_for` to generate its routes and helpers.
210
-
211
- ```ruby
212
- passwordless_for :users
213
- # <%= users.sign_in_path %> # => /users/sign_in
214
-
215
- passwordless_for :users, at: '/', as: :auth
216
- # <%= auth.sign_in_path %> # => /sign_in
217
- ```
218
-
219
- Also be sure to [specify ActionMailer's `default_url_options.host`](http://guides.rubyonrails.org/action_mailer_basics.html#generating-urls-in-action-mailer-views).
220
-
221
-
222
- ### Customize the way to send magic link
223
-
224
- By default, magic link will send by email. You can customize this method. For example, you can send magic link via SMS.
225
-
226
- config/initializers/passwordless.rb
227
-
228
- ```
229
- Passwordless.after_session_save = lambda do |session, request|
230
- # Default behavior is
231
- # Passwordless::Mailer.magic_link(session).deliver_now
232
-
233
- # You can change behavior to do something with session model. For example,
234
- # session.authenticatable.send_sms
235
- end
236
- ```
237
-
238
- You can access user model through authenticatable.
239
-
240
299
  ### Claiming tokens
241
300
 
242
301
  Opt-in for marking tokens as `claimed` so they can only be used once.
@@ -269,25 +328,7 @@ end
269
328
  ```
270
329
  </details>
271
330
 
272
- ### Overrides
273
-
274
- By default `passwordless` uses the `passwordless_with` column to _case insensitively_ fetch the resource.
275
-
276
- You can override this and provide your own customer fetcher by defining a class method `fetch_resource_for_passwordless` in your passwordless model. The method will be called with the downcased email and should return an `ActiveRecord` instance of the model.
277
-
278
- Example time:
279
-
280
- Let's say we would like to fetch the record and if it doesn't exist, create automatically.
281
-
282
- ```ruby
283
- class User < ApplicationRecord
284
- def self.fetch_resource_for_passwordless(email)
285
- find_or_create_by(email: email)
286
- end
287
- end
288
- ```
289
-
290
- ### E-mail security
331
+ ## E-mail security
291
332
 
292
333
  There's no reason that this approach should be less secure than the usual username/password combo. In fact this is most often a more secure option, as users don't get to choose the weak passwords they still use. In a way this is just the same as having each user go through "Forgot password" on every login.
293
334
 
@@ -42,20 +42,15 @@ module Passwordless
42
42
  def show
43
43
  # Make it "slow" on purpose to make brute-force attacks more of a hassle
44
44
  BCrypt::Password.create(params[:token])
45
-
46
- destination =
47
- Passwordless.redirect_back_after_sign_in &&
48
- reset_passwordless_redirect_location!(authenticatable_class)
49
-
50
45
  sign_in passwordless_session
51
46
 
52
- redirect_to destination || main_app.root_path
47
+ redirect_to passwordless_success_redirect_path
53
48
  rescue Errors::TokenAlreadyClaimedError
54
49
  flash[:error] = I18n.t(".passwordless.sessions.create.token_claimed")
55
- redirect_to main_app.root_path
50
+ redirect_to passwordless_failure_redirect_path
56
51
  rescue Errors::SessionTimedOutError
57
52
  flash[:error] = I18n.t(".passwordless.sessions.create.session_expired")
58
- redirect_to main_app.root_path
53
+ redirect_to passwordless_failure_redirect_path
59
54
  end
60
55
 
61
56
  # match '/sign_out', via: %i[get delete].
@@ -63,7 +58,31 @@ module Passwordless
63
58
  # @see ControllerHelpers#sign_out
64
59
  def destroy
65
60
  sign_out authenticatable_class
66
- redirect_to main_app.root_path
61
+ redirect_to passwordless_sign_out_redirect_path
62
+ end
63
+
64
+ protected
65
+
66
+ def passwordless_sign_out_redirect_path
67
+ Passwordless.sign_out_redirect_path
68
+ end
69
+
70
+ def passwordless_failure_redirect_path
71
+ Passwordless.failure_redirect_path
72
+ end
73
+
74
+ def passwordless_query_redirect_path
75
+ query_redirect_uri = URI(params[:destination_path])
76
+ query_redirect_uri.to_s if query_redirect_uri.host.nil? || query_redirect_uri.host == URI(request.url).host
77
+ rescue URI::InvalidURIError, ArgumentError
78
+ nil
79
+ end
80
+
81
+ def passwordless_success_redirect_path
82
+ return Passwordless.success_redirect_path unless Passwordless.redirect_back_after_sign_in
83
+
84
+ session_redirect_url = reset_passwordless_redirect_location!(authenticatable_class)
85
+ passwordless_query_redirect_path || session_redirect_url || Passwordless.success_redirect_path
67
86
  end
68
87
 
69
88
  private
@@ -15,6 +15,9 @@ module Passwordless
15
15
 
16
16
  mattr_accessor(:expires_at) { lambda { 1.year.from_now } }
17
17
  mattr_accessor(:timeout_at) { lambda { 1.hour.from_now } }
18
+ mattr_accessor(:success_redirect_path) { "/" }
19
+ mattr_accessor(:failure_redirect_path) { "/" }
20
+ mattr_accessor(:sign_out_redirect_path) { "/" }
18
21
 
19
22
  mattr_accessor(:after_session_save) do
20
23
  lambda { |session, _request| Mailer.magic_link(session).deliver_now }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Passwordless
4
- VERSION = "0.8.2" # :nodoc:
4
+ VERSION = "0.9.0" # :nodoc:
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passwordless
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikkel Malmberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-30 00:00:00.000000000 Z
11
+ date: 2019-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails