From eb0f566e7ada517d74884e62fe4e6d286acc9fc3 Mon Sep 17 00:00:00 2001 From: Kevin G Date: Thu, 28 May 2026 14:03:12 -0600 Subject: [PATCH 1/2] feat: configurable passthrough of custom /authorize query params Forward request parameters to the /authorize endpoint when their name starts with a configured prefix, via a new `passthrough_prefixes` option that defaults to `["ext-"]` (Auth0's documented convention for surfacing custom params to Universal Login and Actions) and can be set to `[]` to disable. This replaces the fork's hardcoded `ext-` check (is_authorized_param?) with an idiomatic, configurable implementation suitable for upstreaming: - Extracts the well-known Auth0 params into the frozen PASSTHROUGH_AUTHORIZE_PARAMS constant (behavior unchanged). - Renames the predicate to passthrough_param? (drops the non-idiomatic `is_` prefix) and tightens the select block. - Adds the `passthrough_prefixes` option, README docs citing Auth0's custom-query-parameter docs, and a CHANGELOG entry. - Adds specs for custom prefixes, prefix override, and the disabled case. Closes auth0/omniauth-auth0#214. Co-Authored-By: Claude Opus 4.7 --- CHANGELOG.md | 5 +++ README.md | 21 +++++++++++++ lib/omniauth/strategies/auth0.rb | 29 +++++++++++++++--- spec/omniauth/strategies/auth0_spec.rb | 42 ++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49a2464..844d1cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## [Unreleased](https://github.com/auth0/omniauth-auth0/tree/HEAD) + +**Added** +- Forward custom query parameters to `/authorize` via the configurable `passthrough_prefixes` option (defaults to `ext-`, set to `[]` to disable). Closes [\#214](https://github.com/auth0/omniauth-auth0/issues/214) + ## [v3.2.0](https://github.com/auth0/omniauth-auth0/tree/v3.2.0) (2026-05-27) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v3.1.1...v3.2.0) diff --git a/README.md b/README.md index b286c22..eb9cde9 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,27 @@ end **Note**: The client_assertion_signing_key must be provided as a PKey object. +### Forwarding query parameters to `/authorize` + +The well-known Auth0 `/authorize` parameters (`connection`, `connection_scope`, `prompt`, `screen_hint`, `login_hint`, `organization`, `invitation`, `ui_locales`) are forwarded from the request to the authorization endpoint when present. + +Auth0 also supports [custom query parameters](https://auth0.com/docs/customize/login-pages/universal-login/customize-templates#custom-query-parameters) that are surfaced to the Universal Login page and to Actions, as long as they are prefixed with `ext-`. Any request parameter whose name starts with a configured prefix is forwarded as well. This defaults to `ext-`, so a request to `/auth/auth0?ext-promo=summer` forwards `ext-promo=summer` to `/authorize`. + +Use the `passthrough_prefixes` option to add prefixes, or set it to `[]` to disable the behavior entirely: + +```ruby +Rails.application.config.middleware.use OmniAuth::Builder do + provider( + :auth0, + AUTH0_CONFIG['auth0_client_id'], + AUTH0_CONFIG['auth0_client_secret'], + AUTH0_CONFIG['auth0_domain'], + # Defaults to %w[ext-]; pass [] to forward no prefixed parameters. + passthrough_prefixes: %w[ext-] + ) +end +``` + ### Create the callback controller Create a new controller `./app/controllers/auth0_controller.rb` to handle the callback from Auth0. diff --git a/lib/omniauth/strategies/auth0.rb b/lib/omniauth/strategies/auth0.rb index f694364..a53ca83 100644 --- a/lib/omniauth/strategies/auth0.rb +++ b/lib/omniauth/strategies/auth0.rb @@ -17,8 +17,28 @@ class Auth0 < OmniAuth::Strategies::OAuth2 AUTHORIZATION_CODE_GRANT_TYPE = 'authorization_code' CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' + # Well-known Auth0 /authorize parameters that are forwarded from the + # request to the authorization endpoint when present. + # https://auth0.com/docs/api/authentication#login + PASSTHROUGH_AUTHORIZE_PARAMS = %w[ + connection + connection_scope + prompt + screen_hint + login_hint + organization + invitation + ui_locales + ].freeze + option :name, 'auth0' + # Request parameters whose name starts with one of these prefixes are + # also forwarded to /authorize. Auth0 surfaces `ext-` prefixed parameters + # to the Universal Login page and Actions. Set to [] to disable. + # https://auth0.com/docs/customize/login-pages/universal-login/customize-templates#custom-query-parameters + option :passthrough_prefixes, %w[ext-] + args %i[ client_id client_secret @@ -90,7 +110,7 @@ def client def authorize_params params = super - params.merge! request.params.select{|k,b| is_authorized_param?(k)} + params.merge!(request.params.select { |key, _value| passthrough_param?(key) }) # Generate nonce params[:nonce] = SecureRandom.hex @@ -128,10 +148,9 @@ def callback_phase private - def is_authorized_param?(param_key) - authorized_keys = %w[connection connection_scope prompt screen_hint login_hint organization invitation ui_locales] - - param_key.start_with?("ext-") || authorized_keys.include?(param_key) + def passthrough_param?(key) + PASSTHROUGH_AUTHORIZE_PARAMS.include?(key) || + Array(options.passthrough_prefixes).any? { |prefix| key.start_with?(prefix) } end def client_assertion_signing_key_auth? diff --git a/spec/omniauth/strategies/auth0_spec.rb b/spec/omniauth/strategies/auth0_spec.rb index 9ee0c8a..b3e5ce7 100644 --- a/spec/omniauth/strategies/auth0_spec.rb +++ b/spec/omniauth/strategies/auth0_spec.rb @@ -368,6 +368,48 @@ it_behaves_like 'oauth redirects with various parameters' end + context 'with a custom passthrough prefix configured' do + before do + @app = make_application(passthrough_prefixes: %w[custom-]) + end + + it 'forwards parameters matching the configured prefix' do + get 'auth/auth0?custom-foo=bar' + redirect_url = last_response.headers['Location'] + expect(redirect_url).to have_query('custom-foo', 'bar') + end + + it 'does not forward the default ext- prefix once overridden' do + get 'auth/auth0?ext-test=testval' + redirect_url = last_response.headers['Location'] + expect(redirect_url).not_to have_query('ext-test') + end + + it 'still forwards the standard Auth0 parameters' do + get 'auth/auth0?connection=abcd' + redirect_url = last_response.headers['Location'] + expect(redirect_url).to have_query('connection', 'abcd') + end + end + + context 'with passthrough prefixes disabled' do + before do + @app = make_application(passthrough_prefixes: []) + end + + it 'does not forward ext- prefixed parameters' do + get 'auth/auth0?ext-test=testval' + redirect_url = last_response.headers['Location'] + expect(redirect_url).not_to have_query('ext-test') + end + + it 'still forwards the standard Auth0 parameters' do + get 'auth/auth0?connection=abcd' + redirect_url = last_response.headers['Location'] + expect(redirect_url).to have_query('connection', 'abcd') + end + end + def session session_cookie = last_response.cookies['rack.session'].first session_data, _, _ = session_cookie.rpartition('--') From f4594e5eb47a06d9797adecbe8f4c0b59e6384cd Mon Sep 17 00:00:00 2001 From: Kevin G Date: Thu, 28 May 2026 14:24:23 -0600 Subject: [PATCH 2/2] style: match gem's terse comment style for passthrough params Drop the verbose multi-line comments with inline doc URLs in favor of single-line descriptions consistent with the rest of the strategy (e.g. "Setup client URLs...", "Check if the options include a client_id"). Usage details and the Auth0 docs link remain in the README. Co-Authored-By: Claude Opus 4.7 --- lib/omniauth/strategies/auth0.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/omniauth/strategies/auth0.rb b/lib/omniauth/strategies/auth0.rb index a53ca83..03d153b 100644 --- a/lib/omniauth/strategies/auth0.rb +++ b/lib/omniauth/strategies/auth0.rb @@ -17,9 +17,7 @@ class Auth0 < OmniAuth::Strategies::OAuth2 AUTHORIZATION_CODE_GRANT_TYPE = 'authorization_code' CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' - # Well-known Auth0 /authorize parameters that are forwarded from the - # request to the authorization endpoint when present. - # https://auth0.com/docs/api/authentication#login + # Auth0 /authorize parameters forwarded from the request when present. PASSTHROUGH_AUTHORIZE_PARAMS = %w[ connection connection_scope @@ -33,10 +31,7 @@ class Auth0 < OmniAuth::Strategies::OAuth2 option :name, 'auth0' - # Request parameters whose name starts with one of these prefixes are - # also forwarded to /authorize. Auth0 surfaces `ext-` prefixed parameters - # to the Universal Login page and Actions. Set to [] to disable. - # https://auth0.com/docs/customize/login-pages/universal-login/customize-templates#custom-query-parameters + # Also forward request parameters whose name starts with one of these prefixes. option :passthrough_prefixes, %w[ext-] args %i[ @@ -148,6 +143,7 @@ def callback_phase private + # Check if a request parameter should be forwarded to /authorize. def passthrough_param?(key) PASSTHROUGH_AUTHORIZE_PARAMS.include?(key) || Array(options.passthrough_prefixes).any? { |prefix| key.start_with?(prefix) }