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
I want to set a header for getting the token from flipkart. I dont know how to set a header in curl. My header should like
curl -u <appid>:<app-secret> https://sandbox-api.flipkart.net/oauth-service/oauth/token\?grant_type\=client_credentials\&scope=Seller_Api
It looks like you're trying to do HTTP basic authentication, or at least that's what the -u option of curl does when used alone like this.
In PHP you would set up basic authentication for a curl request like this, assuming $ch is your curl instance (which you can get with curl_init):
curl_setopt($ch, CURLOPT_USERPWD, 'appid:appsecret');
See the curl documentation on curl_setopt for more information.
In curl command you have to do like this,
curl -u your-app-id:your-app-token https://sandbox-api.flipkart.net/oauth-service/oauth/token\?grant_type\=client_credentials\&scope=Seller_Api
you will get the result like this on success,
{"access_token":"394b7d-418a-43f6-8fd5-e67aea2c4b","token_type":"bearer","expires_in":4657653,"scope":"Seller_Api"}
by using this token you can make further api call's like for example listing api,
curl -H "Authorization:Bearer your-access-token" -H "Content-Type: application/json" -d 'json-here-see-format-in-api-example' https://url-end-point-refer-api-docs
note: you have to create app id and secret in "https://sandbox-api.flipkart.net/oauth-register/login" for sandbox. Don't store the access token it will get expired in certain period of time.
link for api doc's - "https://seller.flipkart.com/api-docs/fmsapi_index.html"
I am using the codeigniter rest server api library.
When I enter http://localhost/RESTapi/api/question?X-API-KEY=XXX in Postman with the PUT method
I'm getting:
{
"status": false,
"error": "Invalid API key "
}
It works fine with GET method
How can I fix this issue?
I've seen some API's that do not look at the GET params if you make a POST or PUT request for credentials or are inconsistent in how they do it.
Really, credentials should go in headers either via the Authorize header or a custom one for many reasons like 'not logging credentials to access logs', but I digress.
In this case you can try:
Put (no pun) the X-API-KEY=XXX inside the body of the PUT just to see if this works
See if/how the library accepts the API key in a header
Looking at this library in particular (https://github.com/chriskacerguis/codeigniter-restserver), they do support the header X-API-KEY. This should be where you put the key for ALL requests--it's best practice not to pass them as url params.
Here's the commandline example using curl from their Github project.
curl -X POST -H "X-API-KEY: some_key_here" http://example.com/books
In PHP you can use curl to set header like this:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-API-KEY: XXX'));
I am using the following cURL request to localhost which runs fine:
curl -u admin:e4d4face52f2e3dc22b43b2145ed7c58ce66e26b384d73592c -d "{\"jsonrpc\": \"2.0\", \"method\": \"feed.list\", \"id\": 1}" http://localhost/minifluxR/jsonrpc.php
But when I send the same request using Postman instead of cURL, I am getting:
{"jsonrpc":"2.0","id":null,"error":{"code":-32700,"message":"Parse error"}}
In Postman I used a GET request and sent the following as headers:
url:http://localhost/minifluxR/jsonrpc.php
username:admin
api_token:e4d4face52f2e3dc22b43b2145ed7c58ce66e26b384d73592c
method: feed.list
The following is the PHP function I am trying to trigger:
$server = new Server;
$server->authentication(array(
\Model\Config\get('username') => \Model\Config\get('api_token')
));
// Get all feeds
$server->register('feed.list', function () {
return Model\Feed\get_all();
});
Please help me to correct these errors.
When using cURL, the -u option (or --user) is used to supply the credentials for HTTP Basic authentication. This sets the Authorization header to contain the necessary data to authenticate with the server.
These steps apply to Postman's packaged app. For steps for the legacy app, view this of revision this answer.
To use HTTP Basic authentication as you were in your cURL command, click the Authorization tab and enter your credentials. Clicking Update Request will add the necessary Authorization header for you.
To submit the JSON data in the same way that you did with cURL, use a POST request, select raw under the Body tab, and enter your data like so:
To debug this I used Fiddler - a free web debugging proxy.
I used cURL's --proxy option to make it send its requests through Fiddler like so:
curl \
--proxy http://localhost:8888 \
-u foo:bar \
-d "{\"jsonrpc\": \"2.0\", \"method\": \"feed.list\", \"id\": 1}" \
http://localhost
Now that the request goes through Fiddler, I can select it from the session list, and use the "raw" inspector to see the raw request:
This shows me that the cURL is making a POST request with HTTP Basic authentication and application/x-www-form-urlencoded content. This type of data normally consists of keys and values, such as foo=bar&hoge=fuga. However, this cURL request is submitting a key without a value. A call to var_dump($_POST) will yield the following:
With a = at the end of the data (like so: {"jsonrpc": "2.0", "method": "feed.list", "id": 1}=) the var_dump will yield the following:
However, it seems that JsonRPC will use file_get_contents('php://input') in your case. This returns the data that was submitted with the request, including a =, if the data ends with it. Because it will try to parse the input data as a JSON string, it will fail if the string ends with a =, because that would be invalid JSON.
Using the FoxyProxy extension for Chrome, I created a proxy configuration for Fiddler (127.0.0.1:8888), which allowed me to easily debug the data being sent by Postman's POST request. Using x-www-form-urlencoded with a key of foo with no value, the data sent was actually foo=, which would result in your JSON string being invalid.
However, using "raw" input will allow for the specified data to be sent without a = being added to the end of it, thus ensuring the data is valid JSON.
Curl is using HTTP Basic authentication by default. Your headers set in Postman are something different. Try using Basic Auth in Postman. It is in top panel, you fill in username and password and authorization header will be generated.
I followed this Laravel token API tutorial: http://rjv.im/post/95988160186/api-token-authentication-with-laravel-and-sentry-part. I have written the following cURL request to communicate with my API:
curl -H "X-Auth-Token:tokenhere" http://localhost:8000/account
The request works properly, and accurately returns the expected data. When I translate this to Python I receive urllib2.HTTPError: HTTP Error 401: Unauthorized
import urllib2
req = urllib2.Request('http://localhost:8000/account')
req.add_header("X-Auth-Token", "tokenhere")
resp = urllib2.urlopen(req)
content = resp.read()
print content
If I pass user credentials using basic auth instead of an X-Auth-Token, the request works as expected:
import urllib2
def basic_authorization(user, password):
s = user + ":" + password
return "Basic " + s.encode("base64").rstrip()
req = urllib2.Request("http://localhost:8000/account", headers = { "Authorization": basic_authorization("usernameHere", "passwordHere"), })
f = urllib2.urlopen(req)
print f.read()
Any assistance would be much appreciated.
There is something you missed in the tutorial. In the tokens table there is a column:
$table->string('client');
It is important from which client you are sending your request. I am using https://github.com/hisorange/browser-detect to detect from which client I got the request.
But for now I will just try to see User Agent. In my laravel code I just logged every request to see what's happening with the following code:
Route::filter('auth.token', function($route, $request)
{
....
Log::info($request);
....
}
Now, Let's see:
When I use curl from command line:
curl -u user#example.com:password -X GET http://localhost:8000/account
My User Agent is
User-Agent: curl/7.32.0
I sent the same from python using your code above, User Agent is:
User-Agent: Python-urllib/2.7
Ah! That must be it. You have to authenticate your user at least once using Basic Auth, it will give you a token and that token is valid for only that client. In the first part http://rjv.im/post/78940780589/api-token-authentication-with-laravel-and-sentry-part of tutorial there was no such condition. In the comments I received someone posted a query on how to support multiple clients, so this example was made to solve that problem.
Apart from that, may I suggest this library: https://github.com/chrisbjr/api-guard It supports Rate Limiting, easy to integrate with Sentry. It's a bit different from my tutorial. Using my solution you can hit any endpoint using Basic Auth or Token. Using above library, only token is permitted, so there is dedicated route to generate token. Let me know how it goes.
An API I'm trying to program to requires multipart/form-data content with the HTTP GET verb. From the command line I can make this work like this:
curl -X GET -H "Accept: application/json" -F grant_type=consumer_credentials -F consumer_key=$key -F consumer_secret=$secret https://example.com/api/AccessToken
which seems like a contradiction in terms to me, but it actually works, and from what I see tracing it actually uses GET. I've tried a bunch of things to get this working using PHP's cURL library, but I just can't seem to get it to not use POST, which their servers kick out with an error.
Update to clarify the question: how can I get php's cURL library to do the same thing as that command line?
which seems like a contradiction in terms to me, but it actually
works, and from what I see tracing it actually uses GET
Not exactly. curl uses a feature of the HTTP/1.1. It inserts additional field to the header Expect: 100-continue, on which, if supported by server, server should response by HTTP/1.1 100 Continue, which tells the client to continue with its request. This interim response is used to inform the client that the initial part of the request has been received and has not yet been rejected by the server. The client SHOULD continue by sending the remainder of the request or, if the request has already been completed, ignore this response. The server MUST send a final response after the request has been completed.
Since they are insisting on HTTP GET, then just encode the form elements into query parameters on the URL you are GETing and use cURL's standard get options instead of posting multipart/formdata.
-X will only change the method keyword, everything else will remain acting the same which in this case (with the -F options) means like multipart formpost.
-F is multipart formpost and you really cannot convert that to a query part in the URL suitable for a typical GET so this was probably not a good idea to start with.
I would guess that you actually want to use -d to specify the data to post, and then you use -G to convert that data into a string that gets appended to the URL so that the operation turns out to a nice and clean GET.