standard_id 0.29.0 → 0.29.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: e92eb10b6ca75511deb6b2b825b95fc79b25db73135d1cc6c637095e7466f8e8
4
- data.tar.gz: 4968ead0789aaeddb2ab68de34c224d951d988a18932e49e29125489cfa6eacb
3
+ metadata.gz: 4642a44dc7a0c1c24cc9a9c1d600f8cb902f79c3d2b418181e1e669d000818d7
4
+ data.tar.gz: 809d9802ea1d42c38f06b8675149862a837458cd6bf37c508d010f0804da7082
5
5
  SHA512:
6
- metadata.gz: 4c14b2551f993b7b7f9a20694ef337af4a9ebb05270c9a1cc343f43d3f3483d6196d1360786410b4140cc6c0214e82feadf5688019c347f66e0476958fb3c7c3
7
- data.tar.gz: b71083067ee12c30bfedc1a1ee5ac8b9181c47fcaf790e8ee60e00eee4d73ac5a1eadcbd496e51f7244fd08bd83ec0a5a412e2cc225901c259809645b482af9a
6
+ metadata.gz: 933380f52e99eb7b38352fc6c58f921a8c91a4f7992fabff910ed52d40cce731f623209de938ddf2ece269ab92f65ec1c5a525edd5ffec140400056340e7ef65
7
+ data.tar.gz: c7690d11c5065738e3c27a3e199d7a0d31535cdd4a3b93819ebb23356f8f91abd8b838d550c5c4347a4bf2e70d5e8ec04660e721a98e5f4083a3d3d410506319
@@ -75,6 +75,19 @@ module StandardId
75
75
  return true if destination.start_with?("/") && !destination.start_with?("//")
76
76
  return true if same_origin_url?(destination)
77
77
 
78
+ allow_listed_redirect?(destination)
79
+ end
80
+
81
+ # Whether the host has explicitly allow-listed `destination`'s prefix via
82
+ # `StandardId.config.allowed_redirect_url_prefixes`. This is the only way a
83
+ # cross-origin or custom-scheme destination (e.g. "myapp://done") clears
84
+ # `safe_destination?`, so it is also exactly the condition under which
85
+ # `redirect_to` needs `allow_other_host: true` — Rails otherwise raises
86
+ # UnsafeRedirectError. Mirrors the pattern already used by the social
87
+ # callback (Web::Auth::Callback::ProvidersController).
88
+ def allow_listed_redirect?(destination)
89
+ return false if destination.blank?
90
+
78
91
  Array(StandardId.config.allowed_redirect_url_prefixes).any? do |entry|
79
92
  case entry
80
93
  when Regexp then entry.match?(destination)
@@ -83,6 +96,34 @@ module StandardId
83
96
  end
84
97
  end
85
98
 
99
+ # Redirect a just-authenticated account to an already-validated `destination`.
100
+ #
101
+ # Uses `redirect_with_inertia` rather than `redirect_to` because the sign-in
102
+ # submit itself may be an Inertia XHR (hosts with `use_inertia` render the
103
+ # WebEngine's auth pages as Inertia components) while `destination` may not be
104
+ # an Inertia endpoint at all — the canonical case being the ApiEngine's
105
+ # /api/authorize in an OAuth flow. An Inertia client follows a 303 with its
106
+ # X-Inertia header still attached; inertia_rails' middleware then calls
107
+ # #inertia_configuration on the target controller, which ActionController::API
108
+ # controllers never receive (inertia_rails only includes its Controller module
109
+ # via `on_load(:action_controller_base)`), raising NoMethodError → 500.
110
+ # Emitting 409 + X-Inertia-Location instead makes the client do a full page
111
+ # visit, which drops the header. The destination being same-origin is not
112
+ # enough to make a plain redirect safe, so this deliberately keys off the
113
+ # request being Inertia rather than off the destination.
114
+ #
115
+ # `notice` is written to `flash` instead of being passed as a redirect option
116
+ # because `inertia_location` ignores redirect options — writing it to the
117
+ # session is what lets the message survive on both branches.
118
+ def redirect_after_authentication(destination, notice: nil, status: :see_other)
119
+ flash[:notice] = notice if notice.present?
120
+
121
+ options = { status: status }
122
+ options[:allow_other_host] = true if allow_listed_redirect?(destination)
123
+
124
+ redirect_with_inertia destination, **options
125
+ end
126
+
86
127
  def same_origin_url?(destination)
87
128
  return false unless destination.start_with?("http://", "https://")
88
129
  URI.parse(destination).origin == URI.parse(request.base_url).origin
@@ -81,7 +81,7 @@ module StandardId
81
81
  fallback = after_authentication_url
82
82
  fallback = safe_post_signin_default unless safe_destination?(fallback)
83
83
  destination = redirect_override || (safe_destination?(redirect_uri) ? redirect_uri : nil) || fallback
84
- redirect_to destination, status: :see_other, notice: "Successfully signed in"
84
+ redirect_after_authentication destination, notice: "Successfully signed in"
85
85
  else
86
86
  flash.now[:alert] = "Invalid email or password"
87
87
  render_with_inertia action: :show, props: auth_page_props(passwordless_enabled: passwordless_enabled?), status: :unprocessable_content
@@ -78,7 +78,7 @@ module StandardId
78
78
  # blocks Array/Hash but not "https://evil.com/phish". Validate before redirect.
79
79
  fallback = after_authentication_url
80
80
  destination = redirect_override || (safe_destination?(fallback) ? fallback : safe_post_signin_default)
81
- redirect_to destination, status: :see_other, notice: "Successfully signed in"
81
+ redirect_after_authentication destination, notice: "Successfully signed in"
82
82
  rescue StandardId::AuthenticationDenied => e
83
83
  session.delete(:standard_id_otp_payload)
84
84
  handle_authentication_denied(e, account: account, newly_created: newly_created)
@@ -56,7 +56,9 @@ module StandardId
56
56
  fallback = after_authentication_url
57
57
  fallback = safe_post_signin_default unless safe_destination?(fallback)
58
58
  destination = redirect_override || (safe_destination?(redirect_uri) ? redirect_uri : nil) || fallback
59
- redirect_to destination, notice: "Account created successfully"
59
+ # status: :found preserves this action's long-standing 302 (the other
60
+ # post-auth redirects use 303); only the Inertia branch changes here.
61
+ redirect_after_authentication destination, notice: "Account created successfully", status: :found
60
62
  else
61
63
  @redirect_uri = string_param(:redirect_uri) || after_authentication_url
62
64
  @connection = params[:connection]
@@ -1,3 +1,3 @@
1
1
  module StandardId
2
- VERSION = "0.29.0"
2
+ VERSION = "0.29.1"
3
3
  end
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.29.0
4
+ version: 0.29.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaryl Sim