React Native: Implementing Facebook OAuth with Redux Saga Firebase - firebase

I'm trying to implement Facebook OAuth (react-native-fbsdk) in my React Native application. I can get the Access Token. With the access token, I can then retrieve the credentials using const credential = yield facebookAuth.credential(data.accessToken); Then when I try to create a user, I get an error (see below)
The Credentials Object:
{
oauthIdToken: "MY_ID_TOKEN"
providerId: "facebook.com"
signInMethod: "facebook.com"
}
The Issue:
The last step that I want to do that I can't seem to figure out is to create a user in Firebase using the credentials in const user = yield call(reduxSagaFirebase.auth.signInAndRetrieveDataWithCredential, credential);
When I try and sign in with the credential, I get the following error: Invalid IdP response/credential http://localhost?id_token="MY_TOKEN_HERE
Login With Facebook Saga
// Redux Saga: Login With Facebook
function* loginWithFacebookSaga() {
try {
// Login To Facebook With Read Permissions
console.log('Logging in with Facebook');
yield LoginManager.logInWithPermissions([
'public_profile',
'email',
'user_friends',
]);
// Check If Cancelled
// if (!result.isCancelled) {
const data = yield AccessToken.getCurrentAccessToken();
// yield alert(JSON.stringify(data.accessToken));
// }
// Create Firebase Auth Account With Facebook Access Token
const credential = yield facebookAuth.credential(data.accessToken);
// alert(JSON.stringify(credential));
// Login (ISSUE HERE)
const user = yield call(reduxSagaFirebase.auth.signInAndRetrieveDataWithCredential, credential);
}
catch (error) {
// Firebase: Login Error
alert(error);
yield put(loginWithFacebookError(error));
}
};

UPDATE: You may got the problem with the credential. Please try below
import firebase from 'firebase';
const credential = firebase.auth.FacebookAuthProvider.credential(data.accessToken);

Related

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 };
}
};

How to sign in with Apple and Google credentials in react-native and supabase

I have been trying to implement sign in with google and apple using the following libraries and supabase in bare react-native projects.
react-native-apple-authentication
react-native-google-signin
They work very well with firebase as described here using firebase sdk.
The concept is fairly simple, the native sdk for both apple and google sign return user credential after a successful sign in . Here is an example from https://rnfirebase.io/auth/social-auth
With google credential
import auth from '#react-native-firebase/auth';
import { GoogleSignin } from '#react-native-google-signin/google-signin';
async function onGoogleButtonPress() {
// Get the users ID token
const { idToken } = await GoogleSignin.signIn();
// Create a Google credential with the token
const googleCredential = auth.GoogleAuthProvider.credential(idToken);
// Sign-in the user with the credential
return auth().signInWithCredential(googleCredential);
}
With apple credential
import auth from '#react-native-firebase/auth';
import { appleAuth } from '#invertase/react-native-apple-authentication';
async function onAppleButtonPress() {
// Start the sign-in request
const appleAuthRequestResponse = await appleAuth.performRequest({
requestedOperation: appleAuth.Operation.LOGIN,
requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
});
// Ensure Apple returned a user identityToken
if (!appleAuthRequestResponse.identityToken) {
throw 'Apple Sign-In failed - no identify token returned';
}
// Create a Firebase credential from the response
const { identityToken, nonce } = appleAuthRequestResponse;
const appleCredential = auth.AppleAuthProvider.credential(identityToken, nonce);
// Sign the user in with the credential
return auth().signInWithCredential(appleCredential);
}
I have gone through the auth provided by supabase here supabase-js auth
The closest thing I can find related to the implementation above is the use of a refresh-token as shown here
Sign in using a refresh token
// An example using Expo's `AuthSession`
const redirectUri = AuthSession.makeRedirectUri({ useProxy: false });
const provider = 'google';
AuthSession.startAsync({
authUrl: `https://MYSUPABASEAPP.supabase.co/auth/v1/authorize?provider=${provider}&redirect_to=${redirectUri}`,
returnUrl: redirectUri,
}).then(async (response: any) => {
if (!response) return;
const { user, session, error } = await supabase.auth.signIn({
refreshToken: response.params?.refresh_token,
});
});
The example above uses a refreshToken parameter auth.sign() to create a session for a user who is already registered.
Correct me if am wrong. According to the auth documentation there is no method that allows one to create a user using an auth credential. This is because of how gotrue social auth is implemented. The only solution I can think of as now is to move the entire auth logic to the backend and handle it on the web. This is not elegant at all since it will have to involve ugly deep-linking or webview implementations to use supabase session and access token.
Given the scenario above, is there way of using native social sdk in react-native to create a new user account in supabase using a user credential without having to force them use an email link, password or web ? Any ideas , answers or corrections are welcome.
At the time of writing, Signing in with third party credentials is not implemented in gotrue(Module used for auth in supabase) yet. If you have a native app, flutter app and react-native app that needs social auth using credentials follow up on this WIP:PR. For further information refer to Proof Key for Code Exchange (PKCE).

React native firebase - facebook sign-in

Im following the official code sample provided by RNFB....code below
Problem is that you dont get past the line const facebookCredential = firebase.FacebookAuthProvider.credential(data.accessToken);.....it appears that the firebase.FacebookAuthProvider method is showing as undefined so you dont get the facebookCredential variable back
import { firebase } from '#react-native-firebase/auth';
async function onFacebookButtonPress() {
// Attempt login with permissions
const result = await LoginManager.logInWithPermissions(['public_profile', 'email']);
if (result.isCancelled) {
throw 'User cancelled the login process';
}
// Once signed in, get the users AccesToken
const data = await AccessToken.getCurrentAccessToken();
if (!data) {
throw 'Something went wrong obtaining access token';
}
// Create a Firebase credential with the AccessToken
const facebookCredential = auth.FacebookAuthProvider.credential(data.accessToken);
// Sign-in the user with the credential
return auth().signInWithCredential(facebookCredential);
}
The example linked seems to be missing the declaration of an auth variable. We need to get it from the imported firebase moduled.
Instead of:
auth.FacebookAuthProvider
We should be using:
firebase.auth.FacebookAuthProvider

React Native Google Signin idToken null

I am using react-native 0.60.5, with firebase authentication (using package react-native-firebase and react-native-google-signin).
Everything looks good to me and the google sign return an object with the user logged in, but the idToken is always null. I need to get the idToken to perform the authentication in firebase.
import { GoogleSignin } from 'react-native-google-signin';
export const googleLogin = async () => {
GoogleSignin.configure();
const userInfo = await GoogleSignin.signIn();
//here we have the issue. userInfo cotains all google user informations except the idToken
//userInfo.idToken is null
}
how can I fix the google-sign-in to return the idToken?
Add the web client id which is availble in Firebase authentication/signInmethod/Google:
function configureGoogleSign() {
GoogleSignin.configure({
webClientId: WEB_CLIENT_ID,
offlineAccess: false
})
}
This is working for me.
You have not specified webclientId.
and make sure to configure google signIn in useEffect Method so when you load the screen it already configured.
useEffect(() => {
GoogleSignin.configure({
webClientId:
'YOUR_WEBCLIENT_ID',
});
}, []);

Firebase Authentication with Google Identity (GoogleYOLO)

Is it possible to combine Google Identity (GoogleYOLO) with the Firebase Authentication web stack? If so, how? Thanks!
You can sign in with googleyolo using Firebase Auth as follows:
hintPromise.then((credential) => {
if (credential.idToken) {
// Initialize firebase Auth credential with Google ID token
// obtained from googleyolo.
const cred = firebase.auth.GoogleAuthProvider.credential(credential.idToken);
// Sign in with
return firebase.auth().signInWithCredential(cred);
}
throw new Error;
}).then((result) => {
// User signed in.
}).catch((error) => {
// Handle error.
});
Building on #bojeil's reply, the ID token required by Firebase's signInWithCredential function exists within the credential property of the credential object. Therefore, rather than retrieving the token using credential.idToken, you must retrieve the token with credential.credential. Here is a sample function below using Firebase V8.
// firebase V8
function handleCredentialResponse(credential) {
if (credential) {
const cred = auth.GoogleAuthProvider.credential(credential.credential);
// Sign in with credential from the Google user.
return auth().signInWithCredential(cred);
}
}
The credential param is a credential response returned from the Google one-tap function callback.
google?.accounts.id.initialize({
client_id: your-google-app-client-id.apps.googleusercontent.com,
callback: handleCredentialResponse,
});
google?.accounts.id.prompt((notification) => {
console.log(notification);
});

Resources