如何通过Firebase.signInWithPopup()、Vuejs和Google API解决由新的sameSite



错误体验的再现:我点击我的网络应用程序上的谷歌登录按钮,该按钮调用下面发布的login函数。它会提示用户使用谷歌帐户登录一个简单的弹出窗口。之后,在chrome控制台中,我看到以下Max堆栈错误:

RangeError: Maximum call stack size exceeded

我从firebase文档中复制了代码:https://firebase.google.com/docs/auth/web/google-signin

这是我决定改进的一个老项目的一部分。我清理了很多过时的vuetify代码等,并将本地数据转移到vuex。我也确保清理移动到vuex。vue方面应该没有任何问题。

我在谷歌上研究了一下RangeError,在这里,我发现在客户端使用firebase数据库的快照会导致这个错误。我的案子应该和那个案子不一样

我使用的谷歌帐户有一个现有的帐户(通过电子邮件帐户创建(,但这不应该是这个问题的原因,因为:

  1. 医生说谷歌和gmail账户将合并,不会出现任何错误iirc(我将firebase设置为每个电子邮件有一个账户(
  2. RangeError是在控制台上返回的错误消息。所以1。无关紧要

我确实阅读了Firebase参考页面,但这里没有讨论这个错误。

为了澄清,我没有在chrome中看到user/token set控制台消息,即promise只返回错误。

我很乐意收到任何关于这个问题的建议或解决方案。提前谢谢。

以下是我的登录功能:


login({ commit, dispatch }) {
return new Promise(function(resolve, reject) {
const provider = new firebase.auth.GoogleAuthProvider();
provider.addScope('email');
provider.addScope('profile');
firebase.auth().signInWithPopup(provider).then((result) => {
// The signed-in user info.
commit(
'setUser',
result.user,
);
console.log('user set');
// This gives you a Google Access Token. You can use it to access the Google API.
commit(
'setToken',
result.credential.accessToken,
);
console.log('token set');
return resolve();
// ...
}).catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
// The email of the user's account used.
const { email } = error;
// The firebase.auth.AuthCredential type that was used.
const { credential } = error;
console.error('error found during login');
console.error('---------error');
console.error(error);
console.error(errorCode);
console.error(errorMessage);
console.error(email);
console.error(credential);
console.error('error---------');
dispatch('snackbar/queueSnack',
{
color: 'error',
msg: errorMessage,
},
{ root: true });
return reject(error);
});
});
},

编辑:我做了登录操作返回承诺。这没用。

编辑2:错误实际上是由缺少"sameSite"属性引起的。我最初错过/忽略了警告:

A cookie associated with a cross-site resource at http://google.com/ was set without the `SameSite` attribute. It has been blocked, as Chrome now only delivers cookies with cross-site requests if they are set with `SameSite=None` and `Secure`. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/00000000 and https://www.chromestatus.com/feature/00000000000000.

根据https://github.com/firebase/firebase-js-sdk/issues/2284,问题在于Google API没有设置相同的Site属性。Firebase不处理任何cookie。我明天会调查的。

编辑3:我想禁用sameSite功能chrome://flags将解决此问题。它没有。在firebase github问题中分享如何禁用sameSite的评论已被删除。现在我将使用Google API登录Google。

请记住,gap只处理纯html/javascript。起初我很恼火vuejs只处理节点包,但最终我想起了public/index.html页面。我花了很长时间才记住这一点。因此,现在所有的脚本标签和元标签都可以去那里,应该很容易遵循谷歌API文档

此错误是由谷歌于2019年引入并于2020年7月左右实现的sameSite功能引起的。我读过一篇网上文章,但如果你感兴趣,可以在谷歌上搜索。我在github上查看了这个firebase问题页面,以了解更多上下文:https://github.com/firebase/firebase-js-sdk/issues/2284

因此,仅仅在通过键入chrome://flags获得的页面上禁用sameSite功能并不能解决这个问题。

解决方案是使用Google API的oAuth2登录到Google,然后使用凭据登录到firebase。按照以下步骤操作:https://developers.google.com/identity/sign-in/web/sign-in.记住在public/index.html页面上添加meta和script标记。这是一件很基本的事情,很容易忘记。我还阅读了如何在VueJS中实现Google登录API?并更新了我的代码,使其看起来像解决方案中的代码,以避免任何全局函数。不同之处在于:onsuccess属性不在div标记上,而是在mounted((期间调用的。

现在我们可以登录到Google API。不要忘记使用凭据登录firebase。请参阅手册签名部分:https://firebase.google.com/docs/auth/web/google-signin


public/index.html

<meta name="google-signin-client_id" content="${replace-with-CLIENT_ID}.apps.googleusercontent.com">
<script src="https://apis.google.com/js/platform.js" async defer></script>

@/components/Header.vue

<div id="google-signin-button"></div>
...
mounted() {
gapi.signin2.render('google-signin-button', {
onsuccess: this.onSignIn
})
},
methods: {
onSignIn: function (googleUser) {
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.
},
},

最新更新