Curl to Javascript - javascript

I am making a Chrome Extension that talks to a website via an api. I want it to pass information about a current tab to my website via a cors request.
I have a POST api request already working. It looks like this:
...
var url = "https://webiste.com/api/v1/users/sendInfo"
...
xhr.send(JSON.stringify({user_name:user_name, password:password, info:info}));
Its corresponding curl statement is something like this:
curl -X POST https://website.com/api/v1/users/sendInfo -d '{ username:"username", password:"password", info: "Lot's of info" }' --header "Content-type: application/json
But, this is not as secure as we want. I was told to mirror the curl command below:
curl --basic -u username:password <request url> -d '{ "info": "Lot's of info" }'
But, one cannot just write curl into javascript.
If someone could either supply javascript that acts like this curl statement or explain exactly what is going on in that basic option of the curl script I think that I could progress from there.

The curl command is setting a basic Authorization header. This can be done in JavaScript like
var url = "https://webiste.com/api/v1/users/sendInfo",
username = "...",
password = "...";
xhr.open('POST', url, true, username, password);
xhr.send(...);
This encodes the username/password using base 64, and sets the Authorization header.
Edit As arcyqwerty mentioned, this is no more secure than sending username/password in the request body JSON. The advantage of using the basic authentication approach is that it's a standard way of specifying user credentials which integrates well with many back-ends. If you need security, make sure to send your data over HTTPS.

curl is the curl binary which fetches URLs.
--basic tells curl to use "HTTP Basic Authentication"
-u username:password tells curl supply a given username/password for the authentication. This authentication information is base64 encoded in the request. Note the emphasis on encoded which is different from encrypted. HTTP basic auth is not secure (although it can be made more secure by using an HTTPS channel)
-d tells curl to send the following as the data for the request
You may be able to specify HTTP basic authentication in your request by making the request to https://username:password#website.com/api/v1/users/sendInfo

Related

Creating a Shopify Order via postman / Shopify API

I ran into this tutorial using every technology in the world which is supposed to show how to build a react app from the ground up to leverage the shopify API. However there also this page describing a simple API call to do more or less what I need.
The goal is to have an entirely custom (extremely simple) checkout process that ends up in the shopify system. It would go something like this:
Stripe purchase ok -> shopify order saved -> thank you page redirect.
EDIT: It appears that the format https://api_key:api_secret.#my-store.myshopify.com/admin/api/2019-07/orders.json solves the authentication problem. The call:
GET https://key:secret#my-test-store.myshopify.com/admin/api/2019-07/orders.json
returns a pleasant
{
"orders": []
} so the authentication is a-ok.
However, doing a POST https://key:secret#my-test-store.myshopify.com/admin/api/2019-07/orders.json
Seems to return a cryptic page, instead of an error like so (which simply leads to your demo store/app):
So, in summary, I have a store, an authorized app (which successfully authenticates) so how do I add an order for an existing SKU programmatically?
Are you sure there are no cookies on the request? Because I can reproduce your exact issue if I add cookies.
It might be easier to use curl in order to have absolute clarity into what is being posted. For example:
# Edit to change app hostname, key/secret, and product/variant/customer ids
curl -X POST 'https://key:secret#so57018447.myshopify.com/admin/api/2019-07/orders.json' \
-H 'Content-Type: application/json' \
-d '{
"order": {
"line_items": [
{
"product_id": 2017449607219,
"variant_id": 17985741619251,
"quantity": 1
}
],
"customer": {
"id": 1257159000115
},
"financial_status": "pending"
}
}
'
Response:
{
"order": {
"id":952834392115,
"email":"",
"closed_at":null,
"created_at":"2019-07-15T14:38:18-04:00",
...
But if you want to stick with Postman, here are the supporting screenshots showing success without cookies, and failure with:
Confirming there are no cookies set:
Successful post to orders.json endpoint:
Now, add a cookie:
And I get the response shown in your question:
If you read the documentation of the private apps
Shopify doesn't support cookies in POST requests that use basic HTTP authentication. Any POST requests that use basic authentication and include cookies will fail with a 200 error code. Using cookies with basic authentication can expose your app to CSRF attacks, such as session hijacking.
https://help.shopify.com/en/api/getting-started/authentication/private-authentication
This is on purpose, doing this on a client side is criminal. If you are doing something server side then it is ok to use basic auth. But on client side you shouldn't be using it
If you want to use in postman then you need to use it with access_token
Private apps can authenticate with Shopify by including the request header X-Shopify-Access-Token: {access_token}, where {access_token} is replaced by your private app's Admin API password.

How to see the HTTP request that AngularJS is sending?

I have a REST endpoint called myEndpoint that I can successfully hit using Curl like this:
curl \
--request DELETE \
--header "Content-Type: application/json" \
--header "Authorization: JWT eyJhbFciOiJ__FAKE__sInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InNhcWliIi__FAKE__9pZCI6NSwiZW1haWwiOiJzYXFpYi5hbGkuNzVAZ21haWwuY29tIiwiZXhwIjoxNDkxNzkyMzEzfQ.feGiXm__FAKE__ZS6V-OROM7EzekRzpu_5pwi865tz8" \
--data '{
"myAttribute": "Something"
}' \
"http://localhost:3999/api/myEndpoint"
However, when my AngularJS code tries to call the same endpoint it fails saying that the mandatory myAttribute parameter was not provided. This is how angularJS is making the call:
var httpParams = {'myAttribute': 'Something'};
$scope.myPromise = $http.delete('http://localhost:3999/api/myEndpoint', httpParams).then(self.myEndpointSuccess, self.myEndpointFailure);
(AngularJS's attachment of the JWT token to the HTTP request is not shown, but I'm sure that is working)
How can I see exactly what HTTP request AngularJS is sending so that I can do an apples-to-apples comparison agains my working curl call?
Here is my Chrome's Developer Tools -> Network tab. I don't see the information I'm seeking there:
The $ http service documentation says that $ http.delete gets two parameters, URL and config. By its call curl, I understand that myAtribute is the name given to a parameter that you want to send to the endpoint, in which case it should be in the params property or data property of the config object.
angular reference
another question
FYI, DELETE requests do not typically have a request body.
As for your issue, RTFM; the second arg to $http.delete should be a config object, so in your case
$http.delete('http://localhost:3999/api/myEndpoint', {data: httpParams})
AngularJS provides the $http module for http requests. You can make a specific request with this module and then process the request with the . then() whichever takes a success callback followed by a error callback

How to get a Yelp Fusion API access token?

I'm using the Yelp's Fusion API.
All the documentation is here and seems straight forward but still doesn't seem to work.
https://www.yelp.com/developers/documentation/v3/get_started
Here is my request for a token.
https://api.yelp.com/oauth2/token?grant_type= OAuth2&client_secret= SECRET&client_id=ID
I receive this response.
{
"error": {
"description": "Bad Request",
"code": "CLIENT_ERROR"
}
}
I reread the documentation and it says
"To get an access token, make a POST call to the following endpoint
using the client id and secret obtained from the former step. Then get
the access token from the response body."
I submitted this
https://api.yelp.com/oauth2/token?client_id=ID&client_secret= SECRET
I got the same error.
What am I missing?
Thank you in advance
You have three problems that are causing you to get the bad request
You have spaces in your parameter values
?grant_type= OAuth2
You are using the wrong grant_type. On the documentation page they specify that only client_credentials is supported, meaning you have to use that as the value
grant_type string The OAuth2 grant type to use.
Right now, only client_credentials is supported.
You are using the wrong request method, it has to be a POST not a GET request
These parameters should be sent in application/x-www-form-urlencoded
format in the POST call.
Note that https://api.yelp.com/oauth2/token?client_id=ID&client_secret=SECRET is still sending your parameters as GET parameters as they are in the url query string. You have to pass the parameters as POST fields, and the syntax for doing so differs on the server side script language you use.
Also your request needs to be done server side as the /oauth2/token endpoint does not send a Access-Control-Allow-Origin header meaning you cannot use an ajax request to get the data.
So if say you were using PHP server side, you could use CURL to get the token
$postData = "grant_type=client_credentials&".
"client_id=YOURCLIENTID&".
"client_secret=SECRET";
$ch = curl_init();
//set the url
curl_setopt($ch,CURLOPT_URL, "https://api.yelp.com/oauth2/token");
//tell curl we are doing a post
curl_setopt($ch,CURLOPT_POST, TRUE);
//set post fields
curl_setopt($ch,CURLOPT_POSTFIELDS, $postData);
//tell curl we want the returned data
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
//close connection
curl_close($ch);
if($result){
$data = json_decode($result);
echo "Token: ".$data->access_token;
}
I used POSTMAN to get the data required, you can download it here -
https://www.getpostman.com/
In order to obtain your access token the parameters should be in the request body, not the request URL.
In POSTMAN you need to provide the following as key/value pairs:
grant_type : client_credentials is supported.
client_id : The client id for you app with Yelp.
client_secret : The client secret for you app with Yelp.
To do this, you enter them in the Body. Also click the x-www-form-urlencoded radio button.
See the screenshot link below:
How to configure POSTMAN to get your Yelp Access Token
You can then play around over at RapidAPI Yelp API to test some endpoints and parameters.

Clientside GitHub Authentication

I'm using a Javascript to do Basic Authentication with GitHub. For example, the following shell command gets a token from Github:
curl -i -u uaername:password -k -d "{\"scopes\": [\"repo\"]}" https://api.github.com/authorizations
How do you achieve that with jQuery and AJAX?
Including Basic Auth Data in HTTP Headers with jQuery
You can include basic auth details in the header using the Authorization field. You already understand how jQuery works. This snippet has the bits you're missing:
let auth = btoa(username + ":" + password);
jQuery.ajax({
url: ...,
headers: { Authorization: "Basic " + auth }
...
});
Note: btoa and atob (pronounced B to A and A to B) are builtin functions, and convert to and from Base64. See the MDN docs for more information.
Are you asking whether there is a way to get an oAuth token purely from the client side? If so, the answer is no.
But, you have some work arounds.
Github.js: https://github.com/michael/github
Gatekeeper is an open source server side component which can help with oAuth tokens management:
https://github.com/prose/gatekeeper
You could also use something like Firebase with simple login and in this case you don't need to manage any server side services:
https://www.firebase.com/docs/security/simple-login-github.html

CouchdB Jquery Ajax POST CORS

I am prototyping a very simple webapp. I installed Couch 1.3.1 today and created a database. I am attempting to save a document to my local couch (localhost:5984) with a POST from a client browser also on localhost, but different port (6789)
var dbIp = "http://localhost:5984/commute";
var data = {state:0,timestamp:"faketime"};
$.ajax({
type: 'POST',
crossDomain: true,
contentType: "application/json",
url: dbIp,
data: data,
success: function(result) {
console.log(result);
}
});
I get:
XMLHttpRequest cannot load http://localhost:5984/commute-tracker. Origin http://localhost:6789 is not allowed by Access-Control-Allow-Origin.
I have modified the local.ini to enable CORS as outlined in the couchdb spec with
[httpd]
enable_cors = true
[cors]
origins = *
[cors]
methods = GET, POST, PUT, DELETE
I can see all of these changes reflected in the config file in futon. I have also tested the database with a curl:
curl -X POST localhost:5984/commute -H "Content-Type: application/json" -d '{"tags":"sure","name":"made it"}'
The curl works just fine, but I can't make a similar POST in the browser because of Access Control Allow Origin. What else am I missing, or what can I change to make this POST possible?
Going about this trying to do cross-domain, whether it's CORS or JSONP is not ideal.
Since you actually do control both the web server instance and the couchdb instance (I'm assuming you have admin rights to the server) I'd recommend using a reverse proxy to serve couchdb as an endpoint for the main web app.
If you're using Apache mod_proxy will allow you to do this, or nginx is another great HTTP reverse proxy server...inserting a config directive like:
ProxyPass /couch_db/ http://www.localhost:5984/ (for mod_proxy)
would let you post to http://localhost:6789/couch_db/commute

Categories