Search code examples
roauth-2.0youtube-apiyoutube-data-apihttr

How to do YouTube OAuth Authentication/Reauthentication in R Automatically Using HTTR


I've been using the HTTR package to make requests to the YouTube Data API. I have two channels that I am getting stats for. Upon the first use, when requesting an access token I did the whole OAuth dance where I was redirected to Google as expected. However, I saved the tokens in .httr-oauth files. I developed a for loop similar to the following for me to get my statistics:

channelOneFile <- ".httr-oauth-channel1"
channelTwoFile <- ".httr-oauth-channel2"

myData <- list()
for(i in 1:2){
    token <- try(suppressWarnings(readRDS(tokenFile)), silent = TRUE)[[1]]
    # And Then I get stats with a GET Request
    url <- paste0("https://youtube.googleapis.com/youtube/v3/videospart=contentDetails%2Csnippet",
                  "&id=",videoId)
    request <- GET(url, token)
    myData[[i]] <- request
}

which worked well for a while. However, after running this code roughly 20x or so (due to some testing and tweaking parameters, ONE of the get requests came back with

Auto-refreshing stale OAuth token.
Warning: Unable to refresh token: invalid_grant
Token has been expired or revoked.

At this point I'd just delete the ".httr-oauth" file, reauthenticate, save the new file, and then my code works again. However, I'm hoping to have this code automated on a local server, where the server (I think) can't do the OAuth dance if the token doesn't work.

When I make a request, I know HTTR automatically uses the refresh token to get a new access token, and I know that Google APIs has a limit of how many times a refresh token can be used. I think that perhaps when it gets the new token it doesn't update the ".httr-oauth" file? How can I get it to do that? If that's not an option, what can I do to do the authentication ONCE, save the credentials and access token and such in a file, and then refer to that file when making server requests?

UPDATE: Here is my OAuth flow:

if (file.exists(tokenFile)) {
   token <- try(suppressWarnings(readRDS(tokenFile)), silent = TRUE)[[1]]
} else if (is.null(appId) | is.null(appSecret)) {
    stop("Missing App Credentials")
} else {
  token <- httr::oauth2.0_token(httr::oauth_endpoints("google"), 
                                httr::oauth_app("google", appId, appSecret), 
                                scope = c("https://www.googleapis.com/auth/youtube.readonly", 
                                                        "https://www.googleapis.com/auth/yt-analytics.readonly"))
}

Solution

  • You need to refresh your access token, since this kind of OAuth tokens are short lived (usually are valid one hour). Use httrs function refresh_oauth2.0.

    See this answer of mine for the procedure of handling refresh tokens offline: How to get my own Google API access token without using "Log in with Google"?

    Note that a refresh token can be used as many times as needed for to renew an expiring access token. The refresh tokens usually do not expire (they do when one's app is in testing stage), but can be revoked.