从 Firebase 函数访问 Google 站点验证 API
Accessing Google Site Verification API from a Firebase function
我正在尝试使用 Node.js 的 Firebase 函数使用 Google Site Verification API。
google-api-nodejs-client 存储库中可用的 README Github 建议使用默认值应用程序方法,而不是手动创建 OAuth2 客户端、JWT 客户端或计算客户端。
我写了以下示例,我尝试在本地(模拟函数环境)和远程在 Firebase 函数上 运行:
const google = require('googleapis');
google.auth.getApplicationDefault(function (err, authClient, projectId) {
if (err) {
console.log('Authentication failed because of ', err);
return;
}
if (authClient.createScopedRequired && authClient.createScopedRequired()) {
authClient = authClient.createScoped([
'https://www.googleapis.com/auth/siteverification'
]);
}
const siteVerification = google.siteVerification({
version: 'v1',
auth: authClient
});
siteVerification.webResource.get({
id: 'test.com'
}, {}, function (err, data) {
if (err) {
console.log('siteVerification get error:', err);
} else {
console.log('siteVerification result:', data);
}
});
});
在这两种情况下,在执行时,我都会收到以下错误:
siteVerification get error: { Error: A Forbidden error was returned while attempting to retrieve an access token for the Compute Engine built-in service account. This may be because the Compute Engine instance does not have the correct permission scopes specified. Insufficient Permission
at Request._callback (/user_code/node_modules/googleapis/node_modules/google-auth-library/lib/transporters.js:85:15)
at Request.self.callback (/user_code/node_modules/googleapis/node_modules/request/request.js:188:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/user_code/node_modules/googleapis/node_modules/request/request.js:1171:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at IncomingMessage.<anonymous> (/user_code/node_modules/googleapis/node_modules/request/request.js:1091:12)
at IncomingMessage.g (events.js:292:16)
at emitNone (events.js:91:20)
code: 403,
errors:
[ { domain: 'global',
reason: 'insufficientPermissions',
message: 'Insufficient Permission' } ] }
请注意,已为与 Firebase 关联的 Cloud 项目启用站点验证 API。
更新:
创建具有项目所有者角色的服务帐户并使用 JWT 方法进行身份验证会导致以下权限错误:
info: siteVerification get error: { Error: You are not an owner of this site.
at Request._callback
...
at IncomingMessage.g (events.js:292:16)
at emitNone (events.js:91:20)
code: 403,
errors:
[ { domain: 'global',
reason: 'forbidden',
message: 'You are not an owner of this site.' } ] }
此错误是因为我使用 API 资源管理器和这个 returns 详细信息使用相同 ID 调用了一个我知道拥有的站点的 ID。
不知道是不是一定要在Google云控制台配置一些权限,或者认证方式应该不一样。我有一种感觉,只允许具有手动用户身份验证的 OAuth 2.0 客户端...
欢迎帮助。
站点验证 API 仅允许使用手动身份验证的 OAuth 2.0。入门文档包含与此相关的几行:
Your application must use OAuth 2.0 to authorize requests. No other
authorization protocols are supported. If your application uses Google
Sign-In, some aspects of authorization are handled for you.
作为解决方法,我生成了一个访问令牌及其关联的刷新令牌。一旦你拥有了两者,你就可以在你的服务器功能上使用它们。如果您使用官方 Google NodeJS client 进行站点验证 API,则会为您管理访问令牌刷新。否则,您必须在访问令牌过期时刷新它。
以下是您可以用来轻松创建访问令牌的 Firebase 函数。
function oauth2Client() {
return new google.auth.OAuth2(
config.site_verification_api.client_id,
config.site_verification_api.client_secret,
'http://localhost:8080/oauth'
);
}
exports.oauth2GetAuthorizationCode = functions.https.onRequest((req, res) => {
const client = oauth2Client();
const url = client.generateAuthUrl({
access_type: 'offline',
scope: [
'https://www.googleapis.com/auth/siteverification'
]
});
res.status(200).send({url: url});
});
exports.oauth2GetAccessToken = functions.https.onRequest((req, res) => {
const client = oauth2Client();
const code = req.query.code;
client.getToken(code, (err, tokens) => {
if (!err) {
res.status(200).send({tokens});
} else {
console.error('Error while getting access token:', err);
res.sendStatus(500);
}
});
});
当您调用与 oauth2GetAuthorizationCode 关联的 HTTP 端点时,URL 被 returned。在您的浏览器上打开此 URL。这将重定向到包含授权代码作为查询参数的本地 URL。获取此参数并调用与 oauth2GetAccessToken 关联的第二个 HTTP 端点。最后一次调用应该 return 您的访问和刷新令牌。
获得这两个令牌后,您可以将它们存储在您的 Firebase 环境配置中(连同您的客户端 ID 和密码)并访问站点验证 API,如下所示:
function oauth2ClientWithCredentials() {
const client = oauth2Client();
client.setCredentials({
access_token: config.site_verification_api.access_token,
refresh_token: config.site_verification_api.refresh_token
});
return client;
}
function invokeSiteVerificationApi() {
const client = oauth2ClientWithCredentials();
const siteVerification = google.siteVerification({
version: 'v1',
auth: client
});
siteVerification.webResource.get({
id: 'dns%3A%2F%2F' + domain
}, null, (err, result) => {
// ...
});
}
我正在尝试使用 Node.js 的 Firebase 函数使用 Google Site Verification API。
google-api-nodejs-client 存储库中可用的 README Github 建议使用默认值应用程序方法,而不是手动创建 OAuth2 客户端、JWT 客户端或计算客户端。
我写了以下示例,我尝试在本地(模拟函数环境)和远程在 Firebase 函数上 运行:
const google = require('googleapis');
google.auth.getApplicationDefault(function (err, authClient, projectId) {
if (err) {
console.log('Authentication failed because of ', err);
return;
}
if (authClient.createScopedRequired && authClient.createScopedRequired()) {
authClient = authClient.createScoped([
'https://www.googleapis.com/auth/siteverification'
]);
}
const siteVerification = google.siteVerification({
version: 'v1',
auth: authClient
});
siteVerification.webResource.get({
id: 'test.com'
}, {}, function (err, data) {
if (err) {
console.log('siteVerification get error:', err);
} else {
console.log('siteVerification result:', data);
}
});
});
在这两种情况下,在执行时,我都会收到以下错误:
siteVerification get error: { Error: A Forbidden error was returned while attempting to retrieve an access token for the Compute Engine built-in service account. This may be because the Compute Engine instance does not have the correct permission scopes specified. Insufficient Permission
at Request._callback (/user_code/node_modules/googleapis/node_modules/google-auth-library/lib/transporters.js:85:15)
at Request.self.callback (/user_code/node_modules/googleapis/node_modules/request/request.js:188:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/user_code/node_modules/googleapis/node_modules/request/request.js:1171:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at IncomingMessage.<anonymous> (/user_code/node_modules/googleapis/node_modules/request/request.js:1091:12)
at IncomingMessage.g (events.js:292:16)
at emitNone (events.js:91:20)
code: 403,
errors:
[ { domain: 'global',
reason: 'insufficientPermissions',
message: 'Insufficient Permission' } ] }
请注意,已为与 Firebase 关联的 Cloud 项目启用站点验证 API。
更新:
创建具有项目所有者角色的服务帐户并使用 JWT 方法进行身份验证会导致以下权限错误:
info: siteVerification get error: { Error: You are not an owner of this site.
at Request._callback
...
at IncomingMessage.g (events.js:292:16)
at emitNone (events.js:91:20)
code: 403,
errors:
[ { domain: 'global',
reason: 'forbidden',
message: 'You are not an owner of this site.' } ] }
此错误是因为我使用 API 资源管理器和这个 returns 详细信息使用相同 ID 调用了一个我知道拥有的站点的 ID。
不知道是不是一定要在Google云控制台配置一些权限,或者认证方式应该不一样。我有一种感觉,只允许具有手动用户身份验证的 OAuth 2.0 客户端...
欢迎帮助。
站点验证 API 仅允许使用手动身份验证的 OAuth 2.0。入门文档包含与此相关的几行:
Your application must use OAuth 2.0 to authorize requests. No other authorization protocols are supported. If your application uses Google Sign-In, some aspects of authorization are handled for you.
作为解决方法,我生成了一个访问令牌及其关联的刷新令牌。一旦你拥有了两者,你就可以在你的服务器功能上使用它们。如果您使用官方 Google NodeJS client 进行站点验证 API,则会为您管理访问令牌刷新。否则,您必须在访问令牌过期时刷新它。
以下是您可以用来轻松创建访问令牌的 Firebase 函数。
function oauth2Client() {
return new google.auth.OAuth2(
config.site_verification_api.client_id,
config.site_verification_api.client_secret,
'http://localhost:8080/oauth'
);
}
exports.oauth2GetAuthorizationCode = functions.https.onRequest((req, res) => {
const client = oauth2Client();
const url = client.generateAuthUrl({
access_type: 'offline',
scope: [
'https://www.googleapis.com/auth/siteverification'
]
});
res.status(200).send({url: url});
});
exports.oauth2GetAccessToken = functions.https.onRequest((req, res) => {
const client = oauth2Client();
const code = req.query.code;
client.getToken(code, (err, tokens) => {
if (!err) {
res.status(200).send({tokens});
} else {
console.error('Error while getting access token:', err);
res.sendStatus(500);
}
});
});
当您调用与 oauth2GetAuthorizationCode 关联的 HTTP 端点时,URL 被 returned。在您的浏览器上打开此 URL。这将重定向到包含授权代码作为查询参数的本地 URL。获取此参数并调用与 oauth2GetAccessToken 关联的第二个 HTTP 端点。最后一次调用应该 return 您的访问和刷新令牌。
获得这两个令牌后,您可以将它们存储在您的 Firebase 环境配置中(连同您的客户端 ID 和密码)并访问站点验证 API,如下所示:
function oauth2ClientWithCredentials() {
const client = oauth2Client();
client.setCredentials({
access_token: config.site_verification_api.access_token,
refresh_token: config.site_verification_api.refresh_token
});
return client;
}
function invokeSiteVerificationApi() {
const client = oauth2ClientWithCredentials();
const siteVerification = google.siteVerification({
version: 'v1',
auth: client
});
siteVerification.webResource.get({
id: 'dns%3A%2F%2F' + domain
}, null, (err, result) => {
// ...
});
}