R语言 使用Google API刷新令牌

ttisahbt  于 2023-06-19  发布在  Go
关注(0)|答案(2)|浏览(118)

我在一个应用程序中工作,它不断从GoogleFit API中提取一些与一些用户的步骤相关的信息。
我正在使用httr包进行身份验证:

library(httr)
library(RGoogleFit)

google_client <- gargle::gargle_oauth_client_from_json("client_secret_xxx.apps.googleusercontent.com.json")

myapp <- httr::oauth_app(appname = "myapp", key = google_client$id, secret = google_client$secret)

# Opens a web browser for Google Authentication
google_token <- oauth2.0_token(oauth_endpoints("google"), myapp,
                               scope = "https://www.googleapis.com/auth/fitness.activity.read",
                               cache = "httr-oauth")

我得到了访问令牌和刷新令牌:

> google_token$credentials
$access_token
[1] "ya29.a0AWxxxxxxxxxxxxxxxx"

$expires_in
[1] 3599

$refresh_token
[1] "1//03RHPxxxxxxxxxxxxxxxxx"

$scope
[1] "https://www.googleapis.com/auth/fitness.activity.read"

$token_type
[1] "Bearer"

我需要不断地从API中提取数据。因此,在访问令牌到期后(一小时),我需要使用刷新令牌。
出于测试目的,我使用了一个while(true)循环来查看一个小时后进程是否停止提取数据。

currentToken<-google_token$credentials$access_token
labelToken="current Token"

while(TRUE){
  
  n<-GetFitDataset(currentToken,"derived:com.google.step_count.delta:com.google.android.gms:estimated_steps",as.POSIXct(as.Date("2023-05-01")),as.POSIXct(as.Date("2023-06-04")))
  
  # When the token expires, the data is not extracted and n$point is null
  if (is.null(n$point)) {
    currentToken<-google_token$credentials$refresh_token
    labelToken="refresh Token"
  }
  
  print(paste0(Sys.time()," ",labelToken," nrow ",nrow(n$point)))
  Sys.sleep(60)
}

..一小时后刷新令牌似乎未被识别为有效
经过一番调查,我发现了这个帖子:

然而,我没有找到足够的例子来说明如何使用httr::VERB
我如何使用它来解决我的问题?
谢谢!

w1jd8yoj

w1jd8yoj1#

刷新令牌用于请求新的访问令牌。不能使用刷新令牌代替访问令牌

wz8daaqr

wz8daaqr2#

我使用refresh_oauth2.0而不是httr::VERB解决了这个问题。
下面是我的代码,但坏消息是refresh_oauth2.0每次access token到期(一小时)时都会生成一个新的refresh token。但是(如果我想的话)我可以只使用第一个生成的refresh token来连续生成新的access token 7天。因此,许多refresh tokens将没有任何目的地生成。我不确定这是不是一个坏习惯。
编辑:06/06/2023正如John Hanley建议。应该使用新的刷新标记而不是旧的

library(httr)
library(RGoogleFit)
    
oauth2.0_error_codes <- c(
  400,
  401
)

oauth2.0_errors <- c(
  "invalid_request",
  "invalid_client",
  "invalid_grant",
  "unauthorized_client",
  "unsupported_grant_type",
  "invalid_scope"
)

# This implements error checking according to the OAuth2.0
# specification: https://tools.ietf.org/html/rfc6749#section-5.2
find_oauth2.0_error <- function(response) {
  if (!status_code(response) %in% oauth2.0_error_codes) {
    return(NULL)
  }
  
  content <- content(response)
  if (!content$error %in% oauth2.0_errors) {
    return(NULL)
  }
  
  list(
    error = content$error,
    error_description = content$error_description,
    error_uri = content$error_uri
  )
}

refresh_oauth2.0 <- function(endpoint, app, credentials, user_params = NULL,
                             use_basic_auth = FALSE) {
  if (is.null(credentials$refresh_token)) {
    stop("Refresh token not available", call. = FALSE)
  }
  
  refresh_url <- endpoint$access
  req_params <- list(
    refresh_token = credentials$refresh_token,
    client_id = app$key,
    grant_type = "refresh_token"
  )
  
  if (!is.null(user_params)) {
    req_params <- utils::modifyList(user_params, req_params)
  }
  
  if (isTRUE(use_basic_auth)) {
    response <- POST(refresh_url,
                     body = req_params, encode = "form",
                     authenticate(app$key, app$secret, type = "basic")
    )
  } else {
    req_params$client_secret <- app$secret
    response <- POST(refresh_url, body = req_params, encode = "form")
  }
  
  err <- find_oauth2.0_error(response)
  if (!is.null(err)) {
    lines <- c(
      paste0("Unable to refresh token: ", err$error),
      err$error_description,
      err$error_uri
    )
    warning(paste(lines, collapse = "\n"), call. = FALSE)
    return(NULL)
  }
  
  stop_for_status(response)
  refresh_data <- content(response)
  utils::modifyList(credentials, refresh_data)
}

google_client <- gargle::gargle_oauth_client_from_json("client_secret_xxxx.com.json")

myapp <- httr::oauth_app(appname = "myapp", key = google_client$id, secret = google_client$secret)
#endpoint <- httr::oauth_endpoints("google")

google_token <- oauth2.0_token(oauth_endpoints("google"), myapp,
                               scope = "https://www.googleapis.com/auth/fitness.activity.read",
                               cache = "httr-oauth")

currentToken<-google_token$credentials$access_token
labelToken="current Token"

while(TRUE){
  
  n<-GetFitDataset(currentToken,"derived:com.google.step_count.delta:com.google.android.gms:estimated_steps",as.POSIXct(as.Date("2023-05-01")),as.POSIXct(as.Date("2023-06-04")))
  
  # When the token expires, the data is not extracted and n$point is null
  if (is.null(n$point)) {
    print("NEED REFRESH")
    nt<-refresh_oauth2.0(oauth_endpoints("google"),myapp,google_token$credentials)
    
    currentToken<-nt$access_token
    labelToken="refreshed Token"       
    
    n<-GetFitDataset(currentToken,"derived:com.google.step_count.delta:com.google.android.gms:estimated_steps",as.POSIXct(as.Date("2023-05-01")),as.POSIXct(as.Date("2023-06-04")))
  }
  
  print(paste0(Sys.time()," ",labelToken," nrow ",nrow(n$point)))
  Sys.sleep(60)
}

相关问题