-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(auth, iOS): Expo plugin: skip expo-router for auth URLs #8203
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wow - you are quick with this one!
As mentioned in the related issue, it's a bit delicate because it has to do regex-matching so it will likely break across some future version, but also, I'm not aware of any other way to do this
Given the fragility I think it has to be default-off and have a parameter that turns on this logic (named anything reasonable, like maybe "expoRouterCompatibilityPatch" ... or something)
If it had that, then most people could use the plugin perfectly safely and never break, and those that needed this would be the only ones affected
But in general: thanks so much for posting up a PR to help folks, we rely on community submissions for Expo stuff so it's a huge help here
@mikehardy This is now ready for review, but I'm also hoping to push some documentation updates later, within the next few days. I made the plugin configurable as you suggested, but I also made it so that in the default configuration, it will automatically apply the patch only if "expo-router" is also detected (by looking in the Expo Plugins list). I think this is a happy medium because it addresses the edge cases of projects where it's not applicable, but also makes it easy for the median Expo user. My impression is that the typical Expo user is not comfortable dealing with native code and having even more manual configuration changes to apply and figure out on top of the already complex configuration required for RNFirebase Phone Auth to work. |
CC: @Brandon-Perry |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks amazing, and amazingly robust.
Would be nice to have some docs though I'm not sure exactly where they'd go - perhaps there is an expo section in the auth module already, if so there would work
Left one note you can handle however you see fit about perhaps emitting an info message on successful execution
Default approve at this point, pending whatever you'd like to consider it done, but all okay by me
Cheers!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awesome
The patch-package failure is not related to this PR and is non-blocking here. It was a scheduled deprecation of |
const props = undefined; | ||
const spy = jest | ||
.spyOn(WarningAggregator, 'addWarningIOS') | ||
.mockImplementation(() => undefined); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mikehardy btw for some reason this call to mockImplementation
is required so we don't get get spurious warning messages on jest
's console, yet the one at Line 249 is not required. do you know why?
In particular here's the output when I remove both calls to mockImplementation
:
PASS packages/auth/plugin/__tests__/iosPlugin_openUrlFix.test.ts
● Console
console.warn
» ios: @react-native-firebase/auth: modifying iOS AppDelegate openURL method to ignore firebaseauth reCAPTCHA redirect URLs
77 | } else {
78 | if (configValue === 'default') {
> 79 | WarningAggregator.addWarningIOS(
| ^
80 | '@react-native-firebase/auth',
81 | 'modifying iOS AppDelegate openURL method to ignore firebaseauth reCAPTCHA redirect URLs',
82 | );
at Object.warn (packages/auth/node_modules/@expo/config-plugins/src/utils/warnings.ts:32:11)
at withOpenUrlFixForAppDelegate (packages/auth/plugin/src/ios/openUrlFix.ts:79:27)
at packages/auth/plugin/__tests__/iosPlugin_openUrlFix.test.ts:221:35
at step (packages/auth/node_modules/tslib/tslib.js:195:27)
at Object.next (packages/auth/node_modules/tslib/tslib.js:176:57)
at fulfilled (packages/auth/node_modules/tslib/tslib.js:166:62)
PASS packages/auth/plugin/__tests__/iosPlugin_urlTypes.test.ts
Test Suites: 2 passed, 2 total
Tests: 26 passed, 26 total
Snapshots: 6 passed, 6 total
Time: 2.235 s
Ran all test suites matching /packages\/auth\/plugin\/__tests__\//i.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't mock it, it will print the warning as requested in code, so seeing the warning if you remove the mock seems to me to make sense here, and then...
I wonder if the second one is behaving seemingly-strangely is because the spy is one thing but the mocked implementation is separate - such that the mental model is 2 attempts to spy but only one object that is mocked or not, and if you mock it once it stays mocked. Test of hypothesis would be to reset mocks after test ? Then following my hypothesis the second test should behave as expected if mocked or not (silent if mocked, producing the warn output if not mocked)
const spy = jest.spyOn(WarningAggregator, 'addWarningIOS'); | ||
const spy = jest | ||
.spyOn(WarningAggregator, 'addWarningIOS') | ||
.mockImplementation(() => undefined); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mikehardy related to Line 220, when commenting this line mockImplementation()
, why doesn't jest print a warning message with something like:
» ios: @react-native-firebase/auth: Skipping iOS openURL fix because no 'openURL' method was found
@mikehardy thanks for accepting and merging this PR! Just now I've I left a comment about a lingering mystery that came up when writing the tests |
Description
Summary:
Fix #7258: @react-native-firebase/auth (phone auth) + Expo Router - Redirected to appScheme://firebaseuth/link after resolving recaptcha in ios simulator
Problem:
When using
@react-native-firebase/auth
andexpo-router
in the same application, the phone number login method on iOS fails in some scenarios. In particular, when Firebase uses its ReCAPTCHA verifier (e.g. when running in the iOS simulator), the application ends up navigating away from the login page to a new route/firebaseauth/link
.Cause:
After the user has completed the captcha challenge, the WebView redirects back to the application using an iOS deep link of the form
${googleServiceJson.REVERSED_CLIENT_ID}://firebaseauth/link?${queryParams}
. This inadvertently gets handled by Expo Router, which treats it as a navigation event to a route called/firebaseauth/link
.The root cause of this is a bad interaction between a feature in the Firebase iOS SDK and one in Expo Router:
openURL
call and do its business, but then it also passes along the sameopenURL
call to our application so we can handle it too.AppDelegate
is supposed to returnTRUE
if it can handle the provided URL, andFALSE
if it can't.This interacts badly because it's effectively like Expo Router is hijacking the call that's intended for Firebase Auth. Yet, this situation only occurs because Firebase Auth is forwarding the
openURL
call to our app even after it has already handled it.Solution:
This PR automatically updates the AppDelegate's
openURL
method to not handle URLs for the hostname"firebaseauth"
, under the assumption that it's already being handled by Firebase.@react-native-firebase/auth
Expo plugin calledcaptchaOpenUrlFix
.captchaOpenUrlFix
option is unset or"default"
, automatically applies patch ifexpo-router
plugin is detected in Expo config.TODO:
CC: @mikehardy
Related issues
Fixes #7258, #7953
Release Summary
Checklist
Android
iOS
e2e
tests added or updated inpackages/\*\*/e2e
jest
tests added or updated inpackages/\*\*/__tests__
Test Plan
Comprehensive unit tests have been added: