我需要帮助让我的Firebase ApolloGraphQL云函数认证和接收查询请求。
allAuthenticatedUsers
而我使用的是 Firebase电话认证 来验证。ApolloGraphQL函数可以正常工作。(用操场测试) 当权限设置为 allUsers
. 在将权限设置为 allAuthenticatedUsers
并试图发送验证查询,我收到了以下错误响应。
Bearer error="invalid_token" error_description="The access token could not be verified"
我相信我在客户端发送的请求中犯了错误,或者说在ApolloServer的验证和 "上下文 "的处理上犯了错误。我已经确认初始用户令牌是正确的。我目前的理论是,我发送了错误的头,或者在客户端或服务器层面上以某种方式搞乱了语法。
解释一下我认为适当的请求流程应该是什么。
如果有谁能解释一下如何向Firebase ApolloGraphQL云函数发送有效的认证客户端查询,将非常感谢帮助。下面是服务器和客户端的代码。
服务器.js (ApolloServer)
/* Assume proper imports */
/* Initialize Firebase Admin SDK */
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "[db-url]",
});
/* Async verification with user token */
const verify = async (idToken) => {
var newToken = idToken.replace("Bearer ", "");
let header = await admin.auth().verifyIdToken(newToken)
.then(function(decodedToken) {
let uid = decodedToken.uid;
// Not sure if I should be using the .uid from above as the token?
// Also, not sure if returning the below object is acceptable, or
// if this is even the correct header to send to firebase from Apollo
return {
"Authorization": `Bearer ${decodedToken}`
}
}).catch(function(error) {
// Handle error
return null
});
return header
}
/* Server */
function gqlServer() {
const app = express();
const apolloServer = new ApolloServer({
typeDefs: schema,
resolvers,
context: async ({ req, res }) => {
const verified = await verify(req.headers.Authorization)
console.log('log verified', verified)
return {
headers: verified ? verified: '',
req,
res,
}
},
// Enable graphiql gui
introspection: true,
playground: true
});
apolloServer.applyMiddleware({app, path: '/', cors: true});
return app;
}
export default gqlServer;
Client.js (ApolloClient)
客户端查询使用 本说明.
/* Assume appropriate imports */
/* React Native firebase auth */
firebase.auth().onAuthStateChanged(async (user) => {
const userToken = await user.getIdToken();
/* Client creation */
const client = new ApolloClient({
uri: '[Firebase Cloud Function URL]',
headers: {
Authorization: userToken ? `Bearer ${userToken}` : ''
},
cache: new InMemoryCache(),
});
/* Query test */
client.query({
query: gql`
{
hello
}
`
}).then(
(result) => console.log('log query result', result)
).catch(
(error) => console.log('query error', error)
)
})
更新050320
我可能已经找到了错误的来源。在我确认之前,我不会发布答案,但这里是更新。看起来像 allAuthenticatedUsers
是Google账户特有的角色,而不是Firebase。参见 这一部分的谷歌文档 和 这个stackoverflow的答案.
我将做一些测试,但解决方案 可 是将权限改为 allUsers
这可能仍然需要认证。如果我可以让它工作,我会更新答案。
我能够让事情工作。工作请求需要进行以下修改。
allUsers
而不是 allAuthenticatedUsers
. 这是因为 allUsers
角色使该函数可以用于http请求(你仍然可以通过sdk验证要求认证)。服务器.js (ApolloServer)
/* Assume proper imports */
/* Initialize Firebase Admin SDK */
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "[db-url]",
});
/* Async verification with user token */
const verify = async (idToken) => {
if (idToken) {
var newToken = idToken.replace("Bearer ", "");
// var newToken = idToken
let header = await admin.auth().verifyIdToken(newToken)
.then(function(decodedToken) {
// ...
return {
"Authorization": 'Bearer ' + decodedToken
}
}).catch(function(error) {
// Handle error
return null
});
return header
} else {
throw 'No Access'
}
}
/* Server */
function gqlServer() {
const app = express();
const apolloServer = new ApolloServer({
typeDefs: schema,
resolvers,
context: async ({ req, res }) => {
// headers: req.headers,
const verified = await verify(req.headers.authorization)
console.log('log verified', verified)
return {
headers: verified ? verified: '',
req,
res,
}
},
// Enable graphiql gui
introspection: true,
playground: true
});
apolloServer.applyMiddleware({app, path: '/', cors: true});
return app;
}
export default gqlServer;
Client.js (ApolloClient)
/* Assume appropriate imports */
/* React Native firebase auth */
firebase.auth().onAuthStateChanged(async (user) => {
const userToken = await user.getIdToken();
/* Client creation */
const userToken = await user.getIdToken();
const client = new ApolloClient({
uri: '[Firebase Cloud Function URL]',
headers: {
"Authorization": userToken ? 'Bearer ' + userToken : ''
},
cache: new InMemoryCache(),
});
client.query({
query: gql`
{
hello
}
`
}).then(
(result) => console.log('log query result', result)
).catch(
(error) => console.log('query error', error)
)
})