Firebase Magic Link not complete in Android App - react-native

I have a React Native Project using Expo Managed Workflow.
The App is built as a expo-dev-client.
I use Firebase Native SDK to authenticate via sendSignInLinkToEmail()
I managed to request the magic link for login. It arrives and when I click it on my android device, the App comes to focus and I am even able to listen to the dynamic link when it comes in.
Problem is it does not validate with isSignInWithEmailLink() because the link I get is only the continueURL parameter of the original link in the Email.
I really don't know where the link is being cut off but I need the complete link from the Email to use signInWithEmailLink() which obviously doesn't work.
When I manually insert the link from the email into signInWithEmailLink() everything works as expected.
I really hope someone has experienced this issue and can help me out!

My Bad. Apparently I was using a Dynamic Link from firebase as I did not have action codes set correct as in:
const actionCodeSettings = {
// URL you want to redirect back to. The domain (www.example.com) for this
// URL must be in the authorized domains list in the Firebase Console.
url: 'https://www.example.com/finishSignUp?cartId=1234',
// This must be true.
handleCodeInApp: true,
iOS: {
bundleId: 'com.example.ios'
},
android: {
packageName: 'com.example.android',
installApp: true,
minimumVersion: '12'
},
dynamicLinkDomain: 'example.page.link'
};

Related

Firebase functions auth.generateEmailVerificationLink() generating link with wrong apiKey

I have a Firebase functions project with dev and prod versions. There I'm using auth.generateEmailVerificationLink() to send email verification for a newly created user. Everything works well except in prod environment (testing locally or hosted) the apiKey in the link generated by auth.generateEmailVerificationLink() is not same as Firebase's default apiKey. And clicking that link I get the page with error code:
Try verifying your email again
Your request to verify your email has expired or the link has already been used
Note that when I get the link with the wrong apiKey, if I change it to the right apiKey. the verification works. So it seems the whole problem is related to the wrong apiKey in generated email verification link.
Also to note that the wrong apiKey is not random key but used in project front end for Google Maps apis.
The code itself is simple. (I'm leaving out code which creates user etc as those parts all work perfectly)
-Initializing Admin SDK:
import { initializeApp } from 'firebase-admin/app';
import { getAuth } from 'firebase-admin/auth';
initializeApp();
const auth = getAuth();
export { auth };
-Generating email verification email
const sendEmail = async () => {
const actionCodeSettings = {
// This url is working correctly, it is the same as in Firebase console
// and when changing the wrong apiKey to correct redirecting works correctly
url: process.env.DOMAIN as string,
};
await auth
.generateEmailVerificationLink(email, actionCodeSettings) // email is the email of newly created user
.then((link) => {
// generate email message with link
// generate mailOptions
// use transporter to send email
});
};
Thank you for any help
EDIT
I tested deleting that "wrong" apiKey from GCP credentials page and replaced it with another. Then running the function locally everything worked normally but the "wrong" is still in the verification email link even tho it doesn't exist anymore.
Firebase strongly recommends that if Admin SDK is used in Cloud Functions, among others, initializing the app should be done without parameters.
https://firebase.google.com/docs/admin/setup#initialize-without-parameters
For me it seems something is for some reason pulling that "wrong" and now even deleted apiKey from somewhere to usage.
I solved this by noticing that, unlike in dev project, Web Api Key (Project Settings>General) is different than Web App's firebaseConfig apiKey.
So I added correct permission to this Web Api Key (Identity Toolkit API is required for email verification email) found in GCP credentials and now the cloud function sends email verification emails with correct and working apiKey.

What is the RedirectURL in react-native-app-auth - and how do I get back to my app?

I'm a noob in the world of React-Native development and am trying to work out how to configure FormidableLabs' react-native-app-auth plugin so that a user of our app can sign in to our Identity Server 4 implementation and then return to the app.
I can get to the sign-in form easily enough - but after signing in it goes to another Identity Server page in the browser rather than back to the app. I assume this is because of a wrong configuration, but I've searched the net far and wide for an answer that actually explains what the redirectUrl should actually point to - in all the examples it just points to io.identityserver.demo:/oauthredirect. Is it possible to redirect back to an app?
What I've also noticed is that the original request to the login page does not pass it a ReturnUrl - that parameter is null.
I feel I'm missing something obvious here, but I cannot think what it is.
Here's the relevant code from the app:
import {authorize} from 'react-native-app-auth';
...
const config = {
issuer: 'http://10.0.2.2:5000',
clientId: 'MyApp',
redirectUrl: '?? what goes here ??',
scopes: ['openid', 'profile', 'offline_access'],
serviceConfiguration: {
authorizationEndpoint: `http://10.0.2.2:5000/Account/Login`,
tokenEndpoint: `http://10.0.2.2:5000/connect/token`
}
}
const result = await authorize(config);
The Identity Server is running on port 5000 (in localhost on my pc).
Can anyone point out what I'm doing wrong?
Thanks in advance!
You have 2 main choices for a redirect URI and the first option is simpler but a little less secure:
Private URI Scheme Based: com.mycompany.myapp:/callback
Claimed HTTPS Scheme Based: https://mobile.mycompany.com/callback
In order for the redirect to return to the app you need to register the scheme with the Android / iOS systems.
PRIVATE URI SCHEME
My write ups should enable you to quickly run the standard samples and get Private URI schemes working. You can then set similar Android / iOS settings in your ReactNative app:
Android via AppAuth Sample
iOS via AppAuth Sample
CLAIMED HTTPS SCHEME
This is more effort but my blog also has Android / iOS samples that you can run and read about in case interested.
You are on the right track, once the user has logged into IdentityServer it will redirect back to redirectUrl.
I suggest you to read the docs as it has it explained with example code.

How do I get react-native-inappbrowser-reborn to trigger success upon successful Facebook login

I'm trying to setup a manual flow for Facebook login, as per the docs at: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/
I've got my test Facebook app working as expected, i.e., I can login using a private web browser window fine. The URL I'm using is:
https://facebook.com/v3.3/dialog/oauth?client_id=<app_id>&display=popup&response_type=token&redirect_uri=https://www.facebook.com/connect/login_success.html
Now within my React-Native app, I'm using react-native-inappbrowser-reborn to present a SFAuthenticationSession on iOS. As per their docs (at https://www.npmjs.com/package/react-native-inappbrowser-reborn), I'm doing the following:
const redirectUri = "https://www.facebook.com/connect/login_success.html"
const url = "https://facebook.com/v3.3/dialog/oauth?client_id="+appId+"&display=popup&response_type=token&redirect_uri=https://www.facebook.com/connect/login_success.html"
InAppBrowser.isAvailable()
.then(() => {
InAppBrowser.openAuth(url, redirectUri, {
// iOS Properties
dismissButtonStyle: 'cancel',
// Android Properties
showTitle: false,
enableUrlBarHiding: true,
enableDefaultShare: true,
})
.then((response) => {
// Only gets to this point if user explicitly cancels.
// So this does not trigger upon successful login.
})
// catch handlers follow
Using the above, my app correctly open up an in-app browser and I can login fine using a test user for my test app. Upon successful login though, I don't get redirected back to the .then completion handler. It just stays in the in-app browser view and I see the same message from Facebook that I see when logging in using a web browser. It says something like "Success. Please treat the url the same as you would a password", or something like that.
I may be missing something here, but I thought the purpose of passing redirectUri as an argument to openAuth was so that upon redirection to that URI, the completion handler would be triggered.
Question: How do I redirect back to the completion handler upon login success?
I think that you already have a solution but thought it might be useful for someone else facing this issue. If you don't have a solution so far follow my instructions:
You can't directly redirect back to your application using deep link, since Facebook will not call a link `like myapplicationname://mycustompath´. It's only possible to call links using the https-protocol (https://...).
The solution I'd suggest you to use is to redirect using your own API (Facebook -> Your API -> Deep Link Redirection). You will understand why this is required in the most of the real world applications at the end of the instructions.
Starting from your react-native app call the authorize endpoint of Facebook with a redirection to your application and set the global deeplink of your app as redirect uri.
InAppBrowser.close();
InAppBrowser.openAuth("https://graph.facebook.com/oauth/authorize?client_id=YOURCLIENTID&redirect_uri=https://YOURDOMAIN:PORT/auth/facebook", "{YOURAPPSDEEPLINKNAME}://{SOMEPATHYOUWANTTOEND}")
.then((response) => {
handleAuthorized(response, LOGINTYPE.FACEBOOK);
});
Now after login you'll be redirected to your API with the authorization code token as query parameter (e.g. https://YOURDOMAIN:PORT/auth/facebook?code=AVERYLONGCODESENTBYFACEBOOK)
Using this code token from the query parameter, you make another API Call to get the access_token for the user
{GET}: https://graph.facebook.com/v15.0/oauth/access_token?client_id=YOUR_CLIENT_ID&redirect_uri=https://YOURDOMAIN:PORT/auth/facebook&client_secret=YOUR_CLIENT_SECRET&code=AVERYLONGCODESENTBYFACEBOOK
Facebook's API will send you an answer as JSON with the access_token inside.
You can make another call using the access token of the user, to get the userId and the username
{GET}: https://graph.facebook.com/me?access_token=ACCESS_TOKEN_SENT_BY_FACEBOOK_IN_PREVIOUS_GET_REQUEST.
If you need the e-mail address for the user you have to make another call. Make sure you'd set the permission to read the e-mail address for your app on the developer portal of facebook.
The following request will return you the id, name and the email of the user
{GET}: https://graph.facebook.com/USERIDFROMPREVIOUSREQUEST?fields=id,name,email&access_token=ACCESSTOKEN
I think you want to save all these information to a database and create a session in order to keep the user logged in and therefore all the requests described will be useful for you in a real application.
After doing all the backend stuff, you're ready for the redirection using deep link. To do that, set a meta-tag to redirect the inappbrowser to your application:
<meta http-equiv="refresh" content="0; URL={YOURAPPSDEEPLINKNAME}://{SOMEPATHYOUWANTTOEND}" />

Deep linking with Brnach.IO with sendGrid integration issue as passing params is undefined while opening link from mail using React native

Goal
I am sending email with deep linking implementation with Branch.IO with sendGrid integration. While user click on link my react native app open in phone and redirect me to screen based on query params in url which i have provided during create link in API.
Problem
I am able to open app from link but query params i have provide in link is display as blank. so i am not able to open screen where i want to redirect to user in app.
branch.subscribe(({ params, error, uri }) => {
if (error) {
console.log('Error from Branch: ' + error)
return
}
console.log("params :: ", params);
if(params.reset) {
// Redirect user to reset password screen
console.log("params.reset :: " + params.reset);
Actions.resetpassword({resetToken: params.reset});
} else if(params.verify) {
// Verify signup user
axios.post('http://localhost:3030/authmanagement', {
"action":"verifySignupLong",
"value": params.verify
}).then(response => {
Actions.login({isVerifySuccess: true});
}, error => {
Actions.login();
});
}
});
I have write this code as suggest Branch.IO documentation. In params i have send reset and verify token which i got as blank string.
Information
This code is working without integration with sendGrid in deep linking. But for mailing tracking i used sendGrid. So when i try to email with sendGrid it will create problem.
I have setup Link Branding in SendGrid account and also add CNAME in my domain as given in instruction of sendGrid integration for deep linking.
I have check mailed link in Redirect Detective portal
I have verified link and it will generate valid url with params. please look into below image for more clarification
Jackie from Branch here.
Based on your redirect link, there seems to be an issue with the SendGrid integration. Could you make sure your integration is properly set up by following the instructions here?
For some context, this is what a link should look like within your email template: http://example.com/?foo=bar
When a user clicks your link in the email, Branch processes the link and converts it to something like this:
https://vza3.app.link/3p?%243p=e_xx&%24original_url=http%3A%2F%2Fexample.com%2F%3Ffoo%3Dbar
(Where vza3.app.link is your Branch domain.)
Also, in order for SendGrid to know that the email link should deep-link and open the app, add universal="true" to the HTML, like so:
Link to your app!
If you continue to experience issues with passing deep link data via SendGrid email tracking, please reach out to us directly at integrations#branch.io with your Branch key and the link(s) you're using.

android simple facebook returns "Canceled by user" when publishing post

I have configured android simple facebook library for my app.
It's working properly, but the problem is when using mSimpleFacebook.publish(feed, true, onPublishListener), it always fails with error "canceled by user".
Permission[] permissions = new Permission[] {
Permission.EMAIL,
Permission.PUBLIC_PROFILE,
Permission.PUBLISH_ACTION
};
Any idea what the problem might be?
Thanks