Authenticate using httr package when Making API Requests - r

I'm learning how to fetch data using an API in R. I understand that the aim of httr is to provide a wrapper for the curl package.
The documentation I'm following so that I make requests to the API has the following HTTP request format. This code below will be used to generate a token
curl -s \
-d "client_id=clientid” \
-d "username=user” \
-d "password=pwd” \
-d "grant_type=password" \
-d "scope=openid email" \
"https://auth.com/token"
Afterward, I'll use the token to now communicate with the API using this request
curl --header "Content-Type: application/json" \
--header "Accept: application/+json" \
--header "Authorization: Bearer token_goes_here“ \
--request GET \
--url "https://api-sitename.org/sections?parent_id=0"
Initially, I run these two requests in a terminal and they were successful, I got a response in JSON format. My question is, how do I run these requests in an R script such that I get a responses and they're it's stored in R studio global environment? My goal is to finally load the dataset from the API to the Rstudio working environment.
T

Here is something to get you started:
library(httr)
resp <- POST("https://auth.com/token",
body=list(client_id="clientid",
username="user",
password="pwd",
grant_type="password",
scope="openid email")
)
#parse for auth token here
content(resp, "text")
get_resp <- GET("https://api-sitename.org/sections?parent_id=0",
add_headers("Content-Type"="application/json",
Accept="application/+json",
"Authorization"=paste("Bearer", token))

I was able to successfully get my API call in R by replacing the content in header to body.
Here is my code
#' Th base url
base_url <- "your/url/endpoint/for/token"
# base64 encoded client id, my end-point requires to encone the client id to base64
c_id <- RCurl::base64(txt = "clinetid:sceret", mode = "character")
#' headers
headers <- httr::add_headers(
"Authorization" = paste("Basic",c_id, sep = " ")
)
# move everything else to the body. grant_type and password were requested by the endpoint
body <- list(
username = "your username",
password = "your password",
grant_type = "password",
scope = "read"
)
#' post call to get the token
httr::POST(
url = base_url,
body = body,
config = headers,
httr::accept_json()
)
When I had the user name and password in the body, I received 400 and 403 errors. Once I moved them o the body received 200 status and the token was successfully retrieved. If you can provide what you tried in R, can help you troubleshoot.

Related

Write a complicated curl request's R equivalent

I have a curl request:
curl -k --insecure -X POST https://somehttp -H 'Content-Type: application/x-www-form-urlencoded' -H 'cache-control: no-cache' -d 'grant_type=password&client_id=my_id&username=admin&password=admin&client_secret=k6897pyy-1h7l-11q0-lp10-s20sg4erlq44' | jq .access_token
How could i write that request in R. I've seen examples of simple ones, but not this complicated.
Obviously I can't test this with the example you provided, but this should get you close. First ensure you populate these variables correctly:
url <- "http://www.somehttp.com"
my_id <- "my_id"
username <- "admin"
password <- "admin"
my_secret <- "k6897pyy-1h7l-11q0-lp10-s20sg4erlq4"
Now the following code prepares the request, sends it, and parses the response (I'm assuming it is json)
library(httr)
H <- add_headers(`Content-Type`= "application/x-www-form-urlencoded",
`cache-control` = "no-cache")
form_body <- list(grant_type = "password",
client_id = my_id,
username = username,
password = password,
client_secret = my_secret)
res <- POST(url = url, body = form_body, encode = "form", H)
content(res, "parsed")

Trying to get data from an API

I'm trying to get some appointment data from a practice management software. I have an API key but I have no experience in the area.
I have tried to convert Curl code with little success. The api documentation is here https://github.com/redguava/cliniko-api
I am trying to convert this curl code
curl https://api.cliniko.com/v1/appointments \
-u API_KEY: \
-H 'Accept: application/json' \
-H 'User-Agent: APP_VENDOR_NAME (APP_VENDOR_EMAIL)'
What I've tried: (yes this is from a curl to r converter)
require(httr)
headers = c(
`Accept` = 'application/json',
`User-Agent` = 'APP_VENDOR_NAME (APP_VENDOR_EMAIL)'
)
res <- httr::GET(url = 'https://api.cliniko.com/v1/appointments',
httr::add_headers(.headers=headers),
httr::authenticate('API_KEY', 'INSERTED MY API KEY'))
Any ideas would be greatly appreciated
httr::authenticate takes input username and password in the form httr::authenticate(username,password).
Curl's authenticate takes argument username and password joined by by a :, i.e. username:password.
In the example from the API documentation the curl command authenticates the username:password combination API_KEY:. Looking closely, we can see that after the : is blank. From this we can determine the username field should be 'API_KEY' and the password field should be ''.
So you should change your curl command to:
require(httr)
headers = c(
`Accept` = 'application/json',
`User-Agent` = 'APP_VENDOR_NAME (APP_VENDOR_EMAIL)'
)
res <- httr::GET(url = 'https://api.cliniko.com/v1/appointments',
httr::add_headers(.headers=headers),
httr::authenticate('API_KEY', ''))
Where API_KEY is your provided API key.

how to execute a https post request using curl in flutter

i am new to using curl and I am trying to execute a https post request using curl. and it doest seem to work like other json post requests so i was hoping someone can explain this to me
I am not sure if i understood your answer well enough but you can take a look at this Package or this one the latter one provides provides more flexibility and features like Interceptors etc.
You can use this package Curl https://pub.dev/packages/curl
example code
import 'package:curl/curl.dart';
import 'package:http/http.dart';
final req1 = new Request("GET", "https://exyui.com/endpoint");
print(toCurl(req1));
// will print out:
// curl 'https://exyui.com/endpoint' --compressed --insecure
final req2 = new Request("PUT", "https://exyui.com/endpoint");
req2.body = "This is the text of body😅, \\, \\\\, \\\\\\";
print(req2);
// will print out:
// curl 'https://exyui.com/endpoint' -X PUT -H 'content-type: text/plain; charset=utf-8' --data-binary \$'This is the text of body\\ud83d\\ude05, \\, \\\\, \\\\\\' --compressed --insecure
final req3 = new Request("POST", "https://exyui.com/endpoint");
final part1 = "This is the part one of content";
final part2 = "This is the part two of content😅";
final expectQuery = "part1=This%20is%20the%20part%20one%20of%20content&part2=This%20is%20the%20part%20two%20of%20content%F0%9F%98%85";
req3.bodyFields = {
"part1": part1,
"part2": part2,
};
print(toCurl(req3));

oauth2 error AADSTS90014: The request body must contain the following parameter: 'grant_type'

From the development in Windev I use Oauth 2.0 for authorization to get access to the outlook mail from a user.
The application is registered at https://apps.dev.microsoft.com without the Implicit workflow.
After the user enters the credentials, an Authorization Code is returned.
With the new code the Bearer Token is requested with a HTTP Post command.
So far, so good.
Only that the response gives an error message that makes no sense to me.
In code:
m_sHTTPUrl = "client_id=" + m_sClientID + "&client_secret=" ...
+ m_sClientSecret ...
+ "&redirect_uri=" + m_sRedirectURL + "&code=" + m_sAuthToken ...
+ "&grant_type=authorization_code"
m_sHTTPres = ""
LogLocalFile("GetAccessToken - " + m_sTokenURL + " // " + m_sHTTPUrl)
cMyRequest is httpRequest
cMyRequest..Method = httpPost
cMyRequest..URL = m_sTokenURL
cMyRequest..ContentType = "application/x-www-form-urlencoded"
cMyRequest..Header["grant_type"] = "authorization_code"
cMyRequest..Header["code"] = m_sAuthToken
cMyRequest..Header["client_id"] = m_sClientID
cMyRequest..Header["client_secret"] = m_sClientSecret
cMyRequest..Header["scope"] = m_sScope
cMyRequest..Header["redirect_uri"] = m_sRedirectURL
//cMyRequest..Content = m_sHTTPUrl
cMyResponse is httpResponse = HTTPSend(cMyRequest)
m_sHTTPres = cMyResponse.Content
In a logfile I requested the used parameters and the content of the httpResponse:
GetAccessToken - https://login.microsoftonline.com/common/oauth2/v2.0/token // grant_type=authorization_code
&code=xxxxxxx
&scope=openid+offline_access+User.Read+Email+Mail.Read+Contacts.Read
&redirect_uri=http://localhost/
&client_id=xxxxxxx
&client_secret=xxxxxxx
GetAccessToken - error = invalid_request
GetAccessToken - error_description = AADSTS90014: The request body must contain the following parameter: 'grant_type'.
The grant_type is in the header as it is supposed to be.
Does anybody have any clue of what is needed to get the OAUTH2 working ?
You shouldn't send grant_type neither in params nor in headers. Those should be sent in body params then only it will work.
Url: https://login.microsoftonline.com/common/oauth2/v2.0/token
client_id, scope and redirect_uri params can be sent as query params.
where as grant_type, code and client_secret should sent in body params.
grant_type:authorization_code,
code: {code you got from the authorization step},
client_secret: ****
You need to pass everything in body as form-data:
curl --location --request POST 'https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token' \
--form 'grant_type=authorization_code' \
--form '<the code you have got from the authorization endpoint' \
--form 'client_secret=****' \
--form 'client_id=********' \
--form 'scope=m_sScope' \
--form 'redirect_uri=http://localhost/'
you should change the content type as : application/x-www-form-urlencoded
the body must to be formated as bellow:
client_id=8cfbe8ac-8775-4c56-9302-k9d5a42cbf98
&client_secret=BOy7Q~pGvXF.SWshX72mmMnQeAkvN5elHWiYT
&grant_type=client_credentials
&resource=https://miurl.com
I finally got this right after referring to multiple answers.
POST https://login.microsoftonline.com//oauth2/token
--make sure to enter the ID directly without <,>
Use 'x-www-form-urlencoded' format for the Body.
Enter Keys & Values for the below parameters
client_id - Client_ID on your Azure App
client_secret - client_secret value and not the key. Note that this value is available only for the first time upon the client secret key creation
grant_type - client_credentials (static words, don't try to look for the value)
resource - App ID URI
reference link - https://learn.microsoft.com/en-us/previous-versions/azure/dn645543(v=azure.100)?redirectedfrom=MSDN
when providing "Default Scope" value must be full name example , "User.Read" correct value can get from azure AD APP -> Api Permission

Asynchronous POST Requests - R, using RCurl?

I am trying to make async requests to a REST API from R. The below curl command illustrates the parameters that I need to the pass to the api. I'm giving you guys the linux curl command as I'm hoping that will make it clear:
curl -v -X POST https://app.example.com/api/ \
-H 'Authorization: somepwd' \
-H "Content-Type: application/json" \
-d {key1: value1, key2: value2}
Right now, I'm accomplishing the same thing in R by executing the following:
library(httr)
library(jsonlite)
content(POST('https://app.example.com/api/'
,add_headers(Authorization = 'somepwd')
,body = toJSON(rDataFrame)
,content_type_json()
)
)
The goal is to submit the above POST request from R but to vary the json string that is sent in the body, and do that asynchronously.
I have been searching for packages that will help me make asynchronous requests rather than making requests serially. The closest thing I could find is the getURIAsynchronous() function from the RCurl package (https://cran.r-project.org/web/packages/RCurl/RCurl.pdf) but do not understand how to submit a PUT request with headers and a body using their function. I would really like to make the above POST request from R but asynchronously where the URI is the same, but the data sent is different for each request.
I found this http://www.omegahat.org/RCurl/concurrent.html
getURIs =
function(uris, ..., multiHandle = getCurlMultiHandle(), .perform = TRUE)
{
content = list()
curls = list()
for(i in uris) {
curl = getCurlHandle()
content[[i]] = basicTextGatherer()
opts = curlOptions(URL = i, writefunction = content[[i]]$update, ...)
curlSetOpt(.opts = opts, curl = curl)
multiHandle = push(multiHandle, curl)
}
if(.perform) {
complete(multiHandle)
lapply(content, function(x) x$value())
} else {
return(list(multiHandle = multiHandle, content = content))
}
}
My idea is that I could replace for (i in uris) with for(i in jsons) where I am looping over the different data that I want to send to the same URL, however I am having trouble understanding the following concepts from the RCurl Package:
How do I pass a header as part of a PUT request. How do I pass data in the body of the request? This was pretty straight forward using the httr package as I have illustrated above.
I tried passing in the header in the curl options and alternatively the header. The thing is I don't understand where to pass the the component parts of the post request: authentication, header, and body within the getURIAsynchronous() function, or any of the resources I have described above.
Does anyone know how to accomplish this? An example would be incredibly helpful.
The curl package has been recently updated to handle async requests (see here)
Using the curl, magrittr and jsonlite packages you can create asynchronous post requests by:
Creating a generic handle with your header and body content using the handle_setform function
Writing a call back function to retrieve your results
Initializing a pool and adding your concurrent requests to it
Running your pool via multi_run
Example code is below:
library(curl)
library(jsonlite)
library(magrittr)
#create a handle object
h <- new_handle() %>%
handle_setheaders(Authorization = "somepwd",
"Content-Type" = "application/json") %>%
handle_setform(body = toJSON(iris))
pool <- new_pool()
# results only available through call back function
cb <- function(req){cat("done:", req$url, ": HTTP:", req$status, "\n", "content:", rawToChar(req$content), "\n")}
# example vector of uris to loop through
uris <- c("https://app.example.com/api/endpoint1"
,"https://app.example.com/api/endpoint2"
,"https://app.example.com/api/endpoint3")
# all scheduled requests are performed concurrently
sapply(uris, curl_fetch_multi, done=cb, pool=pool)
# This actually performs requests
out <- multi_run(pool = pool)

Resources