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 +4 -4
- data/README.md +107 -66
- data/app/controllers/passwordless/sessions_controller.rb +28 -9
- data/lib/passwordless.rb +3 -0
- data/lib/passwordless/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 906aa2b5a4bf5184d18d837c68565897bbeaa110550e875f44aaa71c8fee4c01
|
4
|
+
data.tar.gz: b0155e0411c6f1ffca21b22f5f38da4f656c61770280bb3f0afa9ba9d1f6f737
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
###
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
data/lib/passwordless.rb
CHANGED
@@ -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 }
|
data/lib/passwordless/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2019-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|