auth_rails 1.0.2 → 1.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/README.md +44 -0
- data/app/controllers/auth_rails/api/auth_controller.rb +3 -3
- data/app/controllers/concerns/auth_rails/authentication.rb +1 -1
- data/auth_rails.gemspec +1 -0
- data/biome.json +24 -0
- data/docs/.vitepress/config.mts +90 -0
- data/docs/src/api-reference.md +362 -0
- data/docs/src/cli/configuration.md +152 -0
- data/docs/src/cli/migration.md +59 -0
- data/docs/src/customization/complex-retrieve-resource.md +33 -0
- data/docs/src/customization/custom-identifier.md +16 -0
- data/docs/src/customization/custom-password-validation.md +14 -0
- data/docs/src/customization/custom-response.md +63 -0
- data/docs/src/customization/custom-strategy.md +33 -0
- data/docs/src/index.md +14 -0
- data/docs/src/introduction/getting-started.md +111 -0
- data/docs/src/introduction/what-is-it.md +21 -0
- data/lib/auth_rails/class_methods.rb +44 -0
- data/lib/auth_rails/config.rb +6 -2
- data/lib/auth_rails/strategies/allowed_token_strategy.rb +1 -1
- data/lib/auth_rails/strategies/base_strategy.rb +1 -1
- data/lib/auth_rails/version.rb +1 -1
- data/package.json +16 -0
- data/pnpm-lock.yaml +1110 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15e71bc7d2e92cc25d3433db5adbd5608f70c5fbf9de27a234106d95d54d9957
|
4
|
+
data.tar.gz: cfab483acafa215d5530e8ec90904cdceadb55bb53074b69ad73c2ef756ab7ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92bbbfb5274f625b03f8879d9b5cf3f6e61d577a8c30e53bda9cd374e74b46fc821717c7bac9f116502d64f5f1fb55571cd424d0583de3a4b260726c0d4c5ffc
|
7
|
+
data.tar.gz: c4479a4db819b2ba649fed888c074185c751ffbccb71ba4278c9747c01adb9cb3bcf8e0db5eb47c3db60d7b015cb37bb64c4d4c63cb77bab869a4a0ef45d9da2
|
data/README.md
CHANGED
@@ -165,6 +165,50 @@ module Api
|
|
165
165
|
end
|
166
166
|
```
|
167
167
|
|
168
|
+
- In case your identifier is not email
|
169
|
+
|
170
|
+
```rb
|
171
|
+
Rails.application.config.to_prepare do
|
172
|
+
AuthRails.configure do |config|
|
173
|
+
config.resource_class = User # required
|
174
|
+
config.identifier_name = :username # must be string or symbol, default is email
|
175
|
+
end
|
176
|
+
end
|
177
|
+
```
|
178
|
+
|
179
|
+
- If you have a custom method to validate password
|
180
|
+
|
181
|
+
```rb
|
182
|
+
Rails.application.config.to_prepare do
|
183
|
+
AuthRails.configure do |config|
|
184
|
+
config.resource_class = User # required
|
185
|
+
config.identifier_name = :username # must be string or symbol, default is email
|
186
|
+
config.authenticate = ->(resource, password) { resource.password == password } # must be a proc, validate password
|
187
|
+
end
|
188
|
+
end
|
189
|
+
```
|
190
|
+
|
191
|
+
- Sometimes, you have a complex logic to get the user
|
192
|
+
|
193
|
+
```rb
|
194
|
+
Rails.application.config.to_prepare do
|
195
|
+
AuthRails.configure do |config|
|
196
|
+
config.resource_class = User # required
|
197
|
+
config.identifier_name = :username # this one is sub in jwt
|
198
|
+
config.dig_params = ->(params) { params[:identifier] } # must be a proc, how to get identifier from params
|
199
|
+
|
200
|
+
# how to get user from identifier
|
201
|
+
# identifier default is params[<identifier_name>]
|
202
|
+
# or extract from dig_params
|
203
|
+
config.retrieve_resource = lambda { |identifier|
|
204
|
+
User.where(email: identifier)
|
205
|
+
.or(User.where(username: identifier))
|
206
|
+
.first
|
207
|
+
}
|
208
|
+
end
|
209
|
+
end
|
210
|
+
```
|
211
|
+
|
168
212
|
# Strategy list
|
169
213
|
|
170
214
|
- allowed_token
|
@@ -4,9 +4,9 @@ module AuthRails
|
|
4
4
|
module Api
|
5
5
|
class AuthController < ApiController
|
6
6
|
def create
|
7
|
-
resource = AuthRails.
|
7
|
+
resource = AuthRails.retrieve_resource(params: params)
|
8
8
|
|
9
|
-
raise AuthRails.error_class, :unauthenticated if resource.blank? || !
|
9
|
+
raise AuthRails.error_class, :unauthenticated if resource.blank? || !AuthRails.authenticate(resource: resource, password: params[:password])
|
10
10
|
|
11
11
|
respond_to_create(generate_token(resource))
|
12
12
|
end
|
@@ -43,7 +43,7 @@ module AuthRails
|
|
43
43
|
|
44
44
|
def payload(resource)
|
45
45
|
{
|
46
|
-
sub: resource.
|
46
|
+
sub: resource.send(AuthRails.identifier_name)
|
47
47
|
}
|
48
48
|
end
|
49
49
|
|
@@ -10,7 +10,7 @@ module AuthRails
|
|
10
10
|
secret_key: Configuration::Jwt::AccessToken.secret_key
|
11
11
|
)
|
12
12
|
|
13
|
-
CurrentAuth.user = AuthRails.resource_class.find_by(
|
13
|
+
CurrentAuth.user = AuthRails.resource_class.find_by(AuthRails.identifier_name => payload[:sub])
|
14
14
|
|
15
15
|
raise AuthRails.error_class, :unauthenticated unless CurrentAuth.user
|
16
16
|
end
|
data/auth_rails.gemspec
CHANGED
data/biome.json
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "https://biomejs.dev/schemas/1.4.1/schema.json",
|
3
|
+
"organizeImports": {
|
4
|
+
"enabled": true
|
5
|
+
},
|
6
|
+
"linter": {
|
7
|
+
"enabled": true,
|
8
|
+
"rules": {
|
9
|
+
"recommended": true,
|
10
|
+
"complexity": {
|
11
|
+
"useArrowFunction": "off"
|
12
|
+
},
|
13
|
+
"style": {
|
14
|
+
"noParameterAssign": "off"
|
15
|
+
}
|
16
|
+
}
|
17
|
+
},
|
18
|
+
"javascript": {
|
19
|
+
"formatter": {
|
20
|
+
"indentStyle": "space",
|
21
|
+
"quoteStyle": "single"
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
@@ -0,0 +1,90 @@
|
|
1
|
+
import { defineConfig } from 'vitepress';
|
2
|
+
|
3
|
+
export default defineConfig({
|
4
|
+
title: 'AuthRails',
|
5
|
+
description: 'Simple authentication for Rails',
|
6
|
+
srcDir: './src',
|
7
|
+
base: '/auth_rails/',
|
8
|
+
themeConfig: {
|
9
|
+
nav: [
|
10
|
+
{
|
11
|
+
text: 'Guide',
|
12
|
+
link: '/introduction/what-is-it',
|
13
|
+
},
|
14
|
+
],
|
15
|
+
sidebar: [
|
16
|
+
{
|
17
|
+
text: 'Introduction',
|
18
|
+
items: [
|
19
|
+
{
|
20
|
+
text: 'What is AuthRails?',
|
21
|
+
link: '/introduction/what-is-it',
|
22
|
+
},
|
23
|
+
{
|
24
|
+
text: 'Getting Started',
|
25
|
+
link: '/introduction/getting-started',
|
26
|
+
},
|
27
|
+
],
|
28
|
+
},
|
29
|
+
{
|
30
|
+
text: 'CLI',
|
31
|
+
items: [
|
32
|
+
{
|
33
|
+
text: 'Configuration',
|
34
|
+
link: '/cli/configuration',
|
35
|
+
},
|
36
|
+
{
|
37
|
+
text: 'Migration',
|
38
|
+
link: '/cli/migration',
|
39
|
+
},
|
40
|
+
],
|
41
|
+
},
|
42
|
+
{
|
43
|
+
text: 'Customization',
|
44
|
+
items: [
|
45
|
+
{
|
46
|
+
text: 'Custom Strategy',
|
47
|
+
link: '/customization/custom-strategy',
|
48
|
+
},
|
49
|
+
{
|
50
|
+
text: 'Custom Response Data',
|
51
|
+
link: '/customization/custom-response',
|
52
|
+
},
|
53
|
+
{
|
54
|
+
text: 'Custom Password Validation',
|
55
|
+
link: '/customization/custom-password-validation',
|
56
|
+
},
|
57
|
+
{
|
58
|
+
text: 'Custom Identifier Column',
|
59
|
+
link: '/customization/custom-identifier',
|
60
|
+
},
|
61
|
+
{
|
62
|
+
text: 'Complex Retrieve Resource',
|
63
|
+
link: '/customization/complex-retrieve-resource',
|
64
|
+
},
|
65
|
+
],
|
66
|
+
},
|
67
|
+
{
|
68
|
+
text: 'API Reference',
|
69
|
+
link: '/api-reference',
|
70
|
+
},
|
71
|
+
],
|
72
|
+
outline: {
|
73
|
+
level: [2, 3],
|
74
|
+
label: 'On this page',
|
75
|
+
},
|
76
|
+
lastUpdated: {
|
77
|
+
text: 'Last updated',
|
78
|
+
formatOptions: {
|
79
|
+
dateStyle: 'full',
|
80
|
+
timeStyle: 'medium',
|
81
|
+
},
|
82
|
+
},
|
83
|
+
socialLinks: [
|
84
|
+
{
|
85
|
+
icon: 'github',
|
86
|
+
link: 'https://github.com/zgid123/auth_rails',
|
87
|
+
},
|
88
|
+
],
|
89
|
+
},
|
90
|
+
});
|
@@ -0,0 +1,362 @@
|
|
1
|
+
# API Reference
|
2
|
+
|
3
|
+
All features of AuthRails.
|
4
|
+
|
5
|
+
## Configuration
|
6
|
+
|
7
|
+
### dig_params
|
8
|
+
|
9
|
+
- Type: `Proc`
|
10
|
+
- Default: `nil`
|
11
|
+
- Required: `false`
|
12
|
+
|
13
|
+
Method to extract `identifier` for [`retrieve_resource`](/api-reference.html#retrieve-resource).
|
14
|
+
|
15
|
+
```rb
|
16
|
+
# frozen_string_literal: true
|
17
|
+
|
18
|
+
Rails.application.config.to_prepare do
|
19
|
+
AuthRails.configure do |config|
|
20
|
+
config.resource_class = User
|
21
|
+
config.identifier_name = :username
|
22
|
+
config.dig_params = ->(params) { params[:identifier] }
|
23
|
+
|
24
|
+
config.retrieve_resource = lambda { |identifier|
|
25
|
+
User.where(email: identifier)
|
26
|
+
.or(User.where(username: identifier))
|
27
|
+
.first
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
`identifier_name` will be used for JWT's payload's `sub` if you have `dig_params` configuration.
|
34
|
+
|
35
|
+
### error_class
|
36
|
+
|
37
|
+
- Type: `Class`
|
38
|
+
- Default: `nil`
|
39
|
+
- Required: `false`
|
40
|
+
|
41
|
+
Custom error class for AuthRails.
|
42
|
+
|
43
|
+
Whenever AuthRails raises error, it will raise your error.
|
44
|
+
|
45
|
+
```rb
|
46
|
+
# frozen_string_literal: true
|
47
|
+
|
48
|
+
Rails.application.config.to_prepare do
|
49
|
+
AuthRails.configure do |config|
|
50
|
+
config.resource_class = User
|
51
|
+
config.error_class = YourError
|
52
|
+
end
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
### authenticate
|
57
|
+
|
58
|
+
- Type: `Proc`
|
59
|
+
- Default: `nil`
|
60
|
+
- Required: `false`
|
61
|
+
|
62
|
+
Custom method to validate your user password. If not provided, you must add `has_secure_password` to your model. Or create a method called `authenticate` to do the validation for your model. Or else it will raise error.
|
63
|
+
|
64
|
+
```rb
|
65
|
+
# frozen_string_literal: true
|
66
|
+
|
67
|
+
Rails.application.config.to_prepare do
|
68
|
+
AuthRails.configure do |config|
|
69
|
+
config.resource_class = User
|
70
|
+
config.authenticate = ->(resource, password) { resource.password == password }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
### resource_class
|
76
|
+
|
77
|
+
- Type: `Class`
|
78
|
+
- Default: `nil`
|
79
|
+
- Required: `true`
|
80
|
+
|
81
|
+
Your own class to do sign in. Usually it is `User`.
|
82
|
+
|
83
|
+
```rb
|
84
|
+
# frozen_string_literal: true
|
85
|
+
|
86
|
+
Rails.application.config.to_prepare do
|
87
|
+
AuthRails.configure do |config|
|
88
|
+
config.resource_class = User
|
89
|
+
end
|
90
|
+
end
|
91
|
+
```
|
92
|
+
|
93
|
+
### identifier_name
|
94
|
+
|
95
|
+
- Type: `String` | `Symbol`
|
96
|
+
- Default: `:email`
|
97
|
+
- Required: `false`
|
98
|
+
|
99
|
+
Your resource class identifier.
|
100
|
+
|
101
|
+
```rb
|
102
|
+
# frozen_string_literal: true
|
103
|
+
|
104
|
+
Rails.application.config.to_prepare do
|
105
|
+
AuthRails.configure do |config|
|
106
|
+
config.resource_class = User
|
107
|
+
config.identifier_name = :username
|
108
|
+
end
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
### retrieve_resource
|
113
|
+
|
114
|
+
- Type: `Proc`
|
115
|
+
- Default: `nil`
|
116
|
+
- Required: `false`
|
117
|
+
|
118
|
+
Method to custom how to get resource when your project requires a complex logic.
|
119
|
+
|
120
|
+
```rb
|
121
|
+
# frozen_string_literal: true
|
122
|
+
|
123
|
+
Rails.application.config.to_prepare do
|
124
|
+
AuthRails.configure do |config|
|
125
|
+
config.resource_class = User
|
126
|
+
config.identifier_name = :username
|
127
|
+
config.dig_params = ->(params) { params[:identifier] }
|
128
|
+
|
129
|
+
config.retrieve_resource = lambda { |identifier|
|
130
|
+
User.where(email: identifier)
|
131
|
+
.or(User.where(username: identifier))
|
132
|
+
.first
|
133
|
+
}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
#### config.identifier_name
|
139
|
+
|
140
|
+
This is used for JWT's payload's `sub`.
|
141
|
+
|
142
|
+
#### config.dig_params
|
143
|
+
|
144
|
+
This extracts `identifier` from parameters for the provided method.
|
145
|
+
|
146
|
+
## JWT Configuration
|
147
|
+
|
148
|
+
### jwt.strategy
|
149
|
+
|
150
|
+
- Type: `Class`
|
151
|
+
- Default: `AuthRails::Strategies::BaseStrategy`
|
152
|
+
- Required: `false`
|
153
|
+
|
154
|
+
Specify which strategy to handle `refresh_token`.
|
155
|
+
|
156
|
+
```rb
|
157
|
+
# frozen_string_literal: true
|
158
|
+
|
159
|
+
class YourOwnStrategy < AuthRails::Strategies::BaseStrategy
|
160
|
+
end
|
161
|
+
|
162
|
+
AuthRails.configure do |config|
|
163
|
+
config.jwt do |jwt|
|
164
|
+
jwt.strategy = YourOwnStrategy
|
165
|
+
end
|
166
|
+
end
|
167
|
+
```
|
168
|
+
|
169
|
+
## JWT Access Token Configuration
|
170
|
+
|
171
|
+
### access_token.exp
|
172
|
+
|
173
|
+
- Type: `ActiveSupport::TimeWithZone`
|
174
|
+
- Default: `nil`
|
175
|
+
- Required: `false`
|
176
|
+
|
177
|
+
Expiry time for `access_token`.
|
178
|
+
|
179
|
+
```rb
|
180
|
+
# frozen_string_literal: true
|
181
|
+
|
182
|
+
AuthRails.configure do |config|
|
183
|
+
config.jwt do |jwt|
|
184
|
+
jwt.strategy = AuthRails::Strategies::AllowedTokenStrategy
|
185
|
+
|
186
|
+
jwt.access_token do |access_token|
|
187
|
+
access_token.exp = 1.hour.since
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
```
|
192
|
+
|
193
|
+
### access_token.algorithm
|
194
|
+
|
195
|
+
- Type: `string`
|
196
|
+
- Default: `HS256`
|
197
|
+
- Required: `false`
|
198
|
+
|
199
|
+
Algorithm for JWT generator.
|
200
|
+
|
201
|
+
```rb
|
202
|
+
# frozen_string_literal: true
|
203
|
+
|
204
|
+
AuthRails.configure do |config|
|
205
|
+
config.jwt do |jwt|
|
206
|
+
jwt.strategy = AuthRails::Strategies::AllowedTokenStrategy
|
207
|
+
|
208
|
+
jwt.access_token do |access_token|
|
209
|
+
access_token.exp = 1.hour.since
|
210
|
+
access_token.algorithm = 'HS384'
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
```
|
215
|
+
|
216
|
+
### access_token.secret_key
|
217
|
+
|
218
|
+
- Type: `string`
|
219
|
+
- Default: `nil`
|
220
|
+
- Required: `false`
|
221
|
+
|
222
|
+
Secret token for JWT generator.
|
223
|
+
|
224
|
+
```rb
|
225
|
+
# frozen_string_literal: true
|
226
|
+
|
227
|
+
AuthRails.configure do |config|
|
228
|
+
config.jwt do |jwt|
|
229
|
+
jwt.strategy = AuthRails::Strategies::AllowedTokenStrategy
|
230
|
+
|
231
|
+
jwt.access_token do |access_token|
|
232
|
+
access_token.exp = 1.hour.since
|
233
|
+
access_token.algorithm = 'HS384'
|
234
|
+
access_token.secret_key = 'My Secret Key'
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
```
|
239
|
+
|
240
|
+
## JWT Refresh Token Configuration
|
241
|
+
|
242
|
+
### refresh_token.exp
|
243
|
+
|
244
|
+
- Type: `ActiveSupport::TimeWithZone`
|
245
|
+
- Default: `nil`
|
246
|
+
- Required: `false`
|
247
|
+
|
248
|
+
Expiry time for `refresh_token`.
|
249
|
+
|
250
|
+
```rb
|
251
|
+
# frozen_string_literal: true
|
252
|
+
|
253
|
+
AuthRails.configure do |config|
|
254
|
+
config.jwt do |jwt|
|
255
|
+
jwt.strategy = AuthRails::Strategies::AllowedTokenStrategy
|
256
|
+
|
257
|
+
jwt.refresh_token do |refresh_token|
|
258
|
+
refresh_token.exp = 1.hour.since
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
```
|
263
|
+
|
264
|
+
### refresh_token.algorithm
|
265
|
+
|
266
|
+
- Type: `string`
|
267
|
+
- Default: `nil`
|
268
|
+
- Required: `false`
|
269
|
+
|
270
|
+
Algorithm for JWT generator.
|
271
|
+
|
272
|
+
```rb
|
273
|
+
# frozen_string_literal: true
|
274
|
+
|
275
|
+
AuthRails.configure do |config|
|
276
|
+
config.jwt do |jwt|
|
277
|
+
jwt.strategy = AuthRails::Strategies::AllowedTokenStrategy
|
278
|
+
|
279
|
+
jwt.refresh_token do |refresh_token|
|
280
|
+
refresh_token.exp = 1.hour.since
|
281
|
+
refresh_token.algorithm = 'HS384'
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
```
|
286
|
+
|
287
|
+
### refresh_token.secret_key
|
288
|
+
|
289
|
+
- Type: `string`
|
290
|
+
- Default: `nil`
|
291
|
+
- Required: `false`
|
292
|
+
|
293
|
+
Secret token for JWT generator.
|
294
|
+
|
295
|
+
```rb
|
296
|
+
# frozen_string_literal: true
|
297
|
+
|
298
|
+
AuthRails.configure do |config|
|
299
|
+
config.jwt do |jwt|
|
300
|
+
jwt.strategy = AuthRails::Strategies::AllowedTokenStrategy
|
301
|
+
|
302
|
+
jwt.refresh_token do |refresh_token|
|
303
|
+
refresh_token.exp = 1.hour.since
|
304
|
+
refresh_token.algorithm = 'HS384'
|
305
|
+
refresh_token.secret_key = 'My Secret Key'
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
```
|
310
|
+
|
311
|
+
### refresh_token.http_only
|
312
|
+
|
313
|
+
- Type: `boolean`
|
314
|
+
- Default: `false`
|
315
|
+
- Required: `false`
|
316
|
+
|
317
|
+
If true, before respond the `refresh_token`, AuthRails will set `refresh_token` as `httpOnly` cookie.
|
318
|
+
|
319
|
+
Cookie key will be `ref_tok`.
|
320
|
+
|
321
|
+
```rb
|
322
|
+
# frozen_string_literal: true
|
323
|
+
|
324
|
+
AuthRails.configure do |config|
|
325
|
+
config.jwt do |jwt|
|
326
|
+
jwt.strategy = AuthRails::Strategies::AllowedTokenStrategy
|
327
|
+
|
328
|
+
jwt.refresh_token do |refresh_token|
|
329
|
+
refresh_token.http_only = true
|
330
|
+
refresh_token.exp = 1.hour.since
|
331
|
+
refresh_token.algorithm = 'HS384'
|
332
|
+
refresh_token.secret_key = 'My Secret Key'
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
```
|
337
|
+
|
338
|
+
### refresh_token.cookie_key
|
339
|
+
|
340
|
+
- Type: `String` | `Symbol`
|
341
|
+
- Default: `false`
|
342
|
+
- Required: `false`
|
343
|
+
|
344
|
+
Set cookie key for AuthRails when [`refresh_token.http_only`](/api-reference.html#refresh-token-http-only) is enabled.
|
345
|
+
|
346
|
+
```rb
|
347
|
+
# frozen_string_literal: true
|
348
|
+
|
349
|
+
AuthRails.configure do |config|
|
350
|
+
config.jwt do |jwt|
|
351
|
+
jwt.strategy = AuthRails::Strategies::AllowedTokenStrategy
|
352
|
+
|
353
|
+
jwt.refresh_token do |refresh_token|
|
354
|
+
refresh_token.http_only = true
|
355
|
+
refresh_token.exp = 1.hour.since
|
356
|
+
refresh_token.algorithm = 'HS384'
|
357
|
+
refresh_token.cookie_key = :my_ref_tok
|
358
|
+
refresh_token.secret_key = 'My Secret Key'
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
```
|