Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)

Expand Down
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
25 changes: 20 additions & 5 deletions lib/omniauth/strategies/auth0.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,23 @@ class Auth0 < OmniAuth::Strategies::OAuth2
AUTHORIZATION_CODE_GRANT_TYPE = 'authorization_code'
CLIENT_ASSERTION_TYPE = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'

# Auth0 /authorize parameters forwarded from the request when present.
PASSTHROUGH_AUTHORIZE_PARAMS = %w[
connection
connection_scope
prompt
screen_hint
login_hint
organization
invitation
ui_locales
].freeze

option :name, 'auth0'

# Also forward request parameters whose name starts with one of these prefixes.
option :passthrough_prefixes, %w[ext-]

args %i[
client_id
client_secret
Expand Down Expand Up @@ -90,7 +105,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
Expand Down Expand Up @@ -128,10 +143,10 @@ 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)
# 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) }
end

def client_assertion_signing_key_auth?
Expand Down
42 changes: 42 additions & 0 deletions spec/omniauth/strategies/auth0_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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('--')
Expand Down