使用apollo graphql的react firebase认证[英] react firebase authentication with apollo graphql

本文是小编为大家收集整理的关于使用apollo graphql的react firebase认证的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我发现了一篇很棒的文章,将身份验证添加到React中. 文章: https:///wwwwwwwwwwwwwwww.robinwieruch.de/complete-complete-firete-firebase-complete-firebase-authentication- - 回答教程/

本文用我可以将其放入应用程序并可以使用上下文访问的HOC组件完成了Firebase设置(Redux之前).

我的问题是如何将其放入应用程序组件之外的Apollo客户端中,即使我无法将其设置为上下文.我对Redux也有同样的问题.我发现只有一个是使用本地存储,但我想避免.

这是我的Apollo客户端.

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

推荐答案

所以这不是最好的方法,但这是我目前设置的方式.

这是我的阿波罗客户端设置

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,看起来根本没有延迟.这可能不是最好的答案,因为当我只是学习所有内容时,我从几个文档中将其放在一起,并在我有时间的时候就一直在重新审视.

.

本文地址:https://www.itbaoku.cn/post/1938053.html

问题描述

I have found a great article adding authentication into react. Article: https://www.robinwieruch.de/complete-firebase-authentication-react-tutorial/

This article finishes the firebase setup (before redux) with a HOC component that I can put into the app and can access with context.

My issue is how do i put this into the apollo client which is outside of the app component so even with the context I cant set it. I have this same problem with redux. Only one I have found is use local storage but I would like to avoid that.

This is my apollo client in the main app component.

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

推荐答案

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.