简体   繁体   English

如何在 Firestore Cloud Functions 上使用 Apollo 服务器 GraphQL 处理 TypeScript 中的身份验证

[英]How to handle authentication in TypeScript with Apollo Server GraphQL on Firestore Cloud Functions

I've been following this article but attempting to do this in TypeScript instead of JavaScript: https://medium.com/@piuccio/running-apollo-server-on-firebase-cloud-functions-265849e9f5b8 I've been following this article but attempting to do this in TypeScript instead of JavaScript: https://medium.com/@piuccio/running-apollo-server-on-firebase-cloud-functions-265849e9f5b8

However I can't get the behaviour correct on when a Authorization header is not correctly supplied.但是,当未正确提供Authorization header 时,我无法获得正确的行为。 In the code below I am throwing an Error("No token") .在下面的代码中,我抛出了一个Error("No token") I also attempted to return a rejected Promise but that gave me a HTTP 500 error with {} (an empty JSON response).我还尝试返回一个被拒绝的Promise但这给了我一个 HTTP 500 错误{} (一个空的 JSON 响应)。

import gql from 'graphql-tag';
import { makeExecutableSchema } from 'graphql-tools';
import { Config } from 'apollo-server-cloud-functions';
import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';


... resolvers, etc go here...


async function getUser(token: string): Promise<admin.auth.DecodedIdToken> {
    functions.logger.info('token', token);
    if (token === undefined || token === '') {
        throw new Error("No token");
    }
    const idToken = token.split('Bearer ')[1];
    const decodedIdToken = await admin.auth().verifyIdToken(idToken);
    return decodedIdToken;
}

export const config: Config = {
    schema: makeExecutableSchema({
        typeDefs,
        resolvers,
    }),

    // TODO: DISABLE THESE IN PRODUCTION!
    introspection: true,
    playground: true,

    context: ({req, context}): Promise<admin.auth.DecodedIdToken> => {
        // See https://www.apollographql.com/docs/apollo-server/security/authentication/
        functions.logger.info('req headers', req.headers);
        const token = req.headers.authorization || '';
        const user = getUser(token);
        // if (!user) throw new AuthenticationError('you must be logged in');
        return user;
    },
    formatError: formatError,
};

How can I return a valid Promise from getUser() for situations where the API supports anonymous access?对于 API 支持匿名访问的情况,如何从getUser()返回有效的Promise

I'd prefer to use the Apollo Server AuthenticationError (as my authentication check) but I can't return null from getUser() .我更喜欢使用 Apollo Server AuthenticationError (作为我的身份验证检查),但我无法从getUser()返回null

Following the suggestions over here: How to reject in async/await syntax?按照这里的建议: 如何拒绝异步/等待语法?

I can modify the type of the Promise to be DecodedIdToken | null我可以将Promise的类型修改为DecodedIdToken | null DecodedIdToken | null and return null as a valid value. DecodedIdToken | null并返回null作为有效值。 If I reject the Promise then an exception is thrown with the error string.如果我reject Promise ,则会抛出带有错误字符串的异常。

async function getUser(token: string): Promise<DecodedIdToken | null> {
    functions.logger.info('token', token);
    if (token === undefined || token === '') {
        return null;
        // return Promise.reject("No token");
    }
    const idToken = token.split('Bearer ')[1];
    const decodedIdToken = admin.auth().verifyIdToken(idToken);
    return decodedIdToken;
}

export const config: Config = {
    schema: makeExecutableSchema({
        typeDefs,
        resolvers,
    }),

    // TODO: DISABLE THESE IN PRODUCTION!
    introspection: true,
    playground: true,

    context: async ({req, context}): Promise<DecodedIdToken | null> => {
        // See https://www.apollographql.com/docs/apollo-server/security/authentication/
        functions.logger.info('req headers', req.headers);
        const token = req.headers.authorization || '';
        try {
            const user = await getUser(token);
            return Promise.resolve(user);

        } catch (err) {
            return Promise.resolve(null); // "No token"
            // throw new AuthenticationError('you must be logged in');
        }
    },
    formatError: formatError,
};

So depending on whether you want the exception thrown or not, or if you want to use your own exception (such as AuthenticationError for FireStore) you can structure it the way you want.因此,取决于您是否想要抛出异常,或者您是否想要使用自己的异常(例如 FireStore 的AuthenticationError ),您可以按照您想要的方式构造它。

Here are the different options:以下是不同的选项:

Promise.resolve(value)
Promise.resolve(null)
Promise.reject("Not valid")  -> throws exception Error("Not valid")
throw new AuthenticationError("Not authorized")

... or using the constructor syntax: ...或使用构造函数语法:

return new Promise<DecodedIdToken | null>((resolve, reject) => {
  if (valid) {
    resolve(value);
  } else {
    reject("Not valid");
  }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Apollo GraphQL 服务器 + 打字稿 - Apollo GraphQL Server + TypeScript 在 VS Code 中调试 Typescript Apollo Server (graphQL) 时未绑定断点 - Breakpoint not bound when Debugging Typescript Apollo Server (graphQL) in VS Code 使用Cloud Firestore和TypeScript的云功能无法执行 - Cloud functions using Cloud Firestore and TypeScript don't execute 如何使用Typescript从云功能(functions.https.HttpsError)处理客户端(Android)中的错误 - How to handle errors in client side (Android) from cloud functions (functions.https.HttpsError) using Typescript 使用 Express、Firestore、Cloud Functions 和 TypeScript 构建 REST API - Building a REST API using Express, Firestore, Cloud Functions & TypeScript 使用 React TypeScript 进行 GraphQL 身份验证 - GraphQL Authentication with React TypeScript Apollo 服务器中的 Typescript 语法 - Typescript Syntax in Apollo server 如何使用 Apollo Server 测试提供身份验证令牌的 GraphQL 查询? - How to test a GraphQL query providing an auth token with Apollo Server? GraphQL Apollo Server,如何使字段将空字符串注册为空 - GraphQL Apollo Server, how to make a field register an empty string as null 如何在解析器中使用 Apollo-Server Graphql 的枚举? - How to use enum of Apollo-Server Graphql in resolver?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM