passwordless 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +55 -11
- data/app/controllers/passwordless/sessions_controller.rb +9 -3
- data/app/models/passwordless/session.rb +3 -2
- data/lib/passwordless.rb +3 -0
- data/lib/passwordless/version.rb +1 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00fe76a0b0247e700ff5868fcabf1dc82b1bffddd63437f21d5ec5c4dce83479
|
4
|
+
data.tar.gz: ff56c5859f448221da83458c17dd30623bd335942fe77e44bede19144a7dd49e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e3281f7a60b04f82796a00759a6aea284aeeafb237670c10f458a629ea02b0d55607f155b4efa257209f580aeb394b0bf33c69c5bce250ec3e179e01eecaf89
|
7
|
+
data.tar.gz: 81ddaae8d5120e6e1867a8992bc9c0b0f596933ba163dac63a1b3ad39b2b4ba40d84c6b69bb1764283ea9eac39eba199f1fbced0a91f1f93f16f10f01e56bf38
|
data/README.md
CHANGED
@@ -16,8 +16,10 @@ Add authentication to your Rails app without all the icky-ness of passwords.
|
|
16
16
|
* [Usage](#usage)
|
17
17
|
* [Getting the current user, restricting access, the usual](#getting-the-current-user-restricting-access-the-usual)
|
18
18
|
* [Providing your own templates](#providing-your-own-templates)
|
19
|
+
* [Overrides](#overrides)
|
19
20
|
* [Registering new users](#registering-new-users)
|
20
21
|
* [Generating tokens](#generating-tokens)
|
22
|
+
* [Token and Session Expiry](#token-and-session-expiry)
|
21
23
|
* [Redirecting back after sign-in](#redirecting-back-after-sign-in)
|
22
24
|
* [URLs and links](#urls-and-links)
|
23
25
|
* [E-mail security](#e-mail-security)
|
@@ -51,7 +53,7 @@ Then specify which field on your `User` record is the email field with:
|
|
51
53
|
```ruby
|
52
54
|
class User < ApplicationRecord
|
53
55
|
validates :email, presence: true, uniqueness: { case_sensitive: false }
|
54
|
-
|
56
|
+
|
55
57
|
passwordless_with :email # <-- here!
|
56
58
|
end
|
57
59
|
```
|
@@ -73,13 +75,13 @@ Passwordless doesn't give you `current_user` automatically -- it's dead easy to
|
|
73
75
|
```ruby
|
74
76
|
class ApplicationController < ActionController::Base
|
75
77
|
include Passwordless::ControllerHelpers # <-- This!
|
76
|
-
|
78
|
+
|
77
79
|
# ...
|
78
|
-
|
80
|
+
|
79
81
|
helper_method :current_user
|
80
|
-
|
82
|
+
|
81
83
|
private
|
82
|
-
|
84
|
+
|
83
85
|
def current_user
|
84
86
|
@current_user ||= authenticate_by_cookie(User)
|
85
87
|
end
|
@@ -96,7 +98,7 @@ Et voilà:
|
|
96
98
|
```ruby
|
97
99
|
class VerySecretThingsController < ApplicationController
|
98
100
|
before_action :require_user!
|
99
|
-
|
101
|
+
|
100
102
|
def index
|
101
103
|
@things = current_user.very_secret_things
|
102
104
|
end
|
@@ -118,6 +120,22 @@ app/views/passwordless/mailer/magic_link.text.erb
|
|
118
120
|
|
119
121
|
See [the bundled views](https://github.com/mikker/passwordless/tree/master/app/views/passwordless).
|
120
122
|
|
123
|
+
### Overrides
|
124
|
+
|
125
|
+
By default `passwordless` uses the `passwordless_with` column you specify in the model to case insensitively fetch the resource during authentication. 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 supplied with the downcased email and should return an `ActiveRecord` instance of the model.
|
126
|
+
|
127
|
+
Example time:
|
128
|
+
|
129
|
+
Let's say we would like to fetch the record and if it doesn't exist, create automatically.
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
class User < ApplicationRecord
|
133
|
+
def self.fetch_resource_for_passwordless(email)
|
134
|
+
find_or_create_by(email: email)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
121
139
|
### Registering new users
|
122
140
|
|
123
141
|
Because your `User` record is like any other record, you create one like you normally would. Passwordless provides a helper method you can use to sign in the created user after it is saved like so:
|
@@ -129,7 +147,7 @@ class UsersController < ApplicationController
|
|
129
147
|
|
130
148
|
def create
|
131
149
|
@user = User.new user_params
|
132
|
-
|
150
|
+
|
133
151
|
if @user.save
|
134
152
|
sign_in @user # <-- And this!
|
135
153
|
redirect_to @user, flash: {notice: 'Welcome!'}
|
@@ -137,7 +155,7 @@ class UsersController < ApplicationController
|
|
137
155
|
render :new
|
138
156
|
end
|
139
157
|
end
|
140
|
-
|
158
|
+
|
141
159
|
# ...
|
142
160
|
end
|
143
161
|
```
|
@@ -154,6 +172,32 @@ Passwordless.token_generator = -> (session) {
|
|
154
172
|
|
155
173
|
Session is going to keep generating tokens until it finds one that hasn't been used yet. So be sure to use some kind of method where matches are unlikely.
|
156
174
|
|
175
|
+
### Token and Session Expiry
|
176
|
+
|
177
|
+
Token timeout is the time by which the sign in token is invalidated. Post the timeout, the token cannot be used to sign-in to the app and the user would need to request it again.
|
178
|
+
|
179
|
+
Session expiry is the expiration time of the session of a logged in user. Once this is expired, user would need to log back in to create a new session.
|
180
|
+
|
181
|
+
#### Token timeout
|
182
|
+
|
183
|
+
By default, sign in tokens generated by Passwordless are made invalid after `1.hour` from the time they are generated. If you wish you can override this and supply your custom Proc function that will return a valid datetime object. Make sure the generated time is in the future.
|
184
|
+
|
185
|
+
> Make sure to use a `.call`able object, like a proc or lambda as it will be called everytime a session is created.
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
Passwordless.timeout_at = lambda { 2.hours.from_now }
|
189
|
+
```
|
190
|
+
|
191
|
+
#### Session Expiry
|
192
|
+
|
193
|
+
Session expiry is the time when the actual session is itself expired, i.e. users will be logged out and has to sign back in post this expiry time. By default, sessions are valid for `1.year` from the time they are generated. You can override by providing your custom Proc function that returns a datetime object.
|
194
|
+
|
195
|
+
> Make sure to use a `.call`able object, like a proc or lambda as it will be called everytime a session is created.
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
Passwordless.expires_at = lambda { 24.hours.from_now }
|
199
|
+
```
|
200
|
+
|
157
201
|
### Redirecting back after sign-in
|
158
202
|
|
159
203
|
By default Passwordless will redirect back to where the user wanted to go **if** it knows where that is, so you'll have to help it. `Passwordless::ControllerHelpers` provide a method for this:
|
@@ -161,9 +205,9 @@ By default Passwordless will redirect back to where the user wanted to go **if**
|
|
161
205
|
```ruby
|
162
206
|
class ApplicationController < ActionController::Base
|
163
207
|
include Passwordless::ControllerHelpers # <-- Probably already have this!
|
164
|
-
|
208
|
+
|
165
209
|
# ...
|
166
|
-
|
210
|
+
|
167
211
|
def require_user!
|
168
212
|
return if current_user
|
169
213
|
save_passwordless_redirect_location!(User) # <-- here we go!
|
@@ -181,7 +225,7 @@ By default, Passwordless uses the resource name given to `passwordless_for` to g
|
|
181
225
|
```ruby
|
182
226
|
passwordless_for :users
|
183
227
|
# <%= users.sign_in_path %> # => /users/sign_in
|
184
|
-
|
228
|
+
|
185
229
|
passwordless_for :users, at: '/', as: :auth
|
186
230
|
# <%= auth.sign_in_path %> # => /sign_in
|
187
231
|
```
|
@@ -90,9 +90,15 @@ module Passwordless
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def find_authenticatable
|
93
|
-
|
94
|
-
|
95
|
-
)
|
93
|
+
email = params[:passwordless][email_field].downcase
|
94
|
+
|
95
|
+
if authenticatable_class.respond_to?(:fetch_resource_for_passwordless)
|
96
|
+
authenticatable_class.fetch_resource_for_passwordless(email)
|
97
|
+
else
|
98
|
+
authenticatable_class.where(
|
99
|
+
"lower(#{email_field}) = ?", params[:passwordless][email_field].downcase
|
100
|
+
).first
|
101
|
+
end
|
96
102
|
end
|
97
103
|
|
98
104
|
def find_session
|
@@ -8,6 +8,7 @@ module Passwordless
|
|
8
8
|
polymorphic: true, inverse_of: :passwordless_sessions
|
9
9
|
|
10
10
|
validates \
|
11
|
+
:authenticatable,
|
11
12
|
:timeout_at,
|
12
13
|
:expires_at,
|
13
14
|
:user_agent,
|
@@ -28,8 +29,8 @@ module Passwordless
|
|
28
29
|
private
|
29
30
|
|
30
31
|
def set_defaults
|
31
|
-
self.expires_at ||=
|
32
|
-
self.timeout_at ||=
|
32
|
+
self.expires_at ||= Passwordless.expires_at.call
|
33
|
+
self.timeout_at ||= Passwordless.timeout_at.call
|
33
34
|
self.token ||= loop do
|
34
35
|
token = Passwordless.token_generator.call(self)
|
35
36
|
break token unless Session.find_by(token: token)
|
data/lib/passwordless.rb
CHANGED
@@ -9,4 +9,7 @@ module Passwordless
|
|
9
9
|
mattr_accessor(:token_generator) { UrlSafeBase64Generator.new }
|
10
10
|
mattr_accessor(:redirect_back_after_sign_in) { true }
|
11
11
|
mattr_accessor(:mounted_as) { :configured_when_mounting_passwordless }
|
12
|
+
|
13
|
+
mattr_accessor(:expires_at) { lambda { 1.year.from_now } }
|
14
|
+
mattr_accessor(:timeout_at) { lambda { 1.hour.from_now } }
|
12
15
|
end
|
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.6.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:
|
11
|
+
date: 2019-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -127,8 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
127
|
- !ruby/object:Gem::Version
|
128
128
|
version: '0'
|
129
129
|
requirements: []
|
130
|
-
|
131
|
-
rubygems_version: 2.7.6
|
130
|
+
rubygems_version: 3.0.2
|
132
131
|
signing_key:
|
133
132
|
specification_version: 4
|
134
133
|
summary: Add authentication to your app without all the ickyness of passwords.
|