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"))
}
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.
Related
Full disclaimer - I'm a bit of an API noob and I don't have much experience with OAuth or token authorization in general.
I see that the rfacebookstat package is on CRAN but I'm in particular concerned about the following function:
function(
app_id = NULL,
scopes = c("ads_read", "business_management", "pages_manage_ads", "ads_management", "public_profile") ){
if(is.null(app_id)) stop("Enter your app id.")
scopes <- paste(scopes, collapse = ",")
utils::browseURL(paste0("https://www.facebook.com/dialog/oauth?client_id=",app_id ,"&display=popup&redirect_uri=https://selesnow.github.io/rfacebookstat/getToken/get_token.html&response_type=token&scope=",scopes))
token <- readline(prompt = "Enter your token: ")
options(rfacebookstat.access_token = token)
return(token)
}
I see there's a redirect to the package creator's personal github site and that makes me a bit nervous. From the .R file I see that this is needed in order to convert the short time token into a long time token - does this represent a security concern? Anyone else have experience with this package? Want to use but I also don't want to leak any campaign data externally.
Alternatively, if I were to write my own wrapper of the above function, could I use localhost as the redirect URI? I just need to query the API to pull historical campaign data, the script I'm writing isn't for any webapp.
I want to log in https://adventofcode.com/2021 programatically using httr.
I have only a very superficial understanding of the OAuth "dance", so to understand the principles I did the following:
Create an OAuth App on GitHub
Used the following code to authenticate (N.B. I know I could simply use oauth2.0_token but I felt that this workflow helped me to better understand the different messages, which are exchanged).
library(httr)
client_id <- "<my client id>"
base_url <- "https://github.com"
path <- "login/oauth/authorize"
client_secret <- "<my secret>"
url <- modify_url(base_url, path = path,
query = list(client_id = client_id,
redirect_uri = oauth_callback()))
code <- oauth_listener(url) ## needed to provide credentials in the web browser
access_token <- POST(modify_url(base_url, path = "login/oauth/access_token"),
add_headers(Accept = "application/json"),
body = list(client_id = client_id,
client_secret = client_secret,
code = code$code))
## successfully returns the values
GET("https://api.github.com/rate_limit",
add_headers(Authorization = paste(content(access_token)$access_token,
"OAUTH-TOKEN")))
From this example I think I understand the steps as highlighted in the documentation.
However, I fail to see how I could use this to login to https://adventofcode.com/2021. I have, of course, not the client_secret nor can I redirect the response to my localhost (as GitHub requires that the stored callback matches the redirect URI).
Thus, I was wondering how I could programatically login to https://adventofcode.com/2021 to fetch my task data, say?
I think you are mismatching OAuth2 roles. If you want to use adventofcode.com, you are a resource owner, adventofcode.com is a client and github is an authorization server. So you authenticate, adventofcode.com gets an auth code and then tokens. They can use the tokens to get information about your github account.
The example code you posted is different - your application is a client that gets a code and tokens from the authorization server (github) after a user was authenticated and gave a consent to passing the tokens to your app (permission delegation). So you probably cannot include adventofcode.com into this scenario.
The only way is if adventofcode.com takes a role of a resource server and their API accepts github tokens from different clients. But I know nothing about their API.
I want to manage my Trello cards and boards using the trelloR package but when I try to create a token with the get_token function, I get an error message on my browser : "Invalid return_url".
my_token <- get_token(key = my_key, secret = my_secret)
my_key is my personal Trello API key and my_secret is my OAuth secret. I got them on the Trello page that gives you your authentication codes, after login : https://trello.com/app-key
To use the Trello API and to access to boards, I need a token. This token is generated with OAuth1.0 by the httr package. Indeed, the function get_token do something like this, according to Jakub Chromec, author and maintainer of trelloR here :
trello.app = httr::oauth_app(
appname = "trello-app",
key = my_key,
secret = my_secret)
trello.urls = httr::oauth_endpoint(
request = "OAuthGetRequestToken",
authorize ="OAuthAuthorizeToken?scope=read&expiration=30days&name=trello-app",
access = "OAuthGetAccessToken",
base_url = "https://trello.com/1")
httr::oauth1.0_token(
endpoint = trello.urls,
app = trello.app)
When I execute this code or the function get_token with my personal key and secret, I am redirected to my browser, which is normal. As described on this page, a screen should appear asking me to allow authentication. But instead I just have an error message in the browser : "Invalid return_url".
In the RStudio console, this remains displayed :
> my_token <- get_token(my_key, my_secret)
Waiting for authentication in browser...
Press Esc/Ctrl + C to abort
I'm using httr 1.4.1, curl 4.2 and trelloR 0.6.0 with R 3.6.1 under macOS 10.15.
Some people reported the problem started after the introduction of Allowed Origins and they were able to fix it by adding the following origin:
http://localhost:1410
on the appkey page. This is a bit surprising to me as the default * should cover all origins, but there you go.
Trying this today (11/23/2019), I could not get wildcards to work as Allowed Origins. You should specify the domain of where you are running the call for authorization.
One source of confusion: The comments under "Allowed Origins" on https://trello.com/app-key refer to sites that "your application is allowed to redirect back to following the authorization flow." That was a bit confusing to me. The list should include sites you want to redirect back to IN ADDITION TO the sites you are calling Trello.authorize() from.
If you are thinking "I don't need a redirect" (and, in fact, if you are using client.js, I don't think you can specify a redirect), then those comments under "Allowed Origins" could lead you to believe you don't need to specify anything there. That would be incorrect.
Summary: Even if you want NO post-authorization re-direct, you still have to list an ORIGIN.
Also, you cannot specify file:// in Allowed Origins, so you cannot run your javascript off a local file.
I am trying to establish an "implicit" Oauth2 authorization flow for my test connect in R to StackOverflow via the StackExchange API.
I am in situation #3 of this related post, that specifies how to set the redirect_uri and other values in a lanugage-agnostic way.
I've taken the steps described, namely setting up the app on StackApps.com to enable implicit authentication.
I've replicated the linked instructions in R with the httr library, the only major adaptation is that apparently httr requires the client secret earlier in the process than StackOverflow actually requires it.
library(httr)
# in the StackApps answer stackoverflow.com was used here.
# that just took me to the landing page.
# the docs use this URI and it gets me closer but
# it just says "Authorizing Application" with a blank page under that
# and it never completes.
end <- oauth_endpoint(authorize = "stackoverflow.com/oauth",
access = "stackoverflow.com/oauth")
client_secret = "secret_code_here"
myapp <- oauth_app("myapp",
key = "12665", # not a secret
secret = client_secret,
redirect_uri="https://stackexchange.com/oauth/login_success")
token <- oauth2.0_token(end,
myapp,
scope=NULL)
#,use_oob=T)
When I run my code a browser automatically opens and goes to StackOverflow.com. However, it just takes me to the landing page and Oauth never completes.
I tried it with use_oob=T and the only difference was that R prompted me for an authorization code that was never provided.
Until a month ago I was using the Rfacebook library with no problems. When I load the token I had generated and I want to use some function for example
getUsers("me",fb_oauth) #fb_oauth is my token
it gives me the following error:
Error in callAPI(url = url, token = token) :
Error validating access token: Session has expired on Tuesday, 04-Apr-17 13:24:59 PDT. The current time is Tuesday, 02-May-17 06:33:21 PDT.
To try to solve it I generate a new password in the app and generate a new token and I get the new token correctly:
fb_oauth <- fbOAuth(app_id="12345678", app_secret="xxxx")
Copy and paste into Site URL on Facebook App Settings: http://localhost:1410/
When done, press any key to continue...
Waiting for authentication in browser...
Press Esc/Ctrl + C to abort
Authentication complete.
But when I want to use the same function it gives me error
Error in callAPI(url = url, token = token) :
An access token is required to request this resource.
Also configure the login in the app but it does not work either
Anyone know how to generate the new token with the new 2.9 update?
Regards
As CBroe mentioned, the access token return format has changed and therefore the problem seems to be, that the credentials (including the access token) returned when authorizing with facebook is saved as the field name/key instead of the field value.
So a fix to this would be the following:
fb_oauth <- fbOAuth(app_id, app_secret, extended_permissions = FALSE,legacy_permissions = FALSE)
fb_oauth_credentials <- fromJSON(names(fb_oauth$credentials))
and then to make a request, such as getting a page would be;
fb_page <- getPage(page = "FBUserNameHere",
token = fb_oauth_credentials$access_token)