diff --git a/packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java b/packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java index 16337a0ba9..4ca8585cd3 100644 --- a/packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java +++ b/packages/auth/android/src/main/java/io/invertase/firebase/auth/ReactNativeFirebaseAuthModule.java @@ -402,6 +402,20 @@ private void createUserWithEmailAndPassword( }); } + /** + * isSignInWithEmailLink + * + * @param email + * @param promise + */ + @ReactMethod + public void isSignInWithEmailLink(String appName, String emailLink, final Promise promise) { + Log.d(TAG, "isSignInWithEmailLink"); + FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); + FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp); + promise.resolve(firebaseAuth.isSignInWithEmailLink(emailLink)); + } + /** * signInWithEmailAndPassword * diff --git a/packages/auth/e2e/emailLink.e2e.js b/packages/auth/e2e/emailLink.e2e.js index fa0f1b12f4..8000711d35 100644 --- a/packages/auth/e2e/emailLink.e2e.js +++ b/packages/auth/e2e/emailLink.e2e.js @@ -81,11 +81,18 @@ describe('auth() -> emailLink Provider', function () { const emailLink3 = 'https://www.example.com/action?mode=signIn'; const emailLink4 = 'https://x59dg.app.goo.gl/?link=https://rnfirebase-b9ad4.firebaseapp.com/__/auth/action?apiKey%3Dfoo%26mode%3DsignIn%26oobCode%3Dbar'; - - should.equal(true, isSignInWithEmailLink(auth, emailLink1)); - should.equal(false, isSignInWithEmailLink(auth, emailLink2)); - should.equal(false, isSignInWithEmailLink(auth, emailLink3)); - should.equal(true, isSignInWithEmailLink(auth, emailLink4)); + const emailLink5 = 'https://www.example.com/action?mode=signIn&oobCode=oobCode&apiKey=foo'; + + // ios does not require apiKey, but android and web/other do + if (!Platform.ios) { + should.equal(false, await isSignInWithEmailLink(auth, emailLink1)); + } else { + should.equal(true, await isSignInWithEmailLink(auth, emailLink1)); + } + should.equal(false, await isSignInWithEmailLink(auth, emailLink2)); + should.equal(false, await isSignInWithEmailLink(auth, emailLink3)); + should.equal(true, await isSignInWithEmailLink(auth, emailLink4)); + should.equal(true, await isSignInWithEmailLink(auth, emailLink5)); }); }); diff --git a/packages/auth/ios/RNFBAuth/RNFBAuthModule.m b/packages/auth/ios/RNFBAuth/RNFBAuthModule.m index 0c9c2411e0..2c9232e423 100644 --- a/packages/auth/ios/RNFBAuth/RNFBAuthModule.m +++ b/packages/auth/ios/RNFBAuth/RNFBAuthModule.m @@ -254,6 +254,15 @@ - (void)invalidate { }]; } +RCT_EXPORT_METHOD(isSignInWithEmailLink + : (FIRApp *)firebaseApp + : (NSString *)emailLink + : (RCTPromiseResolveBlock)resolve + : (RCTPromiseRejectBlock)reject) { + resolve( + @([RCTConvert BOOL:@([[FIRAuth authWithApp:firebaseApp] isSignInWithEmailLink:emailLink])])); +} + RCT_EXPORT_METHOD(signInWithEmailLink : (FIRApp *)firebaseApp : (NSString *)email diff --git a/packages/auth/lib/index.d.ts b/packages/auth/lib/index.d.ts index 250b2f4c1d..ca34c640e0 100644 --- a/packages/auth/lib/index.d.ts +++ b/packages/auth/lib/index.d.ts @@ -2013,12 +2013,12 @@ export namespace FirebaseAuthTypes { * #### Example * * ```js - * const signedInWithLink = firebase.auth().isSignInWithEmailLink(link); + * const signedInWithLink = await firebase.auth().isSignInWithEmailLink(link); * ``` * * @param emailLink The email link to check whether the user signed in with it. */ - isSignInWithEmailLink(emailLink: string): boolean; + isSignInWithEmailLink(emailLink: string): Promise; /** * Signs the user in with an email link. diff --git a/packages/auth/lib/index.js b/packages/auth/lib/index.js index d5a446cc6f..1d7751ca96 100644 --- a/packages/auth/lib/index.js +++ b/packages/auth/lib/index.js @@ -361,11 +361,7 @@ class FirebaseAuthModule extends FirebaseModule { } isSignInWithEmailLink(emailLink) { - return ( - typeof emailLink === 'string' && - (emailLink.includes('mode=signIn') || emailLink.includes('mode%3DsignIn')) && - (emailLink.includes('oobCode=') || emailLink.includes('oobCode%3D')) - ); + return this.native.isSignInWithEmailLink(emailLink); } signInWithEmailLink(email, emailLink) { diff --git a/packages/auth/lib/modular/index.d.ts b/packages/auth/lib/modular/index.d.ts index 1625afce27..d75d52e7b8 100644 --- a/packages/auth/lib/modular/index.d.ts +++ b/packages/auth/lib/modular/index.d.ts @@ -169,9 +169,9 @@ export function initializeRecaptchaConfig(auth: Auth): Promise; * * @param auth - The Auth instance. * @param emailLink - The email link to check. - * @returns True if the link is a sign-in with email link. + * @returns A promise that resolves if the link is a sign-in with email link. */ -export function isSignInWithEmailLink(auth: Auth, emailLink: string): boolean; +export function isSignInWithEmailLink(auth: Auth, emailLink: string): Promise; /** * Adds an observer for changes to the user's sign-in state. diff --git a/packages/auth/lib/modular/index.js b/packages/auth/lib/modular/index.js index 959939f462..ff53849f8e 100644 --- a/packages/auth/lib/modular/index.js +++ b/packages/auth/lib/modular/index.js @@ -165,7 +165,7 @@ export async function getRedirectResult(auth, resolver) { * Checks if an incoming link is a sign-in with email link suitable for signInWithEmailLink(). * @param {Auth} auth - The Auth instance. * @param {string} emailLink - The email link to check. - * @returns {boolean} + * @returns {Promise} */ export function isSignInWithEmailLink(auth, emailLink) { return auth.isSignInWithEmailLink(emailLink); diff --git a/packages/auth/lib/web/RNFBAuthModule.js b/packages/auth/lib/web/RNFBAuthModule.js index bb8b8acb15..ab8bc3b423 100644 --- a/packages/auth/lib/web/RNFBAuthModule.js +++ b/packages/auth/lib/web/RNFBAuthModule.js @@ -10,6 +10,7 @@ import { multiFactor, createUserWithEmailAndPassword, signInWithEmailAndPassword, + isSignInWithEmailLink, signInWithEmailLink, signInWithCustomToken, sendPasswordResetEmail, @@ -449,6 +450,19 @@ export default { }); }, + /** + * Check if a sign in with email link is valid + * @param {string} appName - The name of the app to get the auth instance for. + * @param {string} emailLink - The email link to sign in with. + * @returns {Promise} - Whether the link is a valid sign in with email link. + */ + async isSignInWithEmailLink(appName, emailLink) { + return guard(async () => { + const auth = getCachedAuthInstance(appName); + return await isSignInWithEmailLink(auth, emailLink); + }); + }, + /** * Sign in with email link. * @param {string} appName - The name of the app to get the auth instance for.