yiffspace-auth 0.0.3 → 0.0.5
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 +15 -0
- data/app/controllers/yiff_space/auth/webhook_controller.rb +1 -1
- data/lib/yiffspace/auth/client.rb +6 -1
- data/lib/yiffspace/auth/helper.rb +78 -12
- data/lib/yiffspace/auth/version.rb +1 -1
- data/lib/yiffspace/auth.rb +32 -0
- data/lib/yiffspace/serializers/anonymous_auth_info_serializer.rb +0 -2
- data/lib/yiffspace/serializers/anonymous_user_info_serializer.rb +0 -2
- data/lib/yiffspace/serializers/auth_info_serializer.rb +0 -2
- data/lib/yiffspace/serializers/discord_info_serializer.rb +0 -2
- data/lib/yiffspace/serializers/permissions_serializer.rb +0 -2
- data/lib/yiffspace/serializers/user_info_serializer.rb +0 -2
- 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: 797ac14850c6fb1331452f93c0f751e9096ea74aa16d9ed488f1e32acfb17da1
|
|
4
|
+
data.tar.gz: 0c2cbc7304003f8ff54cfe0ccf236e89fb16ff89fa801e7537a931bca70cf2d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e81232dbb0d624cf5982b96d80ad454fef794f5fd3b7157bb056807265890e97c27bc9f63ecb2ef2cae784fbb9af1b62c752d6f02c8ad393438340b82acf3aa8
|
|
7
|
+
data.tar.gz: c97f9aca4937066941ddd271041afa13725854cd605b938bb070c748189d360645aa863c7f7ea13d9b4ae059239b117408694f64234efb5cac5e853d5dcfbf04
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
## 0.0.5
|
|
2
|
+
|
|
3
|
+
- Add auth spoofing: `YiffSpace::Auth.enable_spoof_auth!`/`disable_spoof_auth!`
|
|
4
|
+
toggle a global switch, and setting `spoof_user_id` (plus optional
|
|
5
|
+
`spoof_permissions`/`spoof_roles`) on a `Client` makes every request through
|
|
6
|
+
that client log in as that user via `Helper#auth`/`#user`, without touching
|
|
7
|
+
the real session. Intended for local development - the gem doesn't gate this
|
|
8
|
+
by environment itself, so only call `enable_spoof_auth!` from somewhere the
|
|
9
|
+
host app already restricts to development (see `enable_debug_action!`).
|
|
10
|
+
Controllers can override this per-request: the `disable_spoof_auth`/
|
|
11
|
+
`override_spoof_auth` class macros (and the underlying `spoof_override=`
|
|
12
|
+
setter, for values only known at request time) let a controller opt out of
|
|
13
|
+
spoofing entirely, or swap in its own `spoof_user_id`/`spoof_permissions`/
|
|
14
|
+
`spoof_roles` independent of the client's configured defaults.
|
|
15
|
+
|
|
1
16
|
## 0.0.1
|
|
2
17
|
|
|
3
18
|
- Initial release, extracted from the `yiffspace` gem's `YiffSpace::Auth::*`
|
|
@@ -8,7 +8,8 @@ module YiffSpace
|
|
|
8
8
|
class Client
|
|
9
9
|
attr_accessor(:client_id, :client_secret, :scopes, :resource,
|
|
10
10
|
:redirect_uri, :server_url, :auth_session_key, :user_session_key,
|
|
11
|
-
:update_discord_images, :permissions_separator, :logto_webhook_secret
|
|
11
|
+
:update_discord_images, :permissions_separator, :logto_webhook_secret,
|
|
12
|
+
:spoof_user_id, :spoof_permissions, :spoof_roles)
|
|
12
13
|
|
|
13
14
|
attr_reader(:name)
|
|
14
15
|
|
|
@@ -22,6 +23,10 @@ module YiffSpace
|
|
|
22
23
|
@update_discord_images = true
|
|
23
24
|
@permissions_separator = ":"
|
|
24
25
|
@logto_webhook_secret = nil
|
|
26
|
+
# See YiffSpace::Auth.enable_spoof_auth! - spoofing is off for this client until spoof_user_id is set.
|
|
27
|
+
@spoof_user_id = nil
|
|
28
|
+
@spoof_permissions = []
|
|
29
|
+
@spoof_roles = []
|
|
25
30
|
end
|
|
26
31
|
|
|
27
32
|
def logto(controller)
|
|
@@ -8,17 +8,10 @@ module YiffSpace
|
|
|
8
8
|
module Helper
|
|
9
9
|
extend(ActiveSupport::Concern)
|
|
10
10
|
|
|
11
|
-
# auth/user session values (raw Discord profile + OIDC token claims) can easily exceed a
|
|
12
|
-
# cookie's ~4KB limit, so the session cookie itself only holds an opaque pointer - the real
|
|
13
|
-
# payload lives in Rails.cache (already a hard dependency of this module, see
|
|
14
|
-
# #sync_auth_if_dirty! below), keyed off that pointer.
|
|
15
|
-
SESSION_CACHE_KEY = "yiffspace:auth:session:%s"
|
|
16
|
-
SESSION_CACHE_TTL = 30.days
|
|
17
|
-
|
|
18
11
|
module ClassMethods
|
|
19
12
|
def set_client_name(name) # rubocop:disable Naming/AccessorMethodName
|
|
20
13
|
before_action do |controller|
|
|
21
|
-
controller.request.env[
|
|
14
|
+
controller.request.env[CLIENT_NAME_ENV] = name
|
|
22
15
|
if controller.respond_to?(:yiffspace_client_name=)
|
|
23
16
|
controller.yiffspace_client_name = name
|
|
24
17
|
elsif controller.respond_to?(:client_name=)
|
|
@@ -32,6 +25,24 @@ module YiffSpace
|
|
|
32
25
|
end
|
|
33
26
|
end
|
|
34
27
|
end
|
|
28
|
+
|
|
29
|
+
# Disables spoof auth for this controller (or just the actions matched by the given
|
|
30
|
+
# before_action options, e.g. `only:`/`except:`), regardless of the global switch or the
|
|
31
|
+
# client's spoof_user_id. Useful for controllers that must always see the real session
|
|
32
|
+
# (e.g. the auth engine's own login/callback controllers).
|
|
33
|
+
def disable_spoof_auth(**before_action_options)
|
|
34
|
+
before_action(**before_action_options) { |controller| controller.request.env[SPOOF_OVERRIDE_ENV] = false }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Overrides the user/permissions/roles spoofed for this controller (or just the actions
|
|
38
|
+
# matched by the given before_action options), independent of the client's configured
|
|
39
|
+
# spoof_user_id/spoof_permissions/spoof_roles. Still requires the global switch
|
|
40
|
+
# (YiffSpace::Auth.enable_spoof_auth!) to be on - this only changes *who* gets spoofed in,
|
|
41
|
+
# not whether spoofing happens at all.
|
|
42
|
+
def override_spoof_auth(spoof_user_id: nil, spoof_permissions: nil, spoof_roles: nil, **before_action_options)
|
|
43
|
+
overrides = { spoof_user_id: spoof_user_id, spoof_permissions: spoof_permissions, spoof_roles: spoof_roles }.compact
|
|
44
|
+
before_action(**before_action_options) { |controller| controller.request.env[SPOOF_OVERRIDE_ENV] = overrides }
|
|
45
|
+
end
|
|
35
46
|
end
|
|
36
47
|
|
|
37
48
|
def auth_raw
|
|
@@ -39,13 +50,14 @@ module YiffSpace
|
|
|
39
50
|
end
|
|
40
51
|
|
|
41
52
|
def auth
|
|
53
|
+
return spoofed_auth if spoofing?
|
|
42
54
|
return AuthInfo::Anonymous.instance if auth_raw.blank?
|
|
43
55
|
|
|
44
56
|
AuthInfo.from_session(auth_raw)
|
|
45
57
|
end
|
|
46
58
|
|
|
47
59
|
def auth?
|
|
48
|
-
auth_raw.present? && !auth.anonymous?
|
|
60
|
+
spoofing? || (auth_raw.present? && !auth.anonymous?)
|
|
49
61
|
end
|
|
50
62
|
|
|
51
63
|
def auth=(value)
|
|
@@ -62,13 +74,14 @@ module YiffSpace
|
|
|
62
74
|
end
|
|
63
75
|
|
|
64
76
|
def user
|
|
77
|
+
return spoofed_user if spoofing?
|
|
65
78
|
return UserInfo::Anonymous.instance if user_raw.blank?
|
|
66
79
|
|
|
67
80
|
UserInfo.from_session(user_raw)
|
|
68
81
|
end
|
|
69
82
|
|
|
70
83
|
def user?
|
|
71
|
-
user_raw.present? && !user.anonymous?
|
|
84
|
+
spoofing? || (user_raw.present? && !user.anonymous?)
|
|
72
85
|
end
|
|
73
86
|
|
|
74
87
|
def user=(value)
|
|
@@ -99,13 +112,12 @@ module YiffSpace
|
|
|
99
112
|
auth.permissions.has?(name)
|
|
100
113
|
end
|
|
101
114
|
|
|
102
|
-
DIRTY_FLAG_KEY = "yiffspace:auth:dirty:%s"
|
|
103
|
-
|
|
104
115
|
# Checks the dirty flag written by the Logto webhook handler. If set, re-fetches
|
|
105
116
|
# the user's current roles and permissions from the Logto Management API and
|
|
106
117
|
# rewrites the session — without waiting for the access token to expire.
|
|
107
118
|
# Call this as a before_action in any controller that needs instant revocation.
|
|
108
119
|
def sync_auth_if_dirty!
|
|
120
|
+
return if spoofing?
|
|
109
121
|
return unless auth?
|
|
110
122
|
|
|
111
123
|
flag_key = format(DIRTY_FLAG_KEY, auth.id)
|
|
@@ -156,8 +168,62 @@ module YiffSpace
|
|
|
156
168
|
request.env[CLIENT_NAME_ENV] = value.to_sym
|
|
157
169
|
end
|
|
158
170
|
|
|
171
|
+
# Per-request override set via the disable_spoof_auth/override_spoof_auth class macros, or
|
|
172
|
+
# by calling this setter directly (e.g. from a custom before_action, for values that can
|
|
173
|
+
# only be computed per-request). `false` disables spoofing; a Hash overrides individual
|
|
174
|
+
# :spoof_user_id/:spoof_permissions/:spoof_roles values; nil (the default) defers entirely
|
|
175
|
+
# to the client's configuration.
|
|
176
|
+
def spoof_override
|
|
177
|
+
respond_to?(:request, true) && request.env[SPOOF_OVERRIDE_ENV]
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def spoof_override=(value)
|
|
181
|
+
request.env[SPOOF_OVERRIDE_ENV] = value
|
|
182
|
+
end
|
|
183
|
+
|
|
159
184
|
private
|
|
160
185
|
|
|
186
|
+
# True when YiffSpace::Auth.enable_spoof_auth! has been called and a spoof user id resolves
|
|
187
|
+
# (from the client's spoof_user_id or a controller override). Clients without one keep
|
|
188
|
+
# behaving normally even with the global switch on, so spoofing is always opt-in.
|
|
189
|
+
def spoofing?
|
|
190
|
+
YiffSpace::Auth.spoof_auth? && resolved_spoof_user_id.present?
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def resolved_spoof_user_id
|
|
194
|
+
return nil if spoof_override == false
|
|
195
|
+
|
|
196
|
+
(spoof_override.is_a?(Hash) && spoof_override[:spoof_user_id]) || auth_client_config.spoof_user_id
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def resolved_spoof_permissions
|
|
200
|
+
(spoof_override.is_a?(Hash) && spoof_override[:spoof_permissions]) || auth_client_config.spoof_permissions
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def resolved_spoof_roles
|
|
204
|
+
(spoof_override.is_a?(Hash) && spoof_override[:spoof_roles]) || auth_client_config.spoof_roles
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Memoized per-request so repeated calls (controller + views) don't refetch the
|
|
208
|
+
# spoofed user from the Logto Management API on every access.
|
|
209
|
+
def spoofed_user
|
|
210
|
+
@spoofed_user ||= begin
|
|
211
|
+
config = auth_client_config
|
|
212
|
+
api_user = config.logto_management.get_or_create_user(resolved_spoof_user_id)
|
|
213
|
+
UserInfo.new(id: api_user.discord_id, user: api_user, discord: api_user.discord.serializable_hash)
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def spoofed_auth
|
|
218
|
+
@spoofed_auth ||= AuthInfo.new(
|
|
219
|
+
id: spoofed_user.id,
|
|
220
|
+
token: "spoofed",
|
|
221
|
+
roles: resolved_spoof_roles,
|
|
222
|
+
permissions: resolved_spoof_permissions,
|
|
223
|
+
client_id: auth_client_config.client_id,
|
|
224
|
+
)
|
|
225
|
+
end
|
|
226
|
+
|
|
161
227
|
def read_session_cache(session_key)
|
|
162
228
|
token = session[session_key]
|
|
163
229
|
return nil if token.blank?
|
data/lib/yiffspace/auth.rb
CHANGED
|
@@ -19,8 +19,23 @@ module YiffSpace
|
|
|
19
19
|
CLIENT_NAME_ENV = "yiffspace.auth.client_name"
|
|
20
20
|
DEFAULT_CLIENT_NAME = :default
|
|
21
21
|
|
|
22
|
+
# Per-request override of spoof auth, keyed off the request env like CLIENT_NAME_ENV is - see
|
|
23
|
+
# Helper#spoof_override/#spoof_override= below. `false` disables spoofing outright; a Hash
|
|
24
|
+
# overrides individual :spoof_user_id/:spoof_permissions/:spoof_roles values.
|
|
25
|
+
SPOOF_OVERRIDE_ENV = "yiffspace.auth.spoof_override"
|
|
26
|
+
|
|
27
|
+
# auth/user session values (raw Discord profile + OIDC token claims) can easily exceed a
|
|
28
|
+
# cookie's ~4KB limit, so the session cookie itself only holds an opaque pointer - the real
|
|
29
|
+
# payload lives in Rails.cache (already a hard dependency of Helper, see
|
|
30
|
+
# Helper#sync_auth_if_dirty! below), keyed off that pointer.
|
|
31
|
+
SESSION_CACHE_KEY = "yiffspace:auth:session:%s"
|
|
32
|
+
SESSION_CACHE_TTL = 30.days
|
|
33
|
+
|
|
34
|
+
DIRTY_FLAG_KEY = "yiffspace:auth:dirty:%s"
|
|
35
|
+
|
|
22
36
|
@clients = {}
|
|
23
37
|
@enable_debug_action = false
|
|
38
|
+
@spoof_auth = false
|
|
24
39
|
|
|
25
40
|
module_function
|
|
26
41
|
|
|
@@ -54,6 +69,23 @@ module YiffSpace
|
|
|
54
69
|
def disable_debug_action!
|
|
55
70
|
@enable_debug_action = false
|
|
56
71
|
end
|
|
72
|
+
|
|
73
|
+
# Global kill switch for auth spoofing. When enabled, any client with a
|
|
74
|
+
# `spoof_user_id` configured logs every request in as that user instead of
|
|
75
|
+
# reading the real session - see Helper#auth/#user. There's no environment
|
|
76
|
+
# check here (mirrors enable_debug_action!) - it's on the host app to only
|
|
77
|
+
# ever call this from somewhere gated to development.
|
|
78
|
+
def spoof_auth?
|
|
79
|
+
@spoof_auth
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def enable_spoof_auth!
|
|
83
|
+
@spoof_auth = true
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def disable_spoof_auth!
|
|
87
|
+
@spoof_auth = false
|
|
88
|
+
end
|
|
57
89
|
end
|
|
58
90
|
|
|
59
91
|
class Configuration
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yiffspace-auth
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Donovan_DMC
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-08-23 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: httparty
|