使用 apollo graphql 反应 firebase 身份验证

2024-02-23

我发现一篇很棒的文章将身份验证添加到反应中。 文章:https://www.robinwieruch.de/complete-firebase-authentication-react-tutorial/ https://www.robinwieruch.de/complete-firebase-authentication-react-tutorial/

本文使用 HOC 组件完成了 firebase 设置(在 redux 之前),我可以将其放入应用程序中并可以通过上下文进行访问。

我的问题是如何将其放入应用程序组件之外的阿波罗客户端中,因此即使有上下文我也无法设置它。我对 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 helper 类

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,看起来根本没有延迟。这可能不是最好的答案,因为当我刚刚学习所有内容时,我将这些文件放在一起,并且一直打算在有时间但再次工作时回去重新访问。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 apollo graphql 反应 firebase 身份验证 的相关文章

随机推荐