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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5e2b6983e76f48e3663946462d67f0dfdf62914aa8187c29a332111f430335f2
4
- data.tar.gz: 0cfbab5b379a053ff0f23406e25c045caa6d7ca2c249330d0ac24b459e6f1ecf
3
+ metadata.gz: c23b1737c22e177cbc5da56d7aab735c39408b87c6954b59b15b5f6fc3553021
4
+ data.tar.gz: 9906eabdf2bf3593d993bdfc6a6ac5234f346a9fa4f0c26b773fa4291a80fd3a
5
5
  SHA512:
6
- metadata.gz: 820ae8d2258753dd6e7f2f9bea7054537f0242aacc5218f220cc3a83d639a11a5204bcca728a95ec06e4ae8094994609abf0859f5df8162684a56c42bd27757b
7
- data.tar.gz: 9d6f9469c3c4d99cd42f0b410f89934951924c605cff3fe9bf7490064d790d1a814b20e154574de45d525b325acaac6ccd793496f2ffbc83645042e4f2a0268f
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
+ ![A default searls-auth login email](https://github.com/user-attachments/assets/07114dae-a95b-49bd-ba57-92042c62c1b7)
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.
@@ -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 (email)
6
- :user_finder_by_id, # proc (id)
7
- :user_finder_by_token, # proc (token)
8
- :user_initializer, # proc (params)
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 (user, params, errors = []), must return an array of error messages where empty means valid
28
- :after_login_success, # proc (user)
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: Searls::Auth.config.token_generator.call(user),
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
@@ -1,5 +1,5 @@
1
1
  module Searls
2
2
  module Auth
3
- VERSION = "0.1.0"
3
+ VERSION = "0.1.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searls-auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Searls