С помощью библиотеки google oauth2 я могу успешно аутентифицировать пользователя при их первом проходе, получить их токен refre sh и первый токен доступа. Пока токен не истечет, все работает как положено.
Однако, когда срок действия токена доступа истекает, мне нужно получить новый токен доступа и сохранить эти токены в моем хранилище данных, используя существующий токен refre sh. Я знаю, что в документации указано, что токены должны повторно загружаться, когда срок их действия истекает, но поскольку я создаю нового клиента для каждого вызова (чтобы гарантировать, что токены не используются повторно между пользователями), я думаю, что клиент разрушается до того, как токен получает возможность обновить сам sh.
Проверяя, что делает библиотека, вызывая фактический API Google, я должен иметь возможность получить новые токены доступа, вызвав метод client.refreshAccessToken()
, ответ на этот вызов дает мне ошибка invalid_grant
Bad Request
. Я сравнил фактический запрос api, который этот метод делает, с запросом на google oauth2 Playground , и два вызова идентичны, хотя их призыв к обновлению их токенов работает, а мой - нет.
Прикреплено это мой код в его нынешнем виде. Пожалуйста, пришлите помощь - у меня не осталось волос, которые нужно выдергивать!
const { google } = require('googleapis')
const scopes = [
'https://www.googleapis.com/auth/spreadsheets.readonly',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/drive.readonly'
]
module.exports = (env, mongo) => {
const getBaseClient = () => {
const { OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, OAUTH_CALLBACK_URL } = env.credentials
return new google.auth.OAuth2(
OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, OAUTH_CALLBACK_URL
)
}
const getNewAccessTokens = async (authId, refreshToken) => {
const { tokens } = await getBaseClient().getToken(refreshToken)
await mongo.setAccessTokensForAuthUser(authId, { ...tokens, refresh_token: refreshToken })
return tokens
}
const getAuthedClient = async (authId) => {
let tokens = await mongo.getAccessTokensForAuthUser(authId)
if (!tokens.access_token) {
tokens = await getNewAccessTokens(authId, tokens.refresh_token)
}
const client = getBaseClient()
client.setCredentials(tokens)
if (client.isTokenExpiring()) {
const { credentials } = await client.refreshAccessToken()
tokens = { ...credentials, refresh_token: tokens.refreshToken }
await mongo.setAccessTokensForAuthUser(authId, tokens)
client.setCredentials(tokens)
}
return client
}
const generateAuthUrl = (userId) => {
return getBaseClient().generateAuthUrl({
access_type: 'offline',
scope: scopes,
state: `userId=${userId}`
})
}
const getUserInfo = async (authId) => {
const auth = await getAuthedClient(authId)
return google.oauth2({ version: 'v2', auth }).userinfo.get({})
}
const listSheets = async (authId) => {
const auth = await getAuthedClient(authId)
let nextPageToken = null
let results = []
do {
const { data } = await google
.drive({ version: 'v3', auth })
.files.list({
q: 'mimeType = \'application/vnd.google-apps.spreadsheet\'',
includeItemsFromAllDrives: true,
supportsAllDrives: true,
corpora: 'user',
orderBy: 'name',
pageToken: nextPageToken
})
nextPageToken = data.nextPageToken
results = results.concat(data.files)
} while (nextPageToken)
return results
}
return {
generateAuthUrl,
getUserInfo,
listSheets
}
}