使用 firebase admin Auth 在 HTTPS 调用期间进行云功能和客户端身份验证
Cloud Function & client authentication during HTTPS Call using firebase admin Auth
背景:
我有三个实体(语言: JS):
- 浏览器客户端
- Google 云函数
- 一个 HTTP 服务器[有 Firebase admin Auth 中间件]
所以,从 1 和 2,我想使用 HTTPS 调用与 3 通信。
因为 3 已经有 admin Auth,所以我可以授权来自 clients(1) 的调用。
但我想知道如何授权来自 google 云函数的调用(2),以便我可以安全地与两个实体通信。
令牌授权中间件:
const validateFirebaseIdToken = async (req: any, res: any, next: any) => {
console.log(await auth.getCredentials());
if (
(!req.headers.authorization ||
!req.headers.authorization.startsWith("Bearer ")) &&
!(req.cookies && req.cookies.__session)
) {
console.log(
"No Firebase ID token was passed as a Bearer token in the Authorization header." +
"Make sure you authorize your request by providing the following HTTP header:" +
"Authorization: Bearer <Firebase ID Token>" +
'or by passing a "__session" cookie.'
);
res.status(403).send("Unauthorized 1");
return;
}
let idToken;
if (
req.headers.authorization &&
req.headers.authorization.startsWith("Bearer ")
) {
console.log('Found "Authorization" header');
// Read the ID Token from the Authorization header.
idToken = req.headers.authorization.split("Bearer ")[1];
} else if (req.cookies) {
console.log('Found "__session" cookie');
// Read the ID Token from cookie.
idToken = req.cookies.__session;
} else {
// No cookie
res.status(403).send("Unauthorized 2");
return;
}
try {
const decodedIdToken = await admin.auth().verifyIdToken(idToken);
req.user = decodedIdToken;
next();
return;
} catch (error) {
console.log("Error while verifying Firebase ID token:" + error);
res.status(403).send("Unauthorized 3");
return;
}
};
听起来您正试图从云函数向您的服务器发出 API 调用。如果您正在使用 functions.https.onCall
可调用函数,它会自动反序列化请求正文并验证身份验证令牌。因此,除非您明确传递它们,否则您不会获得实际的 ID 令牌。
要将用户信息传递到您的服务器,您可以尝试以下任一方法:
将 ID Token 显式传递给云函数,然后传递给您的 API,这将再次验证 ID Token。
如前所述,可调用的云函数将自动验证用户并将 DecodedIdToken
添加到 context.auth.token
。由于用户已经通过身份验证,您可以简单地将用户的 UID(以及其他必要的声明)传递到您的服务器以进行进一步处理。但是,这意味着您必须以接受 UID 而不是令牌的方式配置中间件,令牌可以通过使用某些 UID 直接向服务器发出随机请求而被滥用。
如果您使用方法 2,则必须确保请求仅来自您的云功能。这可以通过在云功能和服务器之间共享一个秘密来完成,您可以将该秘密附加到您向服务器发出的每个 HTTP 请求,类似于 API 密钥。
背景: 我有三个实体(语言: JS):
- 浏览器客户端
- Google 云函数
- 一个 HTTP 服务器[有 Firebase admin Auth 中间件]
所以,从 1 和 2,我想使用 HTTPS 调用与 3 通信。 因为 3 已经有 admin Auth,所以我可以授权来自 clients(1) 的调用。
但我想知道如何授权来自 google 云函数的调用(2),以便我可以安全地与两个实体通信。
令牌授权中间件:
const validateFirebaseIdToken = async (req: any, res: any, next: any) => {
console.log(await auth.getCredentials());
if (
(!req.headers.authorization ||
!req.headers.authorization.startsWith("Bearer ")) &&
!(req.cookies && req.cookies.__session)
) {
console.log(
"No Firebase ID token was passed as a Bearer token in the Authorization header." +
"Make sure you authorize your request by providing the following HTTP header:" +
"Authorization: Bearer <Firebase ID Token>" +
'or by passing a "__session" cookie.'
);
res.status(403).send("Unauthorized 1");
return;
}
let idToken;
if (
req.headers.authorization &&
req.headers.authorization.startsWith("Bearer ")
) {
console.log('Found "Authorization" header');
// Read the ID Token from the Authorization header.
idToken = req.headers.authorization.split("Bearer ")[1];
} else if (req.cookies) {
console.log('Found "__session" cookie');
// Read the ID Token from cookie.
idToken = req.cookies.__session;
} else {
// No cookie
res.status(403).send("Unauthorized 2");
return;
}
try {
const decodedIdToken = await admin.auth().verifyIdToken(idToken);
req.user = decodedIdToken;
next();
return;
} catch (error) {
console.log("Error while verifying Firebase ID token:" + error);
res.status(403).send("Unauthorized 3");
return;
}
};
听起来您正试图从云函数向您的服务器发出 API 调用。如果您正在使用 functions.https.onCall
可调用函数,它会自动反序列化请求正文并验证身份验证令牌。因此,除非您明确传递它们,否则您不会获得实际的 ID 令牌。
要将用户信息传递到您的服务器,您可以尝试以下任一方法:
将 ID Token 显式传递给云函数,然后传递给您的 API,这将再次验证 ID Token。
如前所述,可调用的云函数将自动验证用户并将
DecodedIdToken
添加到context.auth.token
。由于用户已经通过身份验证,您可以简单地将用户的 UID(以及其他必要的声明)传递到您的服务器以进行进一步处理。但是,这意味着您必须以接受 UID 而不是令牌的方式配置中间件,令牌可以通过使用某些 UID 直接向服务器发出随机请求而被滥用。
如果您使用方法 2,则必须确保请求仅来自您的云功能。这可以通过在云功能和服务器之间共享一个秘密来完成,您可以将该秘密附加到您向服务器发出的每个 HTTP 请求,类似于 API 密钥。