【发布时间】:2019-12-06 18:42:12
【问题描述】:
我正在为 firebase 平台的用户实现 oAuth 登录。
一切正常,除非用户已 禁用跨域cookie。
这就是我所做的。
- 从我的域/应用程序中,用户被重定向到云功能。
- can 函数设置
statecookie 并将用户重定向到 oAuth 提供程序。 - 用户登录到 oAuth 提供程序并被重定向回另一个函数以获取代码等。这就是问题
如果用户在浏览器中禁用了跨域方 cookie,则在上面的第 3 步中,该函数无法读取任何 cookie。 这两个函数都在同一个域中,如下面的屏幕截图所示。
有什么办法可以解决这个问题吗?我的方法做错了吗?
我不明白为什么这两个函数被视为跨域。
更新以包含更多信息
请求:
Request URL: https://europe-west2-quantified-self-io.cloudfunctions.net/authRedirect
Request Method: GET
Status Code: 302
Remote Address: [2a00:1450:4007:811::200e]:443
Referrer Policy: no-referrer-when-downgrade
请求标头
:authority: europe-west2-quantified-self-io.cloudfunctions.net
:method: GET
:path: /authRedirect
:scheme: https
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
accept-encoding: gzip, deflate, br
accept-language: en-GB,en-US;q=0.9,en;q=0.8
cookie: signInWithService=false; state=877798d3672e7d6fa9588b03f1e26794f4ede3a0
dnt: 1
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
响应标头
alt-svc: quic=":443"; ma=2592000; v="46,43,39"
cache-control: private
content-encoding: gzip
content-length: 218
content-type: text/html; charset=utf-8
date: Sat, 03 Aug 2019 08:55:18 GMT
function-execution-id: c8rjc7xnvoy8
location: https://cloudapi-oauth.suunto.com/oauth/authorize?response_type=code&client_id=xxx&redirect_uri=&scope=workout&state=1c8073866d1ffaacf2d4709090ad099872718afa
server: Google Frontend
set-cookie: state=1c8073866d1ffaacf2d4709090ad099872718afa; Max-Age=3600; Path=/; Expires=Sat, 03 Aug 2019 09:55:18 GMT; HttpOnly; Secure
set-cookie: signInWithService=false; Max-Age=3600; Path=/; Expires=Sat, 03 Aug 2019 09:55:18 GMT; HttpOnly; Secure
status: 302
vary: Accept
x-cloud-trace-context: 99a93680a17770f848f200a9e729b122;o=1
x-powered-by: Express
之后,一旦用户从服务返回,他对解析 cookie 的代码(或处理它的函数)进行了身份验证:
export const authToken = functions.region('europe-west2').https.onRequest(async (req, res) => {
const oauth2 = suuntoAppAuth();
cookieParser()(req, res, async () => {
try {
const currentDate = new Date();
const signInWithService = req.cookies.signInWithService === 'true';
console.log('Should sign in:', signInWithService);
console.log('Received verification state:', req.cookies.state);
console.log('Received state:', req.query.state);
if (!req.cookies.state) {
throw new Error('State cookie not set or expired. Maybe you took too long to authorize. Please try again.');
} else if (req.cookies.state !== req.query.state) {
throw new Error('State validation failed');
}
console.log('Received auth code:', req.query.code);
const results = await oauth2.authorizationCode.getToken({
code: req.query.code,
redirect_uri: determineRedirectURI(req), // @todo fix,
});
// console.log('Auth code exchange result received:', results);
// We have an access token and the user identity now.
const accessToken = results.access_token;
const suuntoAppUserName = results.user;
// Create a Firebase account and get the Custom Auth Token.
let firebaseToken;
if (signInWithService) {
firebaseToken = await createFirebaseAccount(suuntoAppUserName, accessToken);
}
return res.jsonp({
firebaseAuthToken: firebaseToken,
serviceAuthResponse: <ServiceTokenInterface>{
accessToken: results.access_token,
refreshToken: results.refresh_token,
tokenType: results.token_type,
expiresAt: currentDate.getTime() + (results.expires_in * 1000),
scope: results.scope,
userName: results.user,
dateCreated: currentDate.getTime(),
dateRefreshed: currentDate.getTime(),
},
serviceName: ServiceNames.SuuntoApp
});
} catch (error) {
return res.jsonp({
error: error.toString(),
});
}
});
});
上面的代码没有找到名称为state的cookie
所以这里失败了
if (!req.cookies.state) {
throw new Error('State cookie not set or expired. Maybe you took too long to authorize. Please try again.');
} else if (req.cookies.state !== req.query.state) {
throw new Error('State validation failed');
}
在这里做了更多的搜索是一些更多的信息。
我基于https://github.com/firebase/functions-samples/tree/master/instagram-auth的例子
看起来其他用户也遇到了同样的问题https://github.com/firebase/functions-samples/issues/569
我也打开了这个问题https://github.com/firebase/firebase-functions/issues/544
【问题讨论】:
-
我对“未禁用跨域 cookie”这句话特别感到困惑。 Cookie 本质上不能跨域共享。这个答案可能会有所帮助,尽管它可能只与 Firebase 函数有关:stackoverflow.com/a/44935288
-
@Grant Timmerman 我是说当用户启用跨域 cookie 时,一切正常。如果您看到我的函数在同一个域上,那么我不明白为什么将它们(保存 cookie 时)视为跨域。看一看。两个函数都在同一个域上。一个设置一个cookie,另一个读取它。但是当用户禁用了跨域 cookie 时,第二个函数无法读取任何内容。
-
@Grant Timmerman。抱歉,这是一个错字并已修复。
-
@JimmyKane,你能从 Inspector 选项卡中显示 cookie 吗?还要确保 cookie 是用
/生成的,否则如果它是用路径/authRedirect或其他东西生成的,它将不起作用。我建议您更新问题中的Set-Cookiecookie 响应,同时确保也具有正确的域 -
@TarunLalwani 我按照你的要求添加了所有信息。感谢您的宝贵时间
标签: firebase oauth google-cloud-functions cross-domain