代表最终用户查询 Google Search Console:invalid_grant
Querying Google Search Console on behalf of end-user: invalid_grant
我正在尝试代表我的用户查询 Google Search Console,使用 Google 进行身份验证,具有 GSC 所需的范围。
我在 Firebase 身份验证中启用了 Google 登录,在我的脚本中使用客户端 ID 和密码。此外,我已经使用测试电子邮件、授权域和范围“https://www.googleapis.com/auth/webmasters”、“https://www.googleapis 设置了我的同意屏幕。 com/auth/webmasters.只读".
这是我的代码
React + Firebase 客户端
请注意,用户已通过电子邮件进行身份验证(我们将电子邮件帐户与 Google 帐户相关联)。
import {Grid, IconButton, List,
ListItem, Tooltip, Typography} from "@mui/material";
import {GoogleAuthProvider, linkWithPopup,
unlink} from "firebase/auth";
import React, {useState} from "react";
import {
useUser,
} from "reactfire";
import {defaultErrorMessage} from "../../utils/constants";
import {log} from "../../utils/logs";
import {LoadingButton} from "@mui/lab";
import {Check, Clear} from "@mui/icons-material";
const GoogleSignIn = () => {
const {data: user} = useUser();
console.log("user", user);
const onGoogleSearchConsole = async () => {
const provider = new GoogleAuthProvider();
provider.addScope("https://www.googleapis.com/auth/webmasters");
provider.addScope("https://www.googleapis.com/auth/webmasters.readonly");
provider.setCustomParameters({
access_type: "offline",
});
linkWithPopup(user!, provider).then((result) => {
console.log("onGoogleSearchConsole result", result);
}).catch((error) => {
console.log("onGoogleSearchConsole failed", error);
});
};
const onDisconnectGoogleSearchConsole = () => {
unlink(user!, "google.com").then(() => {
// Auth provider unlinked from account
console.log("onDisconnectGoogleSearchConsole");
}).catch((error) => {
console.log("onDisconnectGoogleSearchConsole failed", error);
});
};
return (
<React.Fragment>
<Grid
container
direction="column"
>
<List>
<ListItem
secondaryAction={
user &&
user?.providerData.some((e) => e.providerId === "google.com") &&
<Tooltip title="Unlink Google Search Console">
<IconButton
onClick={onDisconnectGoogleSearchConsole}
>
<Clear />
</IconButton>
</Tooltip>
}
>
<Button
color="primary"
variant="contained"
onClick={onGoogleSearchConsole}
startIcon={
user?.providerData.some((e) => e.providerId === "google.com") &&
<Check/>
}
disabled={
!user ||
user?.providerData.some((e) => e.providerId === "google.com")
}
>
Google Search Console
</Button>
</ListItem>
</List>
</Grid>
</React.Fragment>
);
};
export default GoogleSignIn;
尝试查询 GSC 的脚本。
#!/usr/bin/python
from googleapiclient.discovery import build
import google.oauth2.credentials
CLIENT_ID = 'MY_CLIENT_ID'
CLIENT_SECRET = 'MY_CLIENT_SECRET'
# Here I currently copy paste my access token and refresh token from client
at = "MY_ACCESS_TOKEN_COPY_PASTED_FROM_CLIENT"
rt = "MY_REFRESH_TOKEN_COPY_PASTED_FROM_CLIENT"
tu = "https://oauth2.googleapis.com/token"
scopes = [
"https://www.googleapis.com/auth/webmasters",
"https://www.googleapis.com/auth/webmasters.readonly",
]
c = google.oauth2.credentials.Credentials(
None, # seems that we can just use refresh token, otherwise still fail with "at"
scopes=scopes,
refresh_token=rt,
token_uri=tu,
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
)
# v3 or v1 both fail
# webmasters = build('webmasters', 'v3', credentials=c)
webmasters = build('searchconsole', 'v1', credentials=c)
# FAIL HERE
site_list = webmasters.sites().list().execute()
print("site_list", site_list)
错误是
google.auth.exceptions.RefreshError: ('invalid_grant: Bad Request', {'error': 'invalid_grant', 'error_description': 'Bad Request'})
哪个应该说令牌有问题?我尝试了所有解决方案
invalid_grant trying to get oAuth token from google 没有更好的结果
我在这里 https://developers.google.com/webmaster-tools/v1/quickstart/quickstart-python 尝试了示例(它似乎只适用于桌面 oauth 客户端 ID),并且它有效,不知何故,我试图调整他们的代码,但这是一种不同的情况。
我做错了什么吗?
非常感谢:).
我使用“gapi”(Google JS 客户端)代替 Firebase 解决了这个问题。
为了简单起见,我使用了 https://github.com/ph-fritsche/react-gapi。
// component ...
const scopes = [
"https://www.googleapis.com/auth/webmasters",
"https://www.googleapis.com/auth/webmasters.readonly",
];
const gapi = useGoogleApi({
scopes: scopes,
});
const gAuth = gapi?.auth2?.getAuthInstance();
gAuth?.currentUser.listen((e) => console.log("user", e));
const onGoogleSearchConsole = async () => {
const refreshToken = await gAuth!.grantOfflineAccess();
console.log("refresh token", refreshToken);
};
const onDisconnectGoogleSearchConsole = () => {
gAuth!.currentUser.get().disconnect();
};
// ...
我正在尝试代表我的用户查询 Google Search Console,使用 Google 进行身份验证,具有 GSC 所需的范围。
我在 Firebase 身份验证中启用了 Google 登录,在我的脚本中使用客户端 ID 和密码。此外,我已经使用测试电子邮件、授权域和范围“https://www.googleapis.com/auth/webmasters”、“https://www.googleapis 设置了我的同意屏幕。 com/auth/webmasters.只读".
这是我的代码
React + Firebase 客户端
请注意,用户已通过电子邮件进行身份验证(我们将电子邮件帐户与 Google 帐户相关联)。
import {Grid, IconButton, List,
ListItem, Tooltip, Typography} from "@mui/material";
import {GoogleAuthProvider, linkWithPopup,
unlink} from "firebase/auth";
import React, {useState} from "react";
import {
useUser,
} from "reactfire";
import {defaultErrorMessage} from "../../utils/constants";
import {log} from "../../utils/logs";
import {LoadingButton} from "@mui/lab";
import {Check, Clear} from "@mui/icons-material";
const GoogleSignIn = () => {
const {data: user} = useUser();
console.log("user", user);
const onGoogleSearchConsole = async () => {
const provider = new GoogleAuthProvider();
provider.addScope("https://www.googleapis.com/auth/webmasters");
provider.addScope("https://www.googleapis.com/auth/webmasters.readonly");
provider.setCustomParameters({
access_type: "offline",
});
linkWithPopup(user!, provider).then((result) => {
console.log("onGoogleSearchConsole result", result);
}).catch((error) => {
console.log("onGoogleSearchConsole failed", error);
});
};
const onDisconnectGoogleSearchConsole = () => {
unlink(user!, "google.com").then(() => {
// Auth provider unlinked from account
console.log("onDisconnectGoogleSearchConsole");
}).catch((error) => {
console.log("onDisconnectGoogleSearchConsole failed", error);
});
};
return (
<React.Fragment>
<Grid
container
direction="column"
>
<List>
<ListItem
secondaryAction={
user &&
user?.providerData.some((e) => e.providerId === "google.com") &&
<Tooltip title="Unlink Google Search Console">
<IconButton
onClick={onDisconnectGoogleSearchConsole}
>
<Clear />
</IconButton>
</Tooltip>
}
>
<Button
color="primary"
variant="contained"
onClick={onGoogleSearchConsole}
startIcon={
user?.providerData.some((e) => e.providerId === "google.com") &&
<Check/>
}
disabled={
!user ||
user?.providerData.some((e) => e.providerId === "google.com")
}
>
Google Search Console
</Button>
</ListItem>
</List>
</Grid>
</React.Fragment>
);
};
export default GoogleSignIn;
尝试查询 GSC 的脚本。
#!/usr/bin/python
from googleapiclient.discovery import build
import google.oauth2.credentials
CLIENT_ID = 'MY_CLIENT_ID'
CLIENT_SECRET = 'MY_CLIENT_SECRET'
# Here I currently copy paste my access token and refresh token from client
at = "MY_ACCESS_TOKEN_COPY_PASTED_FROM_CLIENT"
rt = "MY_REFRESH_TOKEN_COPY_PASTED_FROM_CLIENT"
tu = "https://oauth2.googleapis.com/token"
scopes = [
"https://www.googleapis.com/auth/webmasters",
"https://www.googleapis.com/auth/webmasters.readonly",
]
c = google.oauth2.credentials.Credentials(
None, # seems that we can just use refresh token, otherwise still fail with "at"
scopes=scopes,
refresh_token=rt,
token_uri=tu,
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
)
# v3 or v1 both fail
# webmasters = build('webmasters', 'v3', credentials=c)
webmasters = build('searchconsole', 'v1', credentials=c)
# FAIL HERE
site_list = webmasters.sites().list().execute()
print("site_list", site_list)
错误是
google.auth.exceptions.RefreshError: ('invalid_grant: Bad Request', {'error': 'invalid_grant', 'error_description': 'Bad Request'})
哪个应该说令牌有问题?我尝试了所有解决方案 invalid_grant trying to get oAuth token from google 没有更好的结果
我在这里 https://developers.google.com/webmaster-tools/v1/quickstart/quickstart-python 尝试了示例(它似乎只适用于桌面 oauth 客户端 ID),并且它有效,不知何故,我试图调整他们的代码,但这是一种不同的情况。
我做错了什么吗? 非常感谢:).
我使用“gapi”(Google JS 客户端)代替 Firebase 解决了这个问题。 为了简单起见,我使用了 https://github.com/ph-fritsche/react-gapi。
// component ...
const scopes = [
"https://www.googleapis.com/auth/webmasters",
"https://www.googleapis.com/auth/webmasters.readonly",
];
const gapi = useGoogleApi({
scopes: scopes,
});
const gAuth = gapi?.auth2?.getAuthInstance();
gAuth?.currentUser.listen((e) => console.log("user", e));
const onGoogleSearchConsole = async () => {
const refreshToken = await gAuth!.grantOfflineAccess();
console.log("refresh token", refreshToken);
};
const onDisconnectGoogleSearchConsole = () => {
gAuth!.currentUser.get().disconnect();
};
// ...