standard_id 0.52.0 → 0.53.0
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 +41 -4
- data/README.md +48 -5
- data/lib/generators/standard_id/install/install_generator.rb +4 -1
- data/lib/generators/standard_id/install/templates/standard_id.rb +11 -563
- data/lib/generators/standard_id/install/templates/standard_id_reference.rb +581 -0
- data/lib/standard_id/app_environment.rb +26 -0
- data/lib/standard_id/config/schema.rb +9 -9
- data/lib/standard_id/engine.rb +1 -1
- data/lib/standard_id/passwordless/verification_service.rb +4 -4
- data/lib/standard_id/provider_registry.rb +1 -1
- data/lib/standard_id/testing/request_helpers.rb +99 -0
- data/lib/standard_id/version.rb +1 -1
- data/lib/standard_id.rb +1 -0
- metadata +3 -1
|
@@ -55,6 +55,105 @@ module StandardId
|
|
|
55
55
|
def bearer_auth_header(token)
|
|
56
56
|
{ "Authorization" => "Bearer #{token}" }
|
|
57
57
|
end
|
|
58
|
+
|
|
59
|
+
# Bearer headers for an account, in one call: build_jwt + bearer_auth_header.
|
|
60
|
+
#
|
|
61
|
+
# get "/api/orders", headers: bearer_headers_for(account, scope: "orders.read")
|
|
62
|
+
#
|
|
63
|
+
# @param account [Object] the account (its id becomes the sub claim)
|
|
64
|
+
# @param jwt_options [Hash] any other build_jwt keyword (scope:, client_id:, extra:, ...)
|
|
65
|
+
# @return [Hash] header hash
|
|
66
|
+
#
|
|
67
|
+
def bearer_headers_for(account, **jwt_options)
|
|
68
|
+
bearer_auth_header(build_jwt(account: account, **jwt_options))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Sign an account in for the following requests in a request spec,
|
|
72
|
+
# without driving a login form or stubbing controllers.
|
|
73
|
+
#
|
|
74
|
+
# Creates a real BrowserSession and writes the same encrypted
|
|
75
|
+
# `session_token` cookie that Web::SessionManager writes on a real
|
|
76
|
+
# sign-in, so `current_account`, `require_browser_session!` and the
|
|
77
|
+
# session's expiry and revocation all behave exactly as in production.
|
|
78
|
+
# With `scope:`, it also writes the Rails session cookie carrying
|
|
79
|
+
# `standard_id_scopes` (what `current_scope_names` reads), which needs
|
|
80
|
+
# the cookie session store; any other store raises ArgumentError.
|
|
81
|
+
#
|
|
82
|
+
# Nothing is added to the app: the cookies are built with the app's own
|
|
83
|
+
# encrypted cookie jar and secret_key_base, so there is no test-only route
|
|
84
|
+
# to forget to remove. Like a real sign-in (which resets the session), it
|
|
85
|
+
# always replaces the Rails session cookie: an earlier request's session
|
|
86
|
+
# data, and an earlier sign_in_as's scopes, never carry over to this
|
|
87
|
+
# account.
|
|
88
|
+
#
|
|
89
|
+
# sign_in_as(account)
|
|
90
|
+
# sign_in_as(account, scope: :platform)
|
|
91
|
+
# get "/dashboard"
|
|
92
|
+
#
|
|
93
|
+
# @param account [Object] the account to sign in
|
|
94
|
+
# @param scope [Symbol, String, Array, nil] scope name(s) to grant
|
|
95
|
+
# @param user_agent [String] stored on the BrowserSession
|
|
96
|
+
# @return [StandardId::BrowserSession] the session that was created
|
|
97
|
+
#
|
|
98
|
+
def sign_in_as(account, scope: nil, user_agent: "RSpec")
|
|
99
|
+
ensure_cookie_session_store! if scope
|
|
100
|
+
browser_session = create_browser_session(account, user_agent: user_agent)
|
|
101
|
+
jar = standard_id_cookie_jar
|
|
102
|
+
|
|
103
|
+
jar.encrypted[:session_token] = {
|
|
104
|
+
value: browser_session.token,
|
|
105
|
+
expires: browser_session.expires_at,
|
|
106
|
+
httponly: true
|
|
107
|
+
}
|
|
108
|
+
cookies[:session_token] = jar[:session_token]
|
|
109
|
+
|
|
110
|
+
if scope
|
|
111
|
+
write_standard_id_scopes(jar, scope)
|
|
112
|
+
elsif (key = rails_session_key)
|
|
113
|
+
cookies.delete(key)
|
|
114
|
+
end
|
|
115
|
+
browser_session
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
# The host app's cookie jar, outside any request: same secret_key_base,
|
|
121
|
+
# salts, serializer and rotations as a real request, so the cookies it
|
|
122
|
+
# writes read back exactly as Web::SessionManager's own.
|
|
123
|
+
def standard_id_cookie_jar
|
|
124
|
+
ActionDispatch::Request.new(Rails.application.env_config.deep_dup).cookie_jar
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Checked before anything is created, so a refused call leaves no session.
|
|
128
|
+
def ensure_cookie_session_store!
|
|
129
|
+
store = Rails.application.config.session_store
|
|
130
|
+
unless store.is_a?(Class) && store <= ActionDispatch::Session::CookieStore
|
|
131
|
+
raise ArgumentError,
|
|
132
|
+
"sign_in_as(scope:) writes the Rails session cookie, so it needs the cookie " \
|
|
133
|
+
"session store; this app uses #{store.inspect}. " \
|
|
134
|
+
"Sign in through the app's own scoped login request instead."
|
|
135
|
+
end
|
|
136
|
+
return if rails_session_key
|
|
137
|
+
|
|
138
|
+
raise ArgumentError,
|
|
139
|
+
"sign_in_as(scope:) needs the session cookie name (config.session_options[:key]), and it is not set"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def rails_session_key
|
|
143
|
+
Rails.application.config.session_options[:key]&.to_s
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def write_standard_id_scopes(jar, scope)
|
|
147
|
+
key = rails_session_key
|
|
148
|
+
jar.encrypted[key] = {
|
|
149
|
+
value: {
|
|
150
|
+
"session_id" => SecureRandom.hex(16),
|
|
151
|
+
"standard_id_scopes" => Array(scope).map(&:to_s)
|
|
152
|
+
},
|
|
153
|
+
httponly: true
|
|
154
|
+
}
|
|
155
|
+
cookies[key] = jar[key]
|
|
156
|
+
end
|
|
58
157
|
end
|
|
59
158
|
end
|
|
60
159
|
end
|
data/lib/standard_id/version.rb
CHANGED
data/lib/standard_id.rb
CHANGED
|
@@ -8,6 +8,7 @@ require "standard_id/api_engine"
|
|
|
8
8
|
require "standard_id/config_schema"
|
|
9
9
|
require "standard_id/config/schema"
|
|
10
10
|
require "standard_id/config/presets"
|
|
11
|
+
require "standard_id/app_environment"
|
|
11
12
|
require "standard_id/scope_config"
|
|
12
13
|
require "standard_id/association_strict_loading"
|
|
13
14
|
require "standard_id/migration_check"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: standard_id
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.53.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jaryl Sim
|
|
@@ -245,6 +245,7 @@ files:
|
|
|
245
245
|
- db/migrate/20261020120000_add_registration_access_token_digest_to_standard_id_client_applications.rb
|
|
246
246
|
- lib/generators/standard_id/install/install_generator.rb
|
|
247
247
|
- lib/generators/standard_id/install/templates/standard_id.rb
|
|
248
|
+
- lib/generators/standard_id/install/templates/standard_id_reference.rb
|
|
248
249
|
- lib/standard_id.rb
|
|
249
250
|
- lib/standard_id/account_cleanup.rb
|
|
250
251
|
- lib/standard_id/account_locking.rb
|
|
@@ -253,6 +254,7 @@ files:
|
|
|
253
254
|
- lib/standard_id/api/session_manager.rb
|
|
254
255
|
- lib/standard_id/api/token_manager.rb
|
|
255
256
|
- lib/standard_id/api_engine.rb
|
|
257
|
+
- lib/standard_id/app_environment.rb
|
|
256
258
|
- lib/standard_id/association_strict_loading.rb
|
|
257
259
|
- lib/standard_id/auth_lineage.rb
|
|
258
260
|
- lib/standard_id/authorization_bypass.rb
|