I need to authenticate AWS API in R. I tried using aws.signature package to do the same and I am getting 403 response with error Missing Authentication Token . It seems that I am missing some necessary parameters. Looking for assistance to debug the below code or ways to authenticate AWS API in R.
# To create aws signature for authentication for the rest API call
library(aws.signature)
library(httr)
# validate arguments and setup request URL
current <- Sys.time()
d_timestamp <- format(current, "%Y%m%dT%H%M%SZ", tz = "UTC")
hdrs <- list(`Content-Type` = "application/x-www-form-urlencoded",
Host = "jteti5wnje.execute-api.eu-central-1.amazonaws.com",
`x-amz-date` = d_timestamp)
params <- signature_v4_auth(
datetime = d_timestamp,
region = "eu-central-1",
service = "execute-api",
verb = "GET",
action = "iMetaAPI",
query_args = list(),
canonical_headers = hdrs,
request_body = "json",
key = "***************",
secret = "*****************",
session_token = NULL,
query = FALSE,
algorithm = "AWS4-HMAC-SHA256",
verbose = TRUE)
a <- GET("https://jteti5wnje.execute-api.eu-central-1.amazonaws.com/iMetaAPI",
query = params)
rawToChar(a$content)
A few things:
request_body needs to be the actual body. You're doing a GET() so it should just be NULL or "".
The response from signature_v4_auth() is a list but you don't need all of its elements - probably just the hds$Authorization <- params$SignatureHeader element.
The actual errors you're getting is because you haven't passed the headers. You need to pass the headers to GET() with something like: do.call(add_headers, hdrs) so you can do:
a <- GET("https://jteti5wnje.execute-api.eu-central-1.amazonaws.com/iMetaAPI", do.call(add_headers, headers))
That will probably work, or you'll at least get a more informative error.
Related
I'm trying to create authenticate into the Letterboxd API using R and the httr package. The Letterboxd docs give instructions, but I am not sure how to put everything together into a URL.
I know the url is:
url <- "https://api.letterboxd.com/api/v0/auth/token"
And then they want my username and password, presumably as JSON, but what I'll write as a named list since I'm doing this in R:
login_info <- list(
grant_type = "password",
username = "myemail#gmail.com",
password = "extremelysecurepassword"
)
I've tried various calls, using GET(), oauth2.0_token(), oauth_endpoint() functions from the httr package.
I feel like I have all the necessary information and am circling around a solution, but I can't quite nail it.
The docs contain this information:
When generating or refreshing an access token, make a form request to the /auth/token endpoint with Content-Type: application/x-www-form-urlencoded and Accept: application/json headers
(Full text is linked to above)
And I'm not sure how to add that information; in working with APIs through R, I'm used to just sending URLs with UTM parameters, but the inputs they want don't work here using ? and &.
I'm aware of this related post, but it looks like it relies on having a secret token already. And I don't seem to be able to generate a secret token inside of the GUI of Letterboxd.com, which is again what I'm used to doing with authentication. I think I need to feed it those sources of information above in login_info to the url, but I don't quite know how to connect the dots.
How do I authenticate to the Letterboxd API using R?
This runs for me but I get a 401 Unauthorized since you correctly did not supply valid credentials. It looks like there is a python library for this API https://github.com/swizzlevixen/letterboxd if you need hints how to make subsequent requests.
sign_request() is mimicking python library's api.py#L295-L304
sign_request <- function(apisecret, url, method, body = "") {
signing_bytes <- as.raw(c(charToRaw(method), 0, charToRaw(url), 0, charToRaw(body)))
# https://stackoverflow.com/a/31209556/8996878
# https://stackoverflow.com/q/54606193/8996878
digest::hmac(key = apisecret, object = signing_bytes, algo = "sha256", serialize = FALSE)
}
url <- "https://api.letterboxd.com/api/v0/auth/token"
login_info <- list(
grant_type = "password",
username = "myemail#gmail.com",
password = "extremelysecurepassword"
)
apikey <- "mytopsecretapikey"
apisecret <- "YOUR_API_SECRET"
method <- "POST"
params <- list(
apikey = apikey,
nonce = uuid::UUIDgenerate(),
timestamp = round(as.numeric(Sys.time()))
)
# now we need to sign the request
body <- paste(names(login_info), login_info, sep = "=", collapse = "&")
body <- URLencode(body)
body <- gsub("#","%40", body) # something URLencode doesn't do but post does
destination <- httr::parse_url(url)
destination$query <- params
post_url_with_params <- httr::build_url(destination)
signature <- sign_request(apikey, post_url_with_params, method, body)
token_request <- httr::POST(url, httr::add_headers(
"Accept" = "application/json",
"Authorization" = paste0("Signature ", signature)
),
query = params,
body = login_info, encode = "form", httr::verbose()
)
token_body <- httr::content(token_request, type = "application/json")
# look for the value of"access_token"
I try to call the Google Translate API but always get a 403 error that I didn't provide a valid API key.
I did create one, though, on my Google Cloud Platforms website here: https://console.cloud.google.com/apis/credentials
Here's what I'm doing:
library(jsonlite)
library(httr)
my_text <- c("Hallo Mama", "Ja älskar dig")
my_key <- "MYKEY"
textbody <- toJSON(list(q = my_text,
target = "en"))
translated <- POST(url = paste0("https://translation.googleapis.com/language/translate/v2"),
add_headers("key" = my_key),
content_type("application/json"),
body = textbody,
encode = "json")
But this returns said 403 error, i.e.:
fromJSON(rawToChar(translated$content))
gives:
$error
$error$code
[1] 403
$error$message
[1] "The request is missing a valid API key."
$error$errors
message domain reason
1 The request is missing a valid API key. global forbidden
$error$status
[1] "PERMISSION_DENIED"
Note: the "MYKEY" used above I have of course replaced with my created true API key.
Any ideas what's going on?
Update: the following does work for v2 of the API (but not v3). I was missing te unboxing in the JSON body and I seem to have to put the APIkey into the URL:
textbody <- toJSON(list(q = my_text,
target = "en"),
auto_unbox = TRUE)
translated <- POST(url = paste0("https://translation.googleapis.com/language/translate/v2?key=", my_key),
content_type("application/json"),
body = textbody,
encode = "json")
I use Oauth2 authorization to get the token for REST API. I tested the setting in SoapUI and it is working with the Resource Owner Password Credential Grant as shown below.
The setting in the SoapUI testing is working
Now, I want to retrieve the token through R httr library, but I don’t know how to set the resource owner name and password in the R code. Here is my Code
library(httr)
library(jsonlite)
r <- POST("https://XXXXXXX.com/authservice/connect/token",
config = list(),
body = list(
# grant_type = "RESOURCE_OWNER_PASSWORD_CREDENTIALS",
grant_type = "resource_owner_credentials",
resourceOwnerName = "ResourceName",
resourceOwnerPassword = "Resourcepwd",
# resource_Owner_Name = "ResourceName",
# resource_Owner_Password = "Resourcepwd",
# resourceOwner_Name = "ResourceName",
# resourceOwner_Password = "Resourcepwd",
# resource_OwnerName = "ResourceName",
# resource_OwnerPassword = "Resourcepwd",
# resource_Name = "ResourceName",
# resource_Password = "Resourcepwd",
# resource_id = "ResourceName",
# resource_secret = "Resourcepwd",
client_id = "ClientIDname",
client_secret = "Clientpassword",
scope = "xxxGroup"
),
encode = "form"
)
warn_for_status(r)
content(r)
status_code(r)
I got a 400 error ("unsupported_grant_type" and bad request). I am guessing there may be something wrong with the syntax on the resource onwer name and password, so I also tried all the possible combinations that I commented in above code but they all failed.
My question is: are the parameter names for both resource owner name and password pre-defined by the API document, or they are the fixed names defined by R-httr librabry, regardless what token authorization service?
Can someone help to take a look at? Any input is greatly appreciate!
I am having trouble with DELETE requests in R. I have been successful in making GET and POST requests using the below code. Any help / pointers will be appreciated.
It will require an api.key, secret & passphrase from GDAX to work.
Here is my function:
library(RCurl)
library(jsonlite)
library(httr)
library(digest)
cancel_order <- function(api.key,
secret,
passphrase) {
api.url <- "https://api.gdax.com"
#get url extension----
req.url <- "/orders/"
#define method----
method = "DELETE"
url <- paste0(api.url, req.url)
timestamp <-
format(as.numeric(Sys.time()), digits = 13) # create nonce
key <- base64Decode(secret, mode = "raw") # encode api secret
#create final end point----
what <- paste0(timestamp, method, req.url)
#create encoded signature----
sign <-
base64Encode(hmac(key, what, algo = "sha256", raw = TRUE)) # hash
#define headers----
httpheader <- list(
'CB-ACCESS-KEY' = api.key,
'CB-ACCESS-SIGN' = sign,
'CB-ACCESS-TIMESTAMP' = timestamp,
'CB-ACCESS-PASSPHRASE' = passphrase,
'Content-Type' = 'application/json'
)
##------------------------------------------------
response <- getURL(
url = url,
curl = getCurlHandle(useragent = "R"),
httpheader = httpheader
)
print(rawToChar(response)) #rawToChar only on macOS and not on Win
}
The error I get is "{\"message\":\"invalid signature\"}" even though the same command will code and signature will work with GET & POST.
Ref: GDAX API DOCs
just a guess as I am not familiar with the API, but perhaps you are missing the 'order-id' ...
look at: https://docs.gdax.com/?javascript#cancel-an-order
Ok. I took #mrflick's advise and pointed my connection to requestbin based on his feedback on a different but related question.
After careful inspection, I realized that the my request for some reason was treated as a POST request and not a DELETE request. So I decided to replace the getURL function with another higher level function from RCurl for it to work.
response <- httpDELETE(
url = url,
curl = getCurlHandle(useragent = "R"),
httpheader = httpheader
)
Everything else remains the same. Apparently there never was an issue with the signature.
I have added this function now to my unofficial wrapper rgdax
EDIT::
The unofficial wrapper is now official and on CRAN.
I am trying to post an update to Twitter using the api. Following the steps at https://github.com/hadley/httr/blob/master/demo/oauth1-twitter.r, I can get the GET call to work, but I haven't managed to get the POST to work. Here is the relevant code:
library(httr)
library(httpuv)
oauth_endpoints("twitter")
myapp <- oauth_app("twitter",
key = "key"
secret = "secret"
)
twitter_token <- oauth1.0_token(oauth_endpoints("twitter"), myapp)
#this works fine
req <- GET("https://api.twitter.com/1.1/statuses/home_timeline.json",
config(token = twitter_token))
#this doesn't work. Returns error 403: status is forbidden
POST(url = "https://api.twitter.com/1.1/statuses/update.json",
body = "test",
config(token = twitter_token)
)
Any solution that allows a status update (Tweet) from R is acceptable.
The docs say you need to pass a parameter status as a query parameter, not in the body, which makes sense b/c it can only be 140 characters long anyway.
POST("https://api.twitter.com/1.1/statuses/update.json",
query = list(status = "testing from R"),
config(token = twitter_token)
)