searls-auth 0.1.0 → 0.1.1
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/CHANGELOG.md +4 -0
- data/README.md +88 -0
- data/lib/searls/auth/config.rb +9 -9
- data/lib/searls/auth/emails_link.rb +20 -1
- data/lib/searls/auth/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c23b1737c22e177cbc5da56d7aab735c39408b87c6954b59b15b5f6fc3553021
|
4
|
+
data.tar.gz: 9906eabdf2bf3593d993bdfc6a6ac5234f346a9fa4f0c26b773fa4291a80fd3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2cbd987345d290d2648a67817531f571482f56002a71b5a7a0aacae01f89afc93cc799cf248712f3eae72c630623d4915cf0f3d5f8c71e238a740a9701a6bd35
|
7
|
+
data.tar.gz: a1e03993409a4306dfe443385c993fa6e9d53f2328914311c46996c263212fcbe0b7d45e93d1a7ed092dc45ea4c2eadb149384d11a97dca097240648ee8f052e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.1.1] - 2025-04-27
|
4
|
+
|
5
|
+
* Improve error message when token generation fails due to a token not being configured on the user model
|
6
|
+
|
3
7
|
## [0.1.0] - 2025-04-26
|
4
8
|
|
5
9
|
* Add `max_allowed_short_code_attempts` configuration, beyond which the code is erased from the session and the user needs to login again (default: 10)
|
data/README.md
CHANGED
@@ -1 +1,89 @@
|
|
1
1
|
# searls-auth
|
2
|
+
|
3
|
+
This gem provides a Ruby on Rails engine that implements a minimal, opinionated, and pleasant email-based authentication system. It has zero other dependencies, which is the correct number of dependencies.
|
4
|
+
|
5
|
+
For a detailed walk-through with pictures and whatnot, check out this [example app README](/example/simple_app/README.md). Below you'll find the basic steps for getting started.
|
6
|
+
|
7
|
+
## Install it
|
8
|
+
|
9
|
+
Add it to your Gemfile and `bundle` it:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem "searls-auth"
|
13
|
+
```
|
14
|
+
|
15
|
+
## Mount it
|
16
|
+
|
17
|
+
Next, you need to mount the gem's Engine to host any of the authentication controllers and mailers.
|
18
|
+
|
19
|
+
You can mount the engine at whatever you path you like (mounting it to "/" can result in some goofy behavior, so maybe not that one). I just do "/auth" because I'm boring:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
# config/routes.rb
|
23
|
+
Rails.application.routes.draw do
|
24
|
+
# …
|
25
|
+
mount Searls::Auth::Engine => "/auth"
|
26
|
+
# …
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
If you run your development server and visit [http://localhost:3000/auth/login](http://localhost:3000/auth/login), you should see an ugly login page. (If things look really goofy, it's because the gem defaults to your app's `"application"` layout).
|
31
|
+
|
32
|
+
## Secure it
|
33
|
+
|
34
|
+
If you've got a `User` model with an `email` attribute, you're two-thirds of the way to this thing working. All you need now is to associate [a secure token](https://api.rubyonrails.org/classes/ActiveRecord/TokenFor/ClassMethods.html#method-i-generates_token_for) with the model named `:email_auth`.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
# app/models/user.rb
|
38
|
+
class User < ApplicationRecord
|
39
|
+
# …
|
40
|
+
generates_token_for :email_auth, expires_in: 30.minutes
|
41
|
+
# …
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
(You can [name all these things whatever you want](#configure-it), but this is what searls-auth will assume by default.)
|
46
|
+
|
47
|
+
I'm writing this README as I add searls-auth to my new [POSSE Party](https://posseparty.com) app. As soon as I added the above line I visited [http://localhost:3000/auth/login](http://localhost:3000/auth/login), typed in my email, hit "Log in", and saw this email get sent (thanks to [letter_opener](https://github.com/ryanb/letter_opener)):
|
48
|
+
|
49
|
+

|
50
|
+
|
51
|
+
When I pasted in the six-digit code into the (also ugly) default verification page, it auto-submitted the form. That's because my has a vanilla [import maps](https://guides.rubyonrails.org/working_with_javascript_in_rails.html#import-maps) configuration, the least-bad of the various JavaScript ordeals Rails has on offer. (Don't use import maps? Then I leave figuring out how to load the gem's [Stimulus controllers](app/javascript/controllers/searls_auth_login_controller.js) as an exercise to the reader.)
|
52
|
+
|
53
|
+
I repeated the process to ensure the "magic link" also would have worked by visiting [http://localhost:3000/auth/logout](http://localhost:3000/auth/logout) and then clicking the link.
|
54
|
+
|
55
|
+
## Configure it
|
56
|
+
|
57
|
+
Almost every user-facing thing searls-auth does is configurable, because authentication is an _intimate and precious_ thing that every application must find a way to tweak, brand, and confuse.
|
58
|
+
|
59
|
+
To configure things, create an initializer:
|
60
|
+
|
61
|
+
```
|
62
|
+
touch config/initializers/searls_auth.rb
|
63
|
+
```
|
64
|
+
|
65
|
+
And paste this into it as a starting point:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
Rails.application.config.after_initialize do
|
69
|
+
Searls::Auth.configure do |config|
|
70
|
+
# You can find the defaults here-ish:
|
71
|
+
# https://github.com/searlsco/searls-auth/blob/main/lib/searls/auth.rb#L14
|
72
|
+
#
|
73
|
+
# The expected type of each option is documented inline here-ish:
|
74
|
+
# https://github.com/searlsco/searls-auth/blob/main/lib/searls/auth/config.rb#L3
|
75
|
+
#
|
76
|
+
# (Note that many options can take a proc or a value, which you may want)
|
77
|
+
#
|
78
|
+
# Override any option like this:
|
79
|
+
# config.app_name = "POSSE Party"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
```
|
83
|
+
As stated in the comment above, you can find each configuration and its default value in the code.
|
84
|
+
|
85
|
+
## Use it
|
86
|
+
|
87
|
+
Of course, having a user be "logged in" or not doesn't mean anything if your application doesn't do anything with the knowledge. Users that are logged in will have `session[:user_id]` set to the value of the logged-in user's ID. Logged out users won't have anything set to `session[:user_id]`. What you do with that is your job, not this gem. (Wait, after 20 years does this mean I finally understand the difference between authentication and authorization? Better late than never.)
|
88
|
+
|
89
|
+
If this is your first rodeo and you just read the previous paragraph and thought, _yeah, but now what?_, check out the tail end of the [example app README](/example/simple_app/README.md), which shows an approach that a lot of apps use.
|
data/lib/searls/auth/config.rb
CHANGED
@@ -2,12 +2,12 @@ module Searls
|
|
2
2
|
module Auth
|
3
3
|
Config = Struct.new(
|
4
4
|
# Data setup
|
5
|
-
:user_finder_by_email, # proc
|
6
|
-
:user_finder_by_id, # proc
|
7
|
-
:user_finder_by_token, # proc
|
8
|
-
:user_initializer, # proc
|
5
|
+
:user_finder_by_email, # proc(email)
|
6
|
+
:user_finder_by_id, # proc(id)
|
7
|
+
:user_finder_by_token, # proc(token)
|
8
|
+
:user_initializer, # proc(params)
|
9
9
|
:user_name_method, # string
|
10
|
-
:token_generator, # proc
|
10
|
+
:token_generator, # proc()
|
11
11
|
:token_expiry_minutes, # integer
|
12
12
|
# Controller setup
|
13
13
|
:preserve_session_keys_after_logout, # array of symbols
|
@@ -21,11 +21,11 @@ module Searls
|
|
21
21
|
:mail_login_template_path, # string
|
22
22
|
:mail_login_template_name, # string
|
23
23
|
# Routing setup
|
24
|
-
:redirect_path_after_register, # string or proc, all new registrations redirect here
|
25
|
-
:default_redirect_path_after_login, # string or proc, only redirected here if redirect_path param not set
|
24
|
+
:redirect_path_after_register, # string or proc(user, params, request, routes), all new registrations redirect here
|
25
|
+
:default_redirect_path_after_login, # string or proc(user, params, request, routes), only redirected here if redirect_path param not set
|
26
26
|
# Hook setup
|
27
|
-
:validate_registration, # proc
|
28
|
-
:after_login_success, # proc
|
27
|
+
:validate_registration, # proc(user, params, errors = []), must return an array of error messages where empty means valid
|
28
|
+
:after_login_success, # proc(user)
|
29
29
|
# Branding setup
|
30
30
|
:app_name, # string
|
31
31
|
:app_url, # string
|
@@ -4,12 +4,31 @@ module Searls
|
|
4
4
|
def email(user:, short_code:, redirect_path: nil, redirect_subdomain: nil)
|
5
5
|
LoginLinkMailer.with(
|
6
6
|
user:,
|
7
|
-
token:
|
7
|
+
token: generate_token!(user),
|
8
8
|
short_code:,
|
9
9
|
redirect_path:,
|
10
10
|
redirect_subdomain:
|
11
11
|
).login_link.deliver_later
|
12
12
|
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def generate_token!(user)
|
17
|
+
Searls::Auth.config.token_generator.call(user)
|
18
|
+
rescue KeyError => e
|
19
|
+
raise Error, <<~MSG
|
20
|
+
Secure token generation for user failed!
|
21
|
+
|
22
|
+
Message: #{e.message}
|
23
|
+
User: #{user.inspect}
|
24
|
+
|
25
|
+
This can probably be fixed by adding a line like this to your #{user.class.name} class:
|
26
|
+
|
27
|
+
generates_token_for :email_auth, expires_in: 30.minutes
|
28
|
+
|
29
|
+
Otherwise, you may want to override searls-auth's "token_generator" setting with a proc of your own.
|
30
|
+
MSG
|
31
|
+
end
|
13
32
|
end
|
14
33
|
end
|
15
34
|
end
|
data/lib/searls/auth/version.rb
CHANGED