Checklist
Description
Description
When using customScheme: 'https' on iOS, the Linking event listener registered in NativeWebAuthProvider.authorize() forwards all incoming URLs to resumeWebAuth(), including universal links that are not Auth0 callbacks. This causes login to fail with "Invalid callback URL".
Environment
react-native-auth0: 5.4.0
- iOS 15.8.7 and 26.4 (reproduced on both)
- Expo (React Native)
Setup
- Auth0 domain:
auth.example.com
- App has universal link support for
app.example.com (applinks:app.example.com in associated domains)
- Auth configured with
customScheme: 'https'
Steps to reproduce
- Open the app via a universal link (e.g.
https://app.example.com/some-path)
- Tap login, which calls
authorize() with customScheme: 'https'
ASWebAuthenticationSession opens
Expected: Auth flow completes normally
Actual: Login fails with Auth0.WebAuthError: Invalid callback URL: https://app.example.com/some-path
This also reproduces without a universal link open. If Auth0's Universal Login navigates to the app's initiate_login_uri (e.g. https://app.example.com/main?iss=https://auth.example.com/), iOS delivers it as a universal link, the Linking listener catches it, and resumeWebAuth() rejects it.
Root cause
In [NativeWebAuthProvider.js](https://github.com/auth0/react-native-auth0/blob/master/src/platforms/native/adapters/NativeWebAuthProvider.ts#L34-L38), the Linking listener forwards every URL to resumeWebAuth() without checking whether the URL is actually on the Auth0 domain:
linkSubscription = Linking.addEventListener('url', async event => {
linkSubscription?.remove();
await this.bridge.resumeWebAuth(event.url);
});
When the app has universal links on a domain other than the Auth0 domain, iOS can deliver those URLs to the app during the auth flow. The listener treats them as auth callbacks, resumeWebAuth() fails validation, and the error propagates to the authorize() promise.
Workaround
We're patching the listener to filter by domain:
linkSubscription = Linking.addEventListener('url', async event => {
try {
const url = new URL(event.url);
if (url.hostname !== this.domain) return;
} catch {
return;
}
linkSubscription?.remove();
await this.bridge.resumeWebAuth(event.url);
});
Suggested fix
The SDK should check that the incoming URL's hostname matches this.domain before forwarding to resumeWebAuth(). This would prevent universal links on other domains from being incorrectly processed as auth callbacks.
Reproduction
- Open the app via a universal link (e.g.
https://app.example.com/some-path)
- Tap login, which calls
authorize() with customScheme: 'https'
ASWebAuthenticationSession opens
Expected: Auth flow completes normally
Actual: Login fails with Auth0.WebAuthError: Invalid callback URL: https://app.example.com/some-path
This also reproduces without a universal link open. If Auth0's Universal Login navigates to the app's initiate_login_uri (e.g. https://app.example.com/main?iss=https://auth.example.com/), iOS delivers it as a universal link, the Linking listener catches it, and resumeWebAuth() rejects it.
Additional context
No response
react-native-auth0 version
5.4.0
React Native version
0.81.4
Expo version
54.0.10
Platform
iOS
Platform version(s)
15.8.7 and 26.4 (reproduced on both)
Checklist
Description
Description
When using
customScheme: 'https'on iOS, theLinkingevent listener registered inNativeWebAuthProvider.authorize()forwards all incoming URLs toresumeWebAuth(), including universal links that are not Auth0 callbacks. This causes login to fail with "Invalid callback URL".Environment
react-native-auth0: 5.4.0Setup
auth.example.comapp.example.com(applinks:app.example.comin associated domains)customScheme: 'https'Steps to reproduce
https://app.example.com/some-path)authorize()withcustomScheme: 'https'ASWebAuthenticationSessionopensExpected: Auth flow completes normally
Actual: Login fails with
Auth0.WebAuthError: Invalid callback URL: https://app.example.com/some-pathThis also reproduces without a universal link open. If Auth0's Universal Login navigates to the app's
initiate_login_uri(e.g.https://app.example.com/main?iss=https://auth.example.com/), iOS delivers it as a universal link, the Linking listener catches it, andresumeWebAuth()rejects it.Root cause
In
[NativeWebAuthProvider.js](https://github.com/auth0/react-native-auth0/blob/master/src/platforms/native/adapters/NativeWebAuthProvider.ts#L34-L38), the Linking listener forwards every URL toresumeWebAuth()without checking whether the URL is actually on the Auth0 domain:When the app has universal links on a domain other than the Auth0 domain, iOS can deliver those URLs to the app during the auth flow. The listener treats them as auth callbacks,
resumeWebAuth()fails validation, and the error propagates to theauthorize()promise.Workaround
We're patching the listener to filter by domain:
Suggested fix
The SDK should check that the incoming URL's hostname matches
this.domainbefore forwarding toresumeWebAuth(). This would prevent universal links on other domains from being incorrectly processed as auth callbacks.Reproduction
https://app.example.com/some-path)authorize()withcustomScheme: 'https'ASWebAuthenticationSessionopensExpected: Auth flow completes normally
Actual: Login fails with
Auth0.WebAuthError: Invalid callback URL: https://app.example.com/some-pathThis also reproduces without a universal link open. If Auth0's Universal Login navigates to the app's
initiate_login_uri(e.g.https://app.example.com/main?iss=https://auth.example.com/), iOS delivers it as a universal link, the Linking listener catches it, andresumeWebAuth()rejects it.Additional context
No response
react-native-auth0 version
5.4.0
React Native version
0.81.4
Expo version
54.0.10
Platform
iOS
Platform version(s)
15.8.7 and 26.4 (reproduced on both)