我发现一篇很棒的文章将身份验证添加到了react中。 文章:https://www.robinwieruch.de/complete-firebase-authentication-react-tutorial/
本文完成了Firebase的安装(在redux之前),它带有一个HOC组件,我可以将其放入应用程序并可以通过上下文进行访问。
我的问题是如何将其放入应用程序组件外部的apollo客户端中,因此即使使用上下文也无法设置它。我对redux也有同样的问题。我发现只有一个使用本地存储,但是我想避免这种情况。
这是我在主要应用程序组件中的阿波罗客户端。
const client = new ApolloClient({
uri: clientUrl,
request: async operation => {
const token = How_do_i_set_this <-- ???
console.log('token in request', token)
operation.setContext({
headers: {
authorization: token ? `Bearer ${token}` : ''
}
});
}
});
const App = () => (
<DashAppHolder>
<ApolloProvider client={client}>
<Provider store={store}>
<PublicRoutes history={history} />
</Provider>
</ApolloProvider>
</DashAppHolder>
);
答案 0 :(得分:1)
所以这不是最好的方法,但这是我目前设置的方式。
这是我的阿波罗客户端设置
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'
}
});
}
});
这是我导入的Firebase助手类
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;
}
}
最后在服务器上,这是我使用的我的graphql设置相关事件信息
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)),
}
})),
);
此答案有效,并让我获得了通过Firebase授权的用户的UID,看起来根本没有延迟。这可能不是最好的答案,因为我在学习所有内容时就将多个文档放在一起,并希望在有时间但又要工作的时候回头再来。