Firebase跨子域认证流程中Set-Cookie头返回的Cookie未被浏览器设置的问题求助
我有一个部署在Firebase上的Angular站点,域名是account.mydomain.com,还有一些Firebase/Google Cloud函数部署在functions.mydomain.com。我正尝试搭建一套跨子域认证流程,具体步骤如下:
- 在
account.mydomain.com通过Firebase Auth完成登录; - 将登录成功后获取的idToken POST到名为
sessionLogin的Firebase函数(用onRequest编写),该函数会验证idToken、创建会话Cookie并在响应中返回; - 单独发起GET请求到
checkAuthStatus函数端点,验证Cookie并获取访问令牌,用它在account.mydomain.com上完成认证。
我的核心目标是通过这个会话实现mydomain.com下所有子域的统一认证,但目前遇到了一个棘手的问题:步骤2完成后,Cookie始终没有被浏览器设置——虽然在网络响应的Set-Cookie头中能清晰看到它,但就是不生效。
响应中的Set-Cookie头内容如下:
Set-Cookie:
__session=; Path=/; Domain=mydomain.co.uk; Expires=Mon, 09 Dec 2024 22:33:54 GMT; Max-Age=432000; HttpOnly; Secure; SameSite=None
这个Cookie既不会出现在Chrome DevTools Application标签中account.mydomain.com的Cookie列表里,也不会在步骤3的GET请求中被携带——哪怕我在请求里明确加上了withCredentials: true。
以下是sessionLogin函数的核心代码:
res.setHeader('Access-Control-Allow-Credentials', 'true'); res.setHeader('Access-Control-Allow-Origin', 'https://account.mydomain.com'); if (req.method === 'OPTIONS') { // 处理OPTIONS请求 res.set('Access-Control-Allow-Methods', 'POST'); res.set('Access-Control-Allow-Headers', ['Authorization', 'Content-Type']); res.set('Access-Control-Max-Age', '3600'); res.status(204).send(''); return; } else { // 获取传入的ID token console.log(req.body.idToken); const idToken = req.body.idToken.toString(); const auth = getAuth(app); auth.verifyIdToken(idToken).then((decodedToken) => { // 设置会话有效期为5天 const expiresIn = 60 * 60 * 24 * 5 * 1000; auth .createSessionCookie(idToken, { expiresIn }) .then( (sessionCookie) => { // 配置会话Cookie的参数 const options = { maxAge: expiresIn, httpOnly: true, secure: true, sameSite: 'none' as const, domain: 'mydomain.com' }; res.setHeader('Cache-Control', 'private'); res.cookie('__session', sessionCookie, options); res.send('Cookie set'); return; }, (error) => { res.status(401).send('UNAUTHORIZED REQUEST!'); } ); }).catch((error) => { // 处理错误 console.error('Error creating sessionLogin:', error); res.status(401).send('UNAUTHORIZED REQUEST!'); }); } });
以下是Angular端发起请求的代码:
var responsePromise = new Promise<void>((resolve, reject) => { signInWithPopup(this.afAuth, provider) .then(async (result: UserCredential) => { return result.user.getIdToken().then(idToken => { var functionBaseUrl = 'https://account.mydomain.co.uk'; // 函数部署地址 var body = { idToken: idToken }; axios.post(functionBaseUrl + '/sessionLogin', body).then(function (response) { console.log(response); axios.get(functionBaseUrl + '/checkAuthStatus', { withCredentials: true, headers: { 'Content-Type': 'application/json' } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.error(error); }); }) .catch(function (error) { console.error(error); }); }); }) .catch((error) => { console.error(error); }); });
目前看起来没有CORS相关的错误,而且我自认为Cookie的配置是符合跨站Cookie要求的,但就是不知道哪里出了问题。有没有大佬能帮我找出问题所在,或者给我一些排查的方向?
备注:内容来源于stack exchange,提问作者GlennMoseley

