谷歌 OAuth API 获取用户的电子邮件地址?

我正在使用我自己的个人 Google 帐户玩 Google 的 OAuth 2.0游乐场,但是我似乎不能使用游乐场恢复我的 Gmail 地址。

我使用的范围是:

email profile https://www.googleapis.com/auth/plus.login

但当我调用 API 时:

https://www.googleapis.com/oauth2/v2/userinfo

我得到了用户的各种信息,如姓氏,名字,性别,照片等,但它不返回用户的电子邮件。

如何检索用户的电子邮件地址?我是否拥有错误的作用域,还是调用了错误的 API?我觉得这应该是非常简单的,但我一直试图找出这几个小时,我不能找到一个 API 和范围组合,始终提供用户的电子邮件地址。

123289 次浏览

更新: 2018年12月

12月20日,Google 宣布 Google + API 将于2019年3月关闭,间歇性故障将于2019年1月底开始。作为 不推荐使用 plus.people.get端点,并计划终止该端点的一部分。

userinfo端点不推荐使用(参见说明) ,并且应该提供假设的信息

  1. 请求 https://developers.google.com/identity/sign-in/web/devconsole-project作用域和
  2. 请求 email字段。

澄清: 2019年1月24日

Google记录在案表示 userinfo (v2)端点已被弃用,但后来将其更改为“已被弃用,但保持向后兼容”。

当前文档 讨论通过当前支持的 openid方法获取配置文件和电子邮件信息。这包括按照 OpenID Connect 的要求,使用在其 发现文件中指定的“ userinfo”端点。

目前,这个 URL 是 https://openidconnect.googleapis.com/v1/userinfo,但是这在过去已经改变了,而且 https://accounts.google.com/.well-known/openid-configuration的发现文档是 URL 使用的权威来源。

所以,我要说清楚:

  • 旧的用户信息 URL 是为了向后兼容而维护的
  • 新的 userinfo URL 可以在发现文档中找到

无论如何,任何东西(下面描述)的加号版本都是 已废弃并计划删除的

原始答案

在你正在做什么以及你如何尝试去做这件事的过程中有很多问题。

对于初学者来说,https://www.googleapis.com/oauth2/v2/userinfo端点已被弃用,并计划在2014年9月移除。它已经开始工作不一致-所以不要使用它。

正如@Abraham 指出的,您将在 https://www.googleapis.com/plus/v1/people/me使用 大家快走端点。这将给出包含地址数组的 电邮字段。在您的情况下,可能只有一个具有某种类型的“帐户”。

我来这里查看为什么我的服务器没有收到响应/oauth2/v2/userinfo API 调用的电子邮件。这只是一次,我看到这一点,它一直工作良好,在过去。

答案给出了很好的线索。在解决这个问题的同时,还有其他一些资源可以帮助解决这个问题。我仍然不确定是否总是期待电子邮件的回复是好的。因此-在代码中放入错误处理,以防电子邮件未被返回。

  1. 关于 转移到 google + 登录的 Googleapi 文档。
  2. Https://www.googleapis.com/auth/userinfo.email 瞄准镜
  3. 人力资源 文件
  4. 使用 谷歌开发者控制台将 google + api 添加到项目中。免费电话(配额)相当高(谷歌 + 登录 API 每天2000万)。
  5. 添加错误处理和服务器代码日志在情况下 api 返回没有电子邮件。在我的情况下,我只查看类型 = “帐户”电子邮件。

您需要添加 https://www.googleapis.com/auth/userinfo.email作用域或用它替换 https://www.googleapis.com/oauth2/v2/userinfo。如果使用的是它们提供的 HTML 示例,则可以列出用空格分隔的多个作用域。

<span
class="g-signin"
data-callback="signInCallback"
data-clientid="\{\{ plus_id }}"
data-cookiepolicy="single_host_origin"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-scope="https://www.googleapis.com/auth/plus.login
https://www.googleapis.com/auth/userinfo.email">
</span>

从2017年开始: 使用 email作用域,参见 授权 API 请求

电子邮件作用域等效并替换 Https://www.googleapis.com/auth/userinfo.email 范围。

enter image description here

Https://developers.google.com/gmail/api/v1/reference/users/getprofile

对于 gmailapi,将下面的代码添加到 nodejs 代码:

function getUsersEmail (auth) {
const gmail = google.gmail({version: 'v1', auth})
gmail.users.getProfile({
userId: 'me'
}, (err, {data}) => {
if (err) return console.log('The API returned an error: ' + err)
console.log(data.emailAddress)
})
}

Gmailapi: https://developers.google.com/gmail/api/guides/

这实际上是一个挑战,因为谷歌默认不提供电子邮件。你必须特别从 Google Plus 请求它。

const scope = [
'https://www.googleapis.com/auth/plus.me', // request access here
'https://www.googleapis.com/auth/userinfo.email',
];


auth.generateAuthUrl({
access_type: 'offline',
prompt: 'consent',
scope: scope,
});


const plus = google.plus({ version: 'v1', auth });
const me = await plus.people.get({ userId: 'me' });
const userEmail = me.data.emails[0].value;

在我写的这篇博文中有一个完整的版本: https://medium.com/@jackscott/how-to-use-google-auth-api-with-node-js-888304f7e3a0

对于使用 OAuth 2.0登录 Google 的用户,不需要单独请求获取用户的电子邮件。

当 Google 调用回调 URL 时,它在查询字符串中提供一个 code,您可以使用它来交换访问令牌和 ID 令牌。ID 令牌是一个 JWT,它包含有关用户的身份信息,其中包括电子邮件地址。

点击这里查看更多信息: https://developers.google.com/identity/protocols/oauth2/openid-connect

我一直在关注“囚徒”在上面的回答,它帮助了我... ... 直到我收到了来自 Google 开发者的电子邮件,内容是关于 Google + API 将如何在2019年3月7日关闭。

我四处寻找,并找到了这个解决方案,以获取电子邮件使用 id_token,这是返回当您授权与 email范围的应用程序在您的开发人员控制台。

来自 谷歌网站登录:

要验证 PHP 中的 ID 令牌,请使用 安装库(例如,使用 Composer) :

composer require google/apiclient

然后,调用 verifyIdToken ()函数:

require_once 'vendor/autoload.php';


// Get $id_token via HTTPS POST.


$client = new Google_Client(['client_id' => $CLIENT_ID]);  // Specify the CLIENT_ID of the app that accesses the backend
$payload = $client->verifyIdToken($id_token);
if ($payload) {
$userid = $payload['sub'];
// If request specified a G Suite domain:
//$domain = $payload['hd'];
} else {
// Invalid ID token
}

这将返回一个包含用户信息的数组,该数组还包含登录用户的电子邮件。希望这能帮到其他人。

在给定的范围内更改 authorizationRequest: scope=openid%20email%20profile并使用 userinfoapi.这个链接对我很有用

要检索电子邮件地址,您需要包括范围: “ https://www.googleapis.com/auth/userinfo.email" ,如本文档所述。如果在生成刷新令牌时包含此范围,则应该能够通过发出以下请求来获取正在进行身份验证的用户的电子邮件地址:

您可以使用自己的访问令牌调用它,然后将给出响应

https://www.googleapis.com/oauth2/v3/userinfo?access_token="YOUR_ACCESS_TOKEN"

反应会是这样的

{
"sub": "1057abc98136861333615xz",
"name": "My Name",
"given_name": "My",
"family_name": "Name",
"picture": "https://lh3.googleusercontent.com/a-/AOh14qiJarwP9rRw7IzxO40anYi4pTTAU_xseuRPFeeYFg",
"email": "MyName@gmail.com",
"email_verified": true,
"locale": "en"
}

或者简单地写一个函数

import requests
def get_user_email(access_token):
r = requests.get(
'https://www.googleapis.com/oauth2/v3/userinfo',
params={'access_token': access_token})
return r.json()

请看我对同一问题的回答: 如何获得电子邮件后使用谷歌 OAuth2在 C # ?

  • 显微镜变量中。使用值“ email”而不是 完整的 https 地址。Web 链接中的范围关键字由空格分隔。我用编写为 个人资料电子邮件 openid的作用域来解决您的问题。

使用 Google nodejs sdk:

const {google} = require('googleapis');


const oauth2Client = new google.auth.OAuth2(
googleClientIdPublic,
googleClientSecret,
googleRedirectUriPublic
);


//scope you need: https://www.googleapis.com/auth/userinfo.email


oauth2Client.setCredentials(tokens);


const googleAuth = google.oauth2({
version: "v2",
auth: oauth2Client,
});


const googleUserInfo = await googleAuth.userinfo.get();
const email = googleUserInfo.data.email;

更多信息

我建议使用以下最小代码,包括“ */userinfo.email”和“@google-cloud/local-auth”软件包:

const path = require('path');
const { google } = require('googleapis');
const { authenticate } = require('@google-cloud/local-auth');


const scope = [
'https://www.googleapis.com/auth/userinfo.email'
];
async function runSample() {
const auth = await authenticate({
keyfilePath: path.join(__dirname, 'oauth2.keys.json'),
scopes: scope
});
google.options({ auth });


const dat = await google.oauth2('v2').userinfo.get()
console.log(dat.data.email);
}


if (module === require.main) {
runSample().catch(console.error);
}
module.exports = runSample;