From 1c35c3907c65f53d0f933aed28d90ac4d9b8b229 Mon Sep 17 00:00:00 2001 From: Siddhi Kotak Date: Wed, 23 Sep 2026 16:33:50 +0530 Subject: [PATCH 1/9] feat(auth0-react): expose Experiment Center override params on AuthorizationParameters --- EXAMPLES.md | 55 +++++++++++++++++++++++++++++- README.md | 17 ++++++++++ __tests__/auth-provider.test.tsx | 57 ++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 1 deletion(-) diff --git a/EXAMPLES.md b/EXAMPLES.md index 20992283..5f35ab8c 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -24,6 +24,7 @@ - [Session Expiry from Upstream IdP (IPSIE)](#session-expiry-from-upstream-idp-ipsie) - [Use Suspense for loading state (React 19+)](#use-suspense-for-loading-state-react-19) - [Enterprise Connect](#enterprise-connect) +- [Forcing an Experiment Center variant](#forcing-an-experiment-center-variant) ## Use with a Class Component @@ -2112,4 +2113,56 @@ await logout({ ``` The `returnTo` URL must be registered in the application's **Allowed Logout -URLs** in the Auth0 Dashboard, or the logout redirect will be rejected. \ No newline at end of file +URLs** in the Auth0 Dashboard, or the logout redirect will be rejected. + +## Forcing an Experiment Center variant + +> [!NOTE] +> Experiment Center support via SDKs is currently in Early Access. To request access to this feature, contact your Auth0 representative. + +[Experiment Center](https://auth0.com/docs/customize/experiment-center/overview) lets you A/B test your login flow. Auth0 assigns each user to a variant server-side. When you need to force a specific variant - for testing or to apply a decision from a feature-flag tool. + +Pass `experiment_id` and `variation_id` via `authorizationParams` to force a user into a specific [Experiment Center](https://auth0.com/docs/customize/experiment-center/overview) variation for the login request, bypassing the server-side deterministic assignment. Both IDs are obtained from your Auth0 Dashboard or the Management API. + +You can also pass an optional `segment_id` alongside them. Set these in +`authorizationParams` and the SDK forwards them straight through to the +`/authorize` request: + +```jsx +import { useAuth0 } from '@auth0/auth0-react'; + +function LoginButton() { + const { loginWithRedirect } = useAuth0(); + + return ( + + ); +} +``` + +Pass these **per call** on `loginWithRedirect` (or `loginWithPopup`) rather than +on `Auth0Provider`'s `authorizationParams`, so the override does not bleed into +silent `prompt=none` token-renewal calls, where Experiment Center does not run. + +- **Testing:** drive the IDs from test automation (e.g. Cypress/Playwright) + using values from a CI environment variable against a staging tenant. Do not + hard-code them in shipped app code. +- **Production:** pass the variant decision from a feature-flag tool + (e.g. LaunchDarkly) that has already decided which variant the user should + see for this request. + +The override applies only to this request; the next login without these params +reverts to normal server-side assignment. \ No newline at end of file diff --git a/README.md b/README.md index 09b3a7c5..fec42595 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,23 @@ function App() { export default App; ``` +### Forcing an Experiment Center variant + +To override the [Experiment Center](https://auth0.com/docs/customize/experiment-center) variant Auth0 assigns for a login, pass `experiment_id`, `variation_id`, and the optional `segment_id` per call in `authorizationParams`. The SDK forwards them to the `/authorize` request: + +```jsx +loginWithRedirect({ + authorizationParams: { + experiment_id: '', + variation_id: '', + // segment_id is optional + segment_id: '', + }, +}); +``` + +Pass these per call (not on `Auth0Provider`) so the override does not affect silent token-renewal calls. See [EXAMPLES.md](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md#forcing-an-experiment-center-variant) for details. + For more code samples on how to integrate **auth0-react** SDK in your **React** application, have a look at our [examples](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md). ## API reference diff --git a/__tests__/auth-provider.test.tsx b/__tests__/auth-provider.test.tsx index d6775f63..fd7a4c2a 100644 --- a/__tests__/auth-provider.test.tsx +++ b/__tests__/auth-provider.test.tsx @@ -491,6 +491,63 @@ describe('Auth0Provider', () => { }); }); + it('should forward Experiment Center params through loginWithRedirect', async () => { + const wrapper = createWrapper(); + const { result } = renderHook( + () => useContext(Auth0Context), + { wrapper } + ); + await waitFor(() => { + expect(result.current.loginWithRedirect).toBeInstanceOf(Function); + }); + await result.current.loginWithRedirect({ + authorizationParams: { + redirect_uri: '__redirect_uri__', + experiment_id: '__experiment_id__', + variation_id: '__variation_id__', + segment_id: '__segment_id__', + }, + }); + expect(clientMock.loginWithRedirect).toHaveBeenCalledWith({ + authorizationParams: { + redirect_uri: '__redirect_uri__', + experiment_id: '__experiment_id__', + variation_id: '__variation_id__', + segment_id: '__segment_id__', + }, + }); + }); + + it('should forward Experiment Center params through loginWithRedirect when segment_id is omitted', async () => { + const wrapper = createWrapper(); + const { result } = renderHook( + () => useContext(Auth0Context), + { wrapper } + ); + await waitFor(() => { + expect(result.current.loginWithRedirect).toBeInstanceOf(Function); + }); + await result.current.loginWithRedirect({ + authorizationParams: { + experiment_id: '__experiment_id__', + variation_id: '__variation_id__', + }, + }); + expect(clientMock.loginWithRedirect).toHaveBeenCalledWith({ + authorizationParams: { + experiment_id: '__experiment_id__', + variation_id: '__variation_id__', + }, + }); + expect(clientMock.loginWithRedirect).not.toHaveBeenCalledWith( + expect.objectContaining({ + authorizationParams: expect.objectContaining({ + segment_id: expect.anything(), + }), + }) + ); + }); + it('should provide a login method supporting redirectUri', async () => { const warn = jest.spyOn(console, "warn").mockImplementation(() => undefined); const wrapper = createWrapper(); From e51087498c23f467c0de0724ea3ee69317976af2 Mon Sep 17 00:00:00 2001 From: Siddhi Kotak Date: Thu, 24 Sep 2026 13:54:42 +0530 Subject: [PATCH 2/9] feat: add loginWithPopup example in readme and example.md --- EXAMPLES.md | 42 +++++++++++++++++++++++--------- README.md | 12 +++++++++ __tests__/auth-provider.test.tsx | 7 ------ 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/EXAMPLES.md b/EXAMPLES.md index 5f35ab8c..35e5a20f 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -2118,15 +2118,9 @@ URLs** in the Auth0 Dashboard, or the logout redirect will be rejected. ## Forcing an Experiment Center variant > [!NOTE] -> Experiment Center support via SDKs is currently in Early Access. To request access to this feature, contact your Auth0 representative. +> [Experiment Center](https://auth0.com/docs/customize/experiment-center/overview) support via SDKs is currently in Early Access. To request access to this feature, contact your Auth0 representative. -[Experiment Center](https://auth0.com/docs/customize/experiment-center/overview) lets you A/B test your login flow. Auth0 assigns each user to a variant server-side. When you need to force a specific variant - for testing or to apply a decision from a feature-flag tool. - -Pass `experiment_id` and `variation_id` via `authorizationParams` to force a user into a specific [Experiment Center](https://auth0.com/docs/customize/experiment-center/overview) variation for the login request, bypassing the server-side deterministic assignment. Both IDs are obtained from your Auth0 Dashboard or the Management API. - -You can also pass an optional `segment_id` alongside them. Set these in -`authorizationParams` and the SDK forwards them straight through to the -`/authorize` request: +> Experiment Center lets you A/B test your login flow. To force a specific variant - for testing or to apply a decision from a feature-flag service - pass `experiment_id` and `variation_id` via `authorizationParams`. Auth0 will use them instead of its server-side deterministic assignment. Both IDs are obtained from your Auth0 Dashboard or the Management API. You can also pass the optional `segment_id` when the experiment uses segment targeting. ```jsx import { useAuth0 } from '@auth0/auth0-react'; @@ -2153,9 +2147,35 @@ function LoginButton() { } ``` -Pass these **per call** on `loginWithRedirect` (or `loginWithPopup`) rather than -on `Auth0Provider`'s `authorizationParams`, so the override does not bleed into -silent `prompt=none` token-renewal calls, where Experiment Center does not run. +The same params work with `loginWithPopup`: + +```jsx +import { useAuth0 } from '@auth0/auth0-react'; + +function LoginButton() { + const { loginWithPopup } = useAuth0(); + + return ( + + ); +} +``` + +> [!IMPORTANT] +> Pass these parameters per call on `loginWithRedirect` (or `loginWithPopup`), not on `Auth0Provider`'s `authorizationParams`. Setting them on the provider pins every login including silent `prompt=none` token-renewal calls - to the same variation, which cancels the A/B test. Experiment Center does not run on silent checks. - **Testing:** drive the IDs from test automation (e.g. Cypress/Playwright) using values from a CI environment variable against a staging tenant. Do not diff --git a/README.md b/README.md index fec42595..5cdb071e 100644 --- a/README.md +++ b/README.md @@ -156,6 +156,18 @@ loginWithRedirect({ }); ``` +```jsx +loginWithPopup({ + authorizationParams: { + experiment_id: '', + variation_id: '', + // segment_id is optional + segment_id: '', + }, +}); +``` + + Pass these per call (not on `Auth0Provider`) so the override does not affect silent token-renewal calls. See [EXAMPLES.md](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md#forcing-an-experiment-center-variant) for details. For more code samples on how to integrate **auth0-react** SDK in your **React** application, have a look at our [examples](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md). diff --git a/__tests__/auth-provider.test.tsx b/__tests__/auth-provider.test.tsx index fd7a4c2a..c1909324 100644 --- a/__tests__/auth-provider.test.tsx +++ b/__tests__/auth-provider.test.tsx @@ -539,13 +539,6 @@ describe('Auth0Provider', () => { variation_id: '__variation_id__', }, }); - expect(clientMock.loginWithRedirect).not.toHaveBeenCalledWith( - expect.objectContaining({ - authorizationParams: expect.objectContaining({ - segment_id: expect.anything(), - }), - }) - ); }); it('should provide a login method supporting redirectUri', async () => { From bea300cbd1cd24edf26fd191a65bf17447a04e45 Mon Sep 17 00:00:00 2001 From: Siddhi Kotak Date: Thu, 24 Sep 2026 14:01:09 +0530 Subject: [PATCH 3/9] feat: added unit tests for loginWithPopup --- __tests__/auth-provider.test.tsx | 54 ++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/__tests__/auth-provider.test.tsx b/__tests__/auth-provider.test.tsx index c1909324..74e63e34 100644 --- a/__tests__/auth-provider.test.tsx +++ b/__tests__/auth-provider.test.tsx @@ -541,6 +541,60 @@ describe('Auth0Provider', () => { }); }); + it('should forward Experiment Center params through loginWithPopup', async () => { + const wrapper = createWrapper(); + const { result } = renderHook( + () => useContext(Auth0Context), + { wrapper } + ); + await waitFor(() => { + expect(result.current.loginWithPopup).toBeInstanceOf(Function); + }); + await result.current.loginWithPopup({ + authorizationParams: { + experiment_id: '__experiment_id__', + variation_id: '__variation_id__', + segment_id: '__segment_id__', + }, + }); + expect(clientMock.loginWithPopup).toHaveBeenCalledWith( + { + authorizationParams: { + experiment_id: '__experiment_id__', + variation_id: '__variation_id__', + segment_id: '__segment_id__', + }, + }, + undefined + ); + }); + + it('should forward Experiment Center params through loginWithPopup when segment_id is omitted', async () => { + const wrapper = createWrapper(); + const { result } = renderHook( + () => useContext(Auth0Context), + { wrapper } + ); + await waitFor(() => { + expect(result.current.loginWithPopup).toBeInstanceOf(Function); + }); + await result.current.loginWithPopup({ + authorizationParams: { + experiment_id: '__experiment_id__', + variation_id: '__variation_id__', + }, + }); + expect(clientMock.loginWithPopup).toHaveBeenCalledWith( + { + authorizationParams: { + experiment_id: '__experiment_id__', + variation_id: '__variation_id__', + }, + }, + undefined + ); + }); + it('should provide a login method supporting redirectUri', async () => { const warn = jest.spyOn(console, "warn").mockImplementation(() => undefined); const wrapper = createWrapper(); From 6bd1fa2903fa16a493160a412827558c30ade3aa Mon Sep 17 00:00:00 2001 From: Siddhi Kotak Date: Thu, 24 Sep 2026 19:16:58 +0530 Subject: [PATCH 4/9] fix: formatting issues --- EXAMPLES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EXAMPLES.md b/EXAMPLES.md index 35e5a20f..4c167840 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -2120,7 +2120,7 @@ URLs** in the Auth0 Dashboard, or the logout redirect will be rejected. > [!NOTE] > [Experiment Center](https://auth0.com/docs/customize/experiment-center/overview) support via SDKs is currently in Early Access. To request access to this feature, contact your Auth0 representative. -> Experiment Center lets you A/B test your login flow. To force a specific variant - for testing or to apply a decision from a feature-flag service - pass `experiment_id` and `variation_id` via `authorizationParams`. Auth0 will use them instead of its server-side deterministic assignment. Both IDs are obtained from your Auth0 Dashboard or the Management API. You can also pass the optional `segment_id` when the experiment uses segment targeting. +Experiment Center lets you A/B test your login flow. To force a specific variant - for testing or to apply a decision from a feature-flag service - pass `experiment_id` and `variation_id` via `authorizationParams`. Auth0 will use them instead of its server-side deterministic assignment. Both IDs are obtained from your Auth0 Dashboard or the Management API. You can also pass the optional `segment_id` when the experiment uses segment targeting. ```jsx import { useAuth0 } from '@auth0/auth0-react'; @@ -2185,4 +2185,4 @@ function LoginButton() { see for this request. The override applies only to this request; the next login without these params -reverts to normal server-side assignment. \ No newline at end of file +reverts to normal server-side assignment. From b666d58ab136a336149710452378088f1744c978 Mon Sep 17 00:00:00 2001 From: Siddhi Kotak Date: Thu, 24 Sep 2026 20:09:11 +0530 Subject: [PATCH 5/9] fix: formatting issue --- EXAMPLES.md | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/EXAMPLES.md b/EXAMPLES.md index 4c167840..9850cba2 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -2177,12 +2177,7 @@ function LoginButton() { > [!IMPORTANT] > Pass these parameters per call on `loginWithRedirect` (or `loginWithPopup`), not on `Auth0Provider`'s `authorizationParams`. Setting them on the provider pins every login including silent `prompt=none` token-renewal calls - to the same variation, which cancels the A/B test. Experiment Center does not run on silent checks. -- **Testing:** drive the IDs from test automation (e.g. Cypress/Playwright) - using values from a CI environment variable against a staging tenant. Do not - hard-code them in shipped app code. -- **Production:** pass the variant decision from a feature-flag tool - (e.g. LaunchDarkly) that has already decided which variant the user should - see for this request. - -The override applies only to this request; the next login without these params -reverts to normal server-side assignment. +- **Testing:** drive the IDs from test automation (e.g. Cypress/Playwright) using values from a CI environment variable against a staging tenant. Do not hard-code them in shipped app code. +- **Production:** pass the variant decision from a feature-flag tool (e.g. LaunchDarkly) that has already decided which variant the user should see for this request. + +The override applies only to this request; the next login without these params reverts to normal server-side assignment. From 37f01fcf04149d1773f6400e844660f4bd4b7fdc Mon Sep 17 00:00:00 2001 From: Siddhi Kotak Date: Fri, 25 Sep 2026 17:17:30 +0530 Subject: [PATCH 6/9] fix: added experiment center example link in README file --- README.md | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/README.md b/README.md index 5cdb071e..0a220878 100644 --- a/README.md +++ b/README.md @@ -141,32 +141,7 @@ function App() { export default App; ``` -### Forcing an Experiment Center variant - -To override the [Experiment Center](https://auth0.com/docs/customize/experiment-center) variant Auth0 assigns for a login, pass `experiment_id`, `variation_id`, and the optional `segment_id` per call in `authorizationParams`. The SDK forwards them to the `/authorize` request: - -```jsx -loginWithRedirect({ - authorizationParams: { - experiment_id: '', - variation_id: '', - // segment_id is optional - segment_id: '', - }, -}); -``` - -```jsx -loginWithPopup({ - authorizationParams: { - experiment_id: '', - variation_id: '', - // segment_id is optional - segment_id: '', - }, -}); -``` - +You can also force a specific [Experiment Center](https://auth0.com/docs/customize/experiment-center) variant per login by passing `experiment_id`, `variation_id`, and the optional `segment_id` in `authorizationParams` - see the [Experiment Center example](https://github.com/auth0/auth0-angular/tree/main/EXAMPLES.md#experiment-center). Pass these per call (not on `Auth0Provider`) so the override does not affect silent token-renewal calls. See [EXAMPLES.md](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md#forcing-an-experiment-center-variant) for details. From 78eebbd53034bf922b0969d9efa5baeb8c5c7f82 Mon Sep 17 00:00:00 2001 From: Siddhi Kotak Date: Fri, 25 Sep 2026 18:06:39 +0530 Subject: [PATCH 7/9] fix: experiment center link in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a220878..e46e4716 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ function App() { export default App; ``` -You can also force a specific [Experiment Center](https://auth0.com/docs/customize/experiment-center) variant per login by passing `experiment_id`, `variation_id`, and the optional `segment_id` in `authorizationParams` - see the [Experiment Center example](https://github.com/auth0/auth0-angular/tree/main/EXAMPLES.md#experiment-center). +You can also force a specific [Experiment Center](https://auth0.com/docs/customize/experiment-center) variant per login by passing `experiment_id`, `variation_id`, and the optional `segment_id` in `authorizationParams` - see the [Experiment Center example](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md#forcing-an-experiment-center-variant). Pass these per call (not on `Auth0Provider`) so the override does not affect silent token-renewal calls. See [EXAMPLES.md](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md#forcing-an-experiment-center-variant) for details. From bad35329d46731167333d2a85eb164975b2d9d37 Mon Sep 17 00:00:00 2001 From: Siddhi Kotak Date: Fri, 25 Sep 2026 18:17:23 +0530 Subject: [PATCH 8/9] fix: readme.md file for experiment center fearure --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index e46e4716..aa1bfc7b 100644 --- a/README.md +++ b/README.md @@ -143,8 +143,6 @@ export default App; You can also force a specific [Experiment Center](https://auth0.com/docs/customize/experiment-center) variant per login by passing `experiment_id`, `variation_id`, and the optional `segment_id` in `authorizationParams` - see the [Experiment Center example](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md#forcing-an-experiment-center-variant). -Pass these per call (not on `Auth0Provider`) so the override does not affect silent token-renewal calls. See [EXAMPLES.md](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md#forcing-an-experiment-center-variant) for details. - For more code samples on how to integrate **auth0-react** SDK in your **React** application, have a look at our [examples](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md). ## API reference From 7e966295041027fa68fe2b95cd684ae4f61d4c90 Mon Sep 17 00:00:00 2001 From: Siddhi Kotak Date: Mon, 28 Sep 2026 13:07:50 +0530 Subject: [PATCH 9/9] feat: add experiment center section in README --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aa1bfc7b..091671aa 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,12 @@ function App() { export default App; ``` -You can also force a specific [Experiment Center](https://auth0.com/docs/customize/experiment-center) variant per login by passing `experiment_id`, `variation_id`, and the optional `segment_id` in `authorizationParams` - see the [Experiment Center example](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md#forcing-an-experiment-center-variant). +### Experiment Center + +> [!NOTE] +> [Experiment Center](https://auth0.com/docs/customize/experiment-center) support via SDKs is currently in Early Access. To request access to this feature, contact your Auth0 representative. + +You can also force a specific Experiment Center variant per login by passing `experiment_id`, `variation_id`, and the optional `segment_id` in `authorizationParams` - see the [Experiment Center example](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md#forcing-an-experiment-center-variant). For more code samples on how to integrate **auth0-react** SDK in your **React** application, have a look at our [examples](https://github.com/auth0/auth0-react/blob/main/EXAMPLES.md).