143

I am trying to POST data from my API but I can't pass the basic authentication.

I try:

$.ajax({ type: 'POST', url: http://theappurl.com/api/v1/method/, data: {}, crossDomain: true, beforeSend: function(xhr) { xhr.setRequestHeader('Authorization', 'Basic [REDACTED]'); } }); 

My server configuration response is:

response["Access-Control-Allow-Origin"] = "*" response["Access-Control-Allow-Methods"] = "POST" response["Access-Control-Max-Age"] = "1000" response["Access-Control-Allow-Headers"] = "*" 

The headers that I get is:

Request Headers

OPTIONS /api/v1/token-auth/ HTTP/1.1 Host: theappurl.com Connection: keep-alive Access-Control-Request-Method: POST Origin: http://127.0.0.1:8080 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31 Access-Control-Request-Headers: origin, authorization, content-type Accept: */* Referer: http://127.0.0.1:8080/ Accept-Encoding: gzip,deflate,sdch Accept-Language: es,en;q=0.8 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

Response header

HTTP/1.1 401 Unauthorized Server: nginx/1.1.19 Date: Fri, 16 Aug 2013 01:29:21 GMT Content-Type: text/html Content-Length: 597 Connection: keep-alive WWW-Authenticate: Basic realm="Restricted" 

I guess the server configuration is good because I can access to API from the Advanced REST Client (Chrome Extension)

Any suggestions?

PD: The header that I get from Advanced REST client is:

 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31 Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo Authorization: Basic [REDACTED] Content-Type: application/x-www-form-urlencoded Accept: */* Accept-Encoding: gzip,deflate,sdch Accept-Language: es,en;q=0.8 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

and

 Server: nginx/1.1.19 Date: Fri, 16 Aug 2013 01:07:18 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Vary: Accept, Cookie Allow: POST, OPTIONS X-Robots-Tag: noindex 

sending OPTION method

3
  • 23
    I realize this post is long dead, but I just want to point out in case you're not aware that by posting your Authorization: header, you've essentially posted your password in the clear. The string of gibberish there is just the base64 encoding of your username:password, so everyone can see your password. Hopefully you realized this and used a dummy password here :) Commented Nov 13, 2014 at 16:41
  • This works fine with ssrs report server 2017. It hides the password and username in the URL. Commented Dec 19, 2019 at 21:46
  • 3
    @Lexelby: The username is "the user" and the password is "and the password" in Spanish. So I'm guessing these aren't real credentials. Commented Mar 20, 2020 at 16:21

6 Answers 6

95

Per https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding and http://en.wikipedia.org/wiki/Basic_access_authentication , here is how to do Basic auth with a header instead of putting the username and password in the URL. Note that this still doesn't hide the username or password from anyone with access to the network or this JS code (e.g. a user executing it in a browser):

$.ajax({ type: 'POST', url: http://theappurl.com/api/v1/method/, data: {}, crossDomain: true, beforeSend: function(xhr) { xhr.setRequestHeader('Authorization', 'Basic ' + btoa(unescape(encodeURIComponent(YOUR_USERNAME + ':' + YOUR_PASSWORD)))) } }); 
Sign up to request clarification or add additional context in comments.

2 Comments

Note: A window.btoa polyfill such as Base64.js will be required for this feature to work in IE6,7,8,9. Also unescape is deprecated as per ECMAScript v3.
@Techbrunch you are mistaken, seanp2k's example works very well, it uses a very known trick to decode Unicode characters to ASCII, it actually uses the fact that (un)escape does not support Unicode, but (dec)encodeURIComponent does..
67

NodeJS answer:

In case you wanted to do it with NodeJS: make a GET to JSON endpoint with Authorization header and get a Promise back:

First

npm install --save request request-promise 

(see on npm) and then in your .js file:

var requestPromise = require('request-promise'); var user = 'user'; var password = 'password'; var base64encodedData = Buffer.from(user + ':' + password).toString('base64'); requestPromise.get({ uri: 'https://example.org/whatever', headers: { 'Authorization': 'Basic ' + base64encodedData }, json: true }) .then(function ok(jsonData) { console.dir(jsonData); }) .catch(function fail(error) { // handle error }); 

1 Comment

Thank you this worked in my react application which used "fetch"
62

Important: This answer is out-of-date. While this answer may have worked for a particular case in 2013, users and passwords in the URL are now deprecated according to Mozilla and RFC 3986.


You can include the user and password as part of the URL:

http://user:[email protected]/index.html 

see this URL, for more

HTTP Basic Authentication credentials passed in URL and encryption

of course, you'll need the username password, it's not 'Basic hashstring.

3 Comments

That solution won't work for Android's Native Browser (Pre KitKat). The username/login form will still popup for your user, so be careful.
They asked about POST request but this suggests a GET request.
This is a neat solution to get the job done!
18

If you are in a browser environment you can also use btoa.

btoa is a function which takes a string as argument and produces a Base64 encoded ASCII string. Its supported by 97% of browsers.

Example:

> "Basic " + btoa("billy"+":"+"secretpassword") < "Basic YmlsbHk6c2VjcmV0cGFzc3dvcmQ=" 

You can then add Basic YmlsbHk6c2VjcmV0cGFzc3dvcmQ= to the authorization header.

Note that the usual caveats about HTTP BASIC auth apply, most importantly if you do not send your traffic over https an eavesdropped can simply decode the Base64 encoded string thus obtaining your password.

This security.stackexchange.com answer gives a good overview of some of the downsides.

Comments

3

no need to use user and password as part of the URL

you can try this

byte[] encodedBytes = Base64.encodeBase64("user:passwd".getBytes()); String USER_PASS = new String(encodedBytes); HttpUriRequest request = RequestBuilder.get(url).addHeader("Authorization", USER_PASS).build(); 

Comments

3

PHP - curl:

$username = 'myusername'; $password = 'mypassword'; ... curl_setopt($ch, CURLOPT_USERPWD, $username . ":" . $password); ... 

PHP - POST in WordPress:

$username = 'myusername'; $password = 'mypassword'; ... wp_remote_post('https://...some...api...endpoint...', array( 'headers' => array( 'Authorization' => 'Basic ' . base64_encode("$username:$password") ) )); ... 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.