React Native firebase.auth.RecaptchaVerifier - firebase

How to set the firebase.auth.RecaptchaVerifier in react native using firebase web method to verify phone number and authenticate by receiving OTP on device.Tried with some Methods but not working on mobile.
Code for react native using Web Method:
var appVerifier = firebase.auth.RecaptchaVerifier;
// window.recaptchaVerifier =
// new firebase.auth.RecaptchaVerifier('recaptcha-container');
firebase.auth().signInWithPhoneNumber('+919843191338', appVerifier)
.then(function (confirmationResult) {
Alert.alert(confirmationResult);
window.confirmationResult = confirmationResult;
}).catch(function (error) {
// Error; SMS not sent
// ...
});

You can enable auto verification by enabling SafetyNet API
Check this for detailed information:
https://firebase.google.com/docs/auth/android/phone-auth

Related

Getstream firebase auth react native documentation?

Not sure if anyone has any experience with getstream and react native.
I followed there tutorial to implement getstreams SDK into my existing app and its working great but I'm stuck on tokens. I've successfully set up firebase so when a new user signs up I can see there UID and information over on both firebase auth and getstream but I'm hung up on my frontend getting the user to sign in on the chat with there token. I set up firebase with there extension but still having issues. Works great with dev.tokens but just can't get past this part. Is there any examples out there or better documentation for this? Thank you!
Only documentation I can find.. not specific to react native
https://getstream.io/chat/docs/react/tokens_and_authentication/
This is currently how I initialize my user.. the user token is hard coded in my chat config file.
// useChatClient.js
import { useEffect, useState } from 'react';
import { StreamChat } from 'stream-chat';
import { chatApiKey, chatUserId, chatUserName, chatUserToken } from './chatConfig';
const user = {
id: chatUserId,
name: chatUserName,
};
const chatClient = StreamChat.getInstance(chatApiKey);
export const useChatClient = () => {
const [clientIsReady, setClientIsReady] = useState(false);
useEffect(() => {
const setupClient = async () => {
try {
chatClient.connectUser(user, chatUserToken);
setClientIsReady(true);
// connectUser is an async function. So you can choose to await for it or not depending on your use case (e.g. to show custom loading indicator)
// But in case you need the chat to load from offline storage first then you should render chat components
// immediately after calling `connectUser()`.
// BUT ITS NECESSARY TO CALL connectUser FIRST IN ANY CASE.
} catch (error) {
if (error instanceof Error) {
console.error(`An error occurred while connecting the user: ${error.message}`);
}
}
};
// If the chat client has a value in the field `userID`, a user is already connected
// and we can skip trying to connect the user again.
if (!chatClient.userID) {
setupClient();
}
}, []);
return {
clientIsReady,
};
};
The next step is to request the token from the Firebase cloud function (ext-auth-chat-getStreamUserToken), and then initialise the current user with that token.
There is a guide and video showing how to do this using the Stream Chat Flutter SDK:
https://getstream.io/chat/docs/sdk/flutter/guides/token_generation_with_firebase/
https://youtu.be/Dt_taxX98sg

Next.js SSR with Firebase Auth to authenticate external API using Axios interceptor

My Next.js SSR App will use Firebase Auth to authenticate users. The access token from Firebase Auth will be used to authenticate on an external API.
I have it working in my React App but I am migrating now to Next.js for SSR.
Currently I am struggling with the Axios interceptor... how do I authenticate the user and add the Firebase access token to the request header when on server-side?
I think I need to use cookies?!
High level explanation would sufficient, some code example even better!
edit: I found this article but that would mean I have to add this logic to every single protected route and additionally add the access token to the Axios interceptor for client-side requests, eg. when searching or sending a post request?
export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
try {
const cookies = nookies.get(ctx);
const token = await firebaseAdmin.auth().verifyIdToken(cookies.token);
// the user is authenticated!
const { uid, email } = token;
// FETCH STUFF HERE!! 🚀
return {
props: { message: `Your email is ${email} and your UID is ${uid}.` },
};
} catch (err) {
// either the `token` cookie didn't exist
// or token verification failed
// either way: redirect to the login page
ctx.res.writeHead(302, { Location: '/login' });
ctx.res.end();
// `as never` prevents inference issues
// with InferGetServerSidePropsType.
// The props returned here don't matter because we've
// already redirected the user.
return { props: {} as never };
}
};

FirebaseMessagingError: Invalid registration token provided

I am trying to send push notifications to another iOS device using firebase cloud functions but I receive the following error below when attempting to do so:
'FirebaseMessagingError: Invalid registration token provided. Make sure it matches the registration token the client app receives from registering with FCM.'
This is the registration token I am trying to send to 6e04bb35f06e2d981d5603bbd229eeab5ee5649f6af7b4ecc3894be6ad1574d7 which is the same token I have saved in my realtime database:
Below is my onCreate function:
exports.onMessageCreate = functions.database.ref('/messages/{chatId}/{messageId}').onCreate((snapshot, context) => {
const chatId = context.params.chatId;
const receiverId = chatId.replace(context.auth.uid, '');
const root = snapshot.ref.root;
return admin.database().ref(`/users/${receiverId}/regToken`).once('value').then(tokenSnap => {
var regTokenRef = tokenSnap.val();
const payload = {
notification: {
title: 'title',
body: snapshot.val().text,
}
};
const options = { priority: "high" };
return admin.messaging().sendToDevice(regTokenRef, payload, options).then(function(response){
console.log("Successfully sent message: ", response);
console.log(response.results[0].error);
}).catch(function(error) {
console.log("Error sending message: ", error);
});
});
});
Do you know what may be causing this error? I am not too sure what I need to check here. Is the format wrong here? Does it need to be in quotes? I have looked at other links but they haven't really helped.
I am importing '#react-native-community/push-notification-ios' to generate the token. I think this may be the problem. I was having issues to use the messaging from firebase. Is this the issue?
Please see below the didFinishLaunchingWithOptions method updated in my AppDelegate.m file. Have I placed the below code correctly? When this is added it is causing my app to appear blank when launching the simulator with the FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).? However, when removed my app launches but with still has the FirebaseError.
if ([FIRApp defaultApp] == nil) {
[FIRApp configure];
}
#react-native-community/push-notification-ios is not able to generate an FCM token, only APN token: https://github.com/react-native-push-notification-ios/push-notification-ios/issues/117
If you want to use firebase, you need to generate the token from the messaging package of firebase to have a FCM one.

This operation is not supported in the environment this application is runnung on [duplicate]

I develop a react-native (expo) mobile app and try to sign in with a google account to firebase, but I get an error:
"auth/operation-not-supported-in-this-enviroment. This operation is not supported in the enviroment this application is running on. "location.protocol" must be http, https or chrome-extension and web storage must be enabled"
Code:
loginGoogle() {
var provider = new firebase.auth.GoogleAuthProvider();
provider.addScope('profile');
provider.addScope('email');
firebase.auth().signInWithPopup(provider).then(function(result) {
var token = result.credential.accessToken;
var user = result.user;
return true;
}).catch(function(error) {
alert(error.code + '\n' +
error.message + '\n' +
error.email + '\n' +
error.credential);
return false;
});
}
signInWithPopup is not supported in react-native. You will need to use a third party OAuth library to get the OAuth ID token or access token and then sign in with Firebase:
const cred = firebase.auth.GoogleAuthProvider.credential(googleIdToken, googleAccessToken);
firebase.auth().signInWithCredential(cred)
.then((result) => {
// User signed in.
})
.catch((error) => {
// Error occurred.
});
Firebase does not support signInWithPopup in a React Native environment.
You can view a full list of supported environments on this page.
You can also submit a feature request for extended Firebase support for React Native here.
If you are using expo bare workflow or simple React native cli (or in simple words which contain android and ios folder) then simply use "React Native Firebase" library.
Here is the link https://rnfirebase.io/
But if you are using expo managed workflow(which donot contain android and ios folder ) then you have to follow below steps .
1.setup google developer account
use this guide to setup : https://docs.expo.dev/versions/latest/sdk/google/
Note that: use host.exp.exponent as the package name.
Another problem you may face in this step is generation of hash,which I also faced,the reason for that error is java dev kit(JDK) is not install ,so do install it before proceeding to this step.
2.Setup Firebase account
Simply setup firebase project as you set before, enable google sign in service
but this time the only change is you have to add client ID of your google developer account in (safest client id field) which will popup once you click on edit Google signin in firebase
look like this
3.Coding Part
import * as Google from 'expo-google-app-auth'; //imported from expo package
import {
GoogleAuthProvider,getAuth
} from 'firebase/auth';
import { initializeApp } from "firebase/app";
import { firebaseconfig } from '[your firebase credentials]';
const app=intitializeApp(firebaseconfig)
const auth=getAuth(app);
async function signInWithGoogleAsync() {
try {
const result = await Google.logInAsync({
androidClientId: 'cliend id from google dev console',
iosClientId: 'client id from google dev console for ios app(if you setup)',
scopes: ['profile', 'email'],
});
if (result.type === 'success') {
console.log(result)
const credential = GoogleAuthProvider.credential(result.idToken, result.accessToken);
// Sign in with credential from the Facebook user.
signInWithCredential(auth, credential)
.then(async result => {
console.log(result)
})
.catch(error => { console.log(error) });
return result.accessToken;
} else {
console.log("cancelled by user")
return { cancelled: true };
}
} catch (e) {
console.log(e);
return { error: true };
}//
}

How to send email verification after user creation with Firebase Cloud functions?

I'm trying to send the verification email after the user is created. Since there's no way on Firebase itself, I'm trying it with cloud functions.
I cannot really find a lot of documentation about it. What I tried to do so far is:
exports.sendEmailVerification = functions.auth.user().onCreate(event => {
return user.sendEmailVerification()
});
But I get the error that user is not defined.
How can I create this function?
Thanks!
There are two possibilities to send an "email verification" email to a user:
The signed-in user requests that a verification email be sent. For that, you call, from the front-end, the sendEmailVerification() method from the appropriate Client SDK.
Through one of the Admin SDKs, you generate a link for email verification via the corresponding method (e.g. auth.generateEmailVerificationLink() for the Node.js Admin SDK) and you send this link via an email sent through your own mechanism. All of that is done in the back-end, and can be done in a Cloud Function.
Note that the second option with the Admin SDKs is not exactly similar to the first option with the Client SDKs: in the second option you need to send the email through your own mechanism, while in the first case, the email is automatically sent by the Firebase platform
If you'd like that ability to be added to the Admin SDK, I'd recommend you file a feature request.
This is how I implemented it successfully using Firebase cloud functions along with a small express backend server
Firebase Cloud function (background) triggered with every new user created
This function sends a "user" object to your api endpoint
const functions = require('firebase-functions');
const fetch = require('node-fetch');
// Send email verification through express server
exports.sendVerificationEmail = functions.auth.user().onCreate((user) => {
// Example of API ENPOINT URL 'https://mybackendapi.com/api/verifyemail/'
return fetch( < API ENDPOINT URL > , {
method: 'POST',
body: JSON.stringify({
user: user
}),
headers: {
"Content-Type": "application/json"
}
}).then(res => console.log(res))
.catch(err => console.log(err));
});
Server Middleware code
verifyEmail here is used as middleware
// File name 'middleware.js'
import firebase from 'firebase';
import admin from 'firebase-admin';
// Get Service account file from firebase console
// Store it locally - make sure not to commit it to GIT
const serviceAccount = require('<PATH TO serviceAccount.json FILE>');
// Get if from Firebase console and either use environment variables or copy and paste them directly
// review security issues for the second approach
const config = {
apiKey: process.env.APIKEY,
authDomain: process.env.AUTHDOMAIN,
projectId: process.env.PROJECT_ID,
};
// Initialize Firebase Admin
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
// Initialize firebase Client
firebase.initializeApp(config);
export const verifyEmail = async(req, res, next) => {
const sentUser = req.body.user;
try {
const customToken = await admin.auth().createCustomToken(sentUser.uid);
await firebase.auth().signInWithCustomToken(customToken);
const mycurrentUser = firebase.auth().currentUser;
await mycurrentUser.sendEmailVerification();
res.locals.data = mycurrentUser;
next();
} catch (err) {
next(err);
}
};
Server code
// Filename 'app.js'
import express from 'express';
import bodyParser from 'body-parser';
// If you don't use cors, the api will reject request if u call it from Cloud functions
import cors from 'cors';
import {
verifyEmail
} from './middleware'
app.use(cors());
app.use(bodyParser.urlencoded({
extended: true,
}));
app.use(bodyParser.json());
const app = express();
// If you use the above example for endpoint then here will be
// '/api/verifyemail/'
app.post('<PATH TO ENDPOINT>', verifyEmail, (req, res, next) => {
res.json({
status: 'success',
data: res.locals.data
});
next()
})
This endpoint will return back the full user object and will send the verification email to user.
I hope this helps.
First view the documentation by Firebase here.
As the registration phase completes and result in success, trigger the following function asynchronously :
private void sendVerification() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.sendEmailVerification().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
system.print.out("Verification Email sent Champion")
}
}
});
}
The user will now be provided with a verification Email. Upon clicking the hyper linked the user will be verified by your project server with Firebase.
How do you determine whether or not a user did verify their Email?
private void checkEmail() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user.isEmailVerified()) {
// email verified ...
} else {
// error : email not verified ...
}
}
Sadly, you may not customize the content/body of your verification Email ( I have been heavily corresponding with Firebase to provide alternative less hideous looking templates ). You may change the title or the message sender ID, but that's all there is to it.
Not unless you relink your application with your own supported Web. Here.
Since the release of the Version 6.2.0 of the Node.js Admin SDK on November 19, 2018 it is possible to generate, in a Cloud Function, a link for email verification via the auth.generateEmailVerificationLink() method.
You will find more details and some code samples in the documentation.
You can then send an email containing this link via Mailgun, Sendgrid or any other email microservice. You'll find here a Cloud Function sample that shows how to send an email from a Cloud Function.
If you want to let Admin SDK do it, as of now there is no option other than generating the email verification link and sending with your own email delivery system.
However
You can write a REST request on cloud functions and initiate the email verification mail this way.
export async function verifyEmail(apiKey : string, accessToken : string) {
// Create date for POST request
const options = {
method: 'POST',
url: 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/getOobConfirmationCode',
params: {
key: apiKey
},
data: {
requestType : "VERIFY_EMAIL",
idToken : accessToken
}
};
return await processRequest(options); //This is just to fire the request
}
As soon as you signup, pass the access token to this method and it should send a mail to the signup user.
apiKey : Is the "Web API key" listed in General tab of your project settings in firebase console
access token : Access token of the current user (I use signup rest api internally so there is an option to request token in response)

Resources