I have found a great article adding authentication into react. Article: https://www.robinwieruch.de/complete-firebase-authentication-react-tutorial/
This article finishe
So this my not be the best way but this is how I have it setup at the moment.
this is my apollo client setup
import Firebase from './helpers/firebase';
import ApolloClient from "apollo-boost";
const client = new ApolloClient({
uri: clientUrl,
request: async operation => {
const fireToken = await Firebase.token();
console.log('fire token', fireToken);
operation.setContext({
headers: {
authorization: fireToken ? `Bearer ${fireToken}` : 'token bad'
}
});
}
});
This is my firebase helper class I import
import firebase from 'firebase';
import 'firebase/firestore';
import { firebaseConfig } from '../../settings';
const valid = firebaseConfig && firebaseConfig.apiKey && firebaseConfig.projectId;
const firebaseApp = firebase.initializeApp(firebaseConfig);
const firebaseAuth = firebase.auth;
class FirebaseHelper {
isValid = valid;
EMAIL = 'email';
FACEBOOK = 'facebook';
GOOGLE = 'google';
GITHUB = 'github';
TWITTER = 'twitter';
constructor() {
this.login = this.login.bind(this);
this.logout = this.logout.bind(this);
this.signup = this.signup.bind(this);
this.resetPassword = this.resetPassword.bind(this);
this.doPasswordUpdate = this.doPasswordUpdate.bind(this);
this.auth = this.auth.bind(this);
this.database = firebase.firestore();
}
token = async() => {
const user = this.user()
if (user) {
return await user.getIdToken().then(token => { return token });
} else {
return null;
}
}
user() {
return firebaseAuth().currentUser;
}
login(provider, info) {
switch (provider) {
case this.EMAIL:
return firebaseAuth().signInWithEmailAndPassword(
info.email,
info.password
);
case this.GOOGLE:
var googleProvider = new firebase.auth.GoogleAuthProvider();
return firebaseAuth().signInWithPopup(googleProvider);
default:
}
}
signup(provider, info) {
switch (provider) {
case this.EMAIL:
return firebaseAuth().createUserWithEmailAndPassword(
info.email,
info.password
);
case this.FACEBOOK:
return firebaseAuth().FacebookAuthProvider();
case this.GOOGLE:
return firebaseAuth().GoogleAuthProvider();
case this.GITHUB:
return firebaseAuth().GithubAuthProvider();
case this.TWITTER:
return firebaseAuth().TwitterAuthProvider();
default:
alert('defaulted');
}
}
logout() {
return firebaseAuth().signOut();
}
auth = () => {
return firebaseAuth()
}
resetPassword(email) {
return firebaseAuth().sendPasswordResetEmail(email);
}
doPasswordUpdate(password) {
firebaseAuth().currentUser.updatePassword(password);
}
createNewRef() {
return firebase
.database()
.ref()
.push().key;
}
}
And lastly on the server here is my graphql setup relevent information I use
const admin = require('firebase-admin');
const getUid = async (request) => {
let idToken = (request.headers && request.headers.authorization) ? request.headers.authorization : null;
if (!idToken) {
console.log('no token found');
return null;
}
console.log('raw token', idToken);
var newToken = idToken.replace("Bearer ", "");
console.log('pure token', newToken)
let uid = await admin.auth().verifyIdToken(newToken)
.then(decodedToken => {
var uid = decodedToken.uid;
return uid;
}).catch((error) => {
// Handle error
console.log('uid failed', error);
return null;
});
console.log('uid found', uid);
return uid;
}
app.use(
'/graphql',
cors(),
express.json(),
graphqlExpress(async (request) => ({
schema: schema,
context: {
request: request,
uid: await getUid(request),
accountLoader: new Dataloader(keys => batchAccounts(keys, db)),
dealLoader: new Dataloader(keys => batchDeals(keys, db)),
}
})),
);
This answer works and gets me the UID of the user authorized through firebase and looks like there is no delay at all. This might not be the best answer because I Put this together from several documents when I was just learning everything and have been meaning to go back and revisit when I have time but again, working.