[英]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.