passwordless 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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