【发布时间】:2020-11-05 09:34:32
【问题描述】:
我正在将 Meteor 应用程序与 Google 的 One Tap 集成。尝试使用 Meteor 的 loginWithGoogle 来让用户保存到 Meteor Accounts(内置在 Meteor.js 中)。其复杂性在于
One-Tap 库并非旨在授权用户(即生产 Access Token),仅用于验证用户身份
因此,我必须做的是使用 Google Api 或 gapi 对用户进行身份验证,以检索必要的 access_token 和 id_token。支持this post。
到目前为止,我得到的如下:
HTML
<div data-prompt_parent_id="g_id_onload" style={{ position: "absolute", top: "5em", right: "1em" }} id="g_id_onload"></div>
客户端
google.accounts.id.initialize({
prompt_parent_id: "g_id_onload",
client_id: "42424242-example42.apps.googleusercontent.com",
auto_select: false,
callback: handleCredentialResponse
});
const handleCredentialResponse = async oneTapResponse => {
// see the SERVER SIDE code, which is where validation of One Tap response happens
Meteor.call("verifyOneTap", oneTapResponse.credential, oneTapResponse.clientId, (error, result) => {
if (error) {
console.log(error);
}
if (result) {
// Initialize the JavaScript client library.
gapi.load("auth2", function() {
// Ready. Make a call to gapi.auth2.init or some other API
gapi.auth2.authorize(
{
client_id: oneTapResponse.clientId,
scope: "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
response_type: "code token id_token",
prompt: "none",
// this is the actual email address of user, example@gmail.com, passed back from the server where we validated the One Tap event...
login_hint: result.email
},
function(result, error) {
if (error) {
// An error happened.
console.log(error);
return;
}
//these are the authentication tokens taht are so difficult to capture...
let theAccessToken = result.access_token;
let theIdToken = result.id_token;
//*********************************
//this is the part that doesn't work
//trying to get it to create the account without another Google prompt...
Meteor.loginWithGoogle({ accessToken: theAccessToken, idToken: theIdToken, prompt: "none" }, function(err, res) {
if (err) {
console.log(err)
}
});
//*********************************
}
);
});
}
});
};
google.accounts.id.prompt(notification => {
//this just tells you when things go wrong...
console.log(notification);
});
服务器端
const { OAuth2Client } = require("google-auth-library");
const clientOA2 = new OAuth2Client("42424242-example42.apps.googleusercontent.com");
// the token and clientId are returned from One Tap in an object, are credential (token) and clientId (clientId)
verifyOneTap: async (token, clientId) => {
const ticket = await clientOA2.verifyIdToken({
idToken: token,
audience: clientId // Specify the CLIENT_ID of the app that accesses the backend
// Or, if multiple clients access the backend:
//[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
});
const payload = await ticket.getPayload();
//perform validation here so you don't get hacked...
return payload;
// If request specified a G Suite domain:
// const domain = payload['hd'];
}
尝试在客户端/服务器上以不同的方式编写此内容,以及考虑解决此问题的方法并仅注册 Meteor 的Accounts.createUser,但这并不理想。我传递给loginWithGoogle 的[options] 有什么问题?我认为accessToken 和idToken 就足够了……
发生的情况是,在登录时,它确实让我通过 Google One Tap 的第一阶段登录,但后来我输入Meteor.loginWithGoogle 的选项不知何故无法被识别:
这可行(一步流程的第一步)=>
但随后它再次要求登录:|
loginWithGoogle 上的 documentation 声明格式通常为:
Meteor.loginWith<ExternalService>([options], [callback])
关于loginWithGoogle:
Google 的附加 URI 参数
必填: client_id、nonce、response_type、redirect_uri、范围
可选: access_type、display、hd、include_granted_scopes、login_hint、prompt
不幸的是,它显然无法识别我正在传递的 [options] 中的某些内容,否则它会将用户保存到 MongoDB,而它没有这样做。
【问题讨论】:
标签: node.js google-signin google-authentication meteor-accounts google-one-tap