Is it possible to send two Authorization Header (Bearer and Basic) - ajax

This is how I setup my ajax with Bearer token for Authorization Header:
let headerParams = {
Authorization: "Bearer " + accessToken,
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
};
let url = "url.com";
$.ajax({
type: "GET",
url: url,
headers: headerParams,
success: function (data) {
},
error: function (error) {
},
});
However on the test server, we also use Basic Auth to access the site. How should I add both Basic and Bearer token in the ajax?
Below is the ajax that works when I only use Basic Authorization Header
let headerParams = {
Authorization: "Basic " + btoa(username + ": " + password),
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
};
let url = "url.com";
$.ajax({
type: "GET",
url: url,
headers: headerParams,
success: function (data) {
},
error: function (error) {
},
});
I tried adding the Bearer and Basic in headerParams like below:
let headerParams = {
Authorization: "Basic " + btoa(username + ": " + password),
Authorization: "Bearer " + accessToken,
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
};
But it does not really work since this will overwrite the previous Authorization. I also added Bearer in headerParams while the Basic auth in beforeSend callback, the same error 401 for missing basic auth and 500 in the backend since backend is unable to authenticate user. Most of the SO questions that I have read only uses one or the other.

You may try sending the header as:
Authorization: Bearer <accessToken>, Basic <btoa(username + ": " + password)>
It actually depends more on the server than the client and whether it accepts the multi value. So, please try it out.
According to the spec RFC7230, section 3.2.2, Field Order:
A sender MUST NOT generate multiple header fields with the same field
name in a message unless either the entire field value for that header
field is defined as a comma-separated list [i.e., #(values)] or the
header field is a well-known exception (as noted below).
A recipient MAY combine multiple header fields with the same field
name into one "field-name: field-value" pair, without changing the
semantics of the message, by appending each subsequent field value to
the combined field value in order, separated by a comma. The order in
which header fields with the same field name are received is therefore
significant to the interpretation of the combined field value; a proxy
MUST NOT change the order of these field values when forwarding a
message.

Related

Microsoft Authentication: How to refresh access token using ajax post?

I've been going through the app authorization steps here https://developer.microsoft.com/en-us/graph/docs/authorization/app_authorization, but can't seem to get the request to work. I consistently get errors saying
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access."
This seems weird as I am including that header.
$.ajax({
type: "POST",
url: url,
crossDomain: true,
data: {
'refreshToken': refreshToken,
'client_id': clientId,
'client_secret': clientSecret,
'redirect_uri': redirect_uri,
'resource': resource
},
dataType: 'json',
beforeSend: function (xhr) {
xhr.setRequestHeader('Access-Control-Allow-Origin', "*");
xhr.setRequestHeader('Access-Control-Allow-Methods', "*");
xhr.setRequestHeader('Access-Control-Allow-Headers', "*");
},
success: function (data, status, headers, config) {
callback(data);
},
error: function (data, status, headers, config) {
console.log('Error getting access token from Microsoft Graph: ' + status + " " + JSON.stringify(data));
}
});
You are using a wrong OAuth2 flow. You should not use the Authorization grand code flow in browser applications, because you cannot keep the client secret safe and the tokens get to the server when a browser requests the redirect URL (the tokens are not in the hash # part of the URL).
That's why Microsoft API doesn't support XHR access to the /token endpoint (by omitting the CORS response headers).
You could consider using the Implicit flow, which is designed for usage in browsers, keeps the tokens safe and doesn't require a client secret.

How do I get Postman to call my Web API

I'm got the pluggin Postman for Chrome. I'm just wondering how I would get Postman to call my web API.
Current, I'm using this AJAX call written in Javascript:
alert("Getting security token");
// Do AJAX call to get security token:
$.ajax({
url: [security token url],
type: "POST",
headers: {
Accept: "application/json"
},
ContentType: "application/x-www-form-urlencoded",
data: {
grant_type: "password",
username: [username],
password: [password]
}
}).done(function(data)
{
var accessToken = data.access_token;
alert(accessToken);
alert("Getting json string.");
// Now that we have access token, send it along with the request for the json string:
$.ajax({
// meta data sent as URL parameters:
url: [url to get json string]
type: "GET",
headers: {
Authorization: "Bearer " + accessToken // access token
},
contentType: false,
processData: false
}).done(function(data)
{
$("#jsonDiv").html(data);
}).fail(function(jqXhr, textStatus, errorThrown)
{
alert("jqXhr = " + JSON.stringify(jqXhr));
alert("textStatus = " + textStatus + ", errorThrown = " + errorThrown);
});
}).fail(function(jqXhr, textStatus, errorThrown)
{
alert("jqXhr = " + JSON.stringify(jqXhr));
alert("textStatus = " + textStatus + ", errorThrown = " + errorThrown);
});
What would I have to do in Postman to accomplish the equivalent of this?
Thanks
There are a few ways to achieve this, but here are some steps to get you started. Create two 2 APIs:
The first to call the "security token url" with the POST method.
Add the header:
Accept: application/json
Then under body, select x-www-form-urlencoded and then add the following keys (and their appropriate values):
grant_type : password
username :
password :
Off the top of my head I think the password grant_type also requires client_id and client_secret, but I don't see that in your code above so maybe you don't need it.
If you hit send you should get an access token back.
In your second API, set the method to GET and supply the appropriate URL. Then in the headers add:
- Authorization : Bearer
If you want to get fancy you can use the test tab to write the access token to an environment variable and then use the result in your second call.
You don't need to get a new access token for each call however so you can just keep using the same token until it expires.
Sorry if you already knew how to do this, I couldn't tell your level of expertise from your question. Hope this helps.

javascript: how to make AJAX call based on the avaiable cURL request

Currently in my web app project, I need to parse the content of a web page, and after some searching, I found that Mercury Web Parser API is quite suitable for me.
And I have some experience with such kind of third party APIs, generally speaking I can get my desired result.
But for this API, I can't find documentation about the API usage on the official website.
Based on the my study, it provide two methods:
first is cURL as following:
curl -H "x-api-key: myapikey" "https://mercury.postlight.com/parser?url=https://trackchanges.postlight.com/building-awesome-cms-f034344d8ed"
the myapikey is the API key I get from the website. Then I can get the result in JSON format, which is the main content of the web page specified by the url parameter. It works well for me, I mean the cURL method.
And on the website, it said that the second method is HTTP call, which is just what I need:
GET https://mercury.postlight.com/parser?url=https://trackchanges.postlight.com/building-awesome-cms-f034344d8ed
Content-Type: application/json
x-api-key: myapikey
So based on my understanding, I use jquery AJAX method to do this as following:
var newurl = "https://mercury.postlight.com/parser?url=http://www.businessinsider.com/joel-spolsky-stack-exchange-interview-2016-12&x-api-key=myapikey"
$.ajax({
url: newurl,
dataType: "jsonp",
success: function(data){
console.log(data.title);
}
})
here I made JSONP request because of the Cross origin issue.
But now I face 401 error message (401 Unauthorized. The request has not been applied because it lacks valid authentication credentials for the target resource)
For now my guess is that the apikey is not correctly passed to server. So based on the cURL's successful call, can I get the correct format for AJAX call?
Update:
Based on the following answers ,I tried to set the request header as following:
$.ajax({
url: newurl,
dataType: "jsonp",
beforeSend: function(xhr){
console.log(apiKey);
xhr.setRequestHeader('x-api-key', apiKey);
},
/*
headers: {
"x-api-key": "M1USTPmJMiRjtbjFNkNap9Z8M5XBb1aEQVXoxS5I",
"contentType": 'application/json'
},
*/
success: function(data){
console.log("debugging")
console.log(data.title);
},
error: function (error) {
console.log(error)
}
})
I tried both beforeSend and headers. But still can't work and get the following trackback error message:
send # jquery.js:8698
ajax # jquery.js:8166
addNewArticle # topcontroller.js:18
fn # VM783:4
e # angular.js:281
$eval # angular.js:147
$apply # angular.js:147
(anonymous) # angular.js:281
dispatch # jquery.js:4435
elemData.handle # jquery.js:4121
And for the last send function, still 401 error.
But the ajax error handling part shows that the readyState:4 and status: 404 result. So what's going here.
For your question, the curl request is sending a header which you have attached as part of the query string in your $.ajax request.
Try the following instead (using beforeSend + xhr) :
// broke this string down so you don't have to scroll
var newurl = "https://mercury.postlight.com/parser?" +
"url=http://www.businessinsider.com/" +
"joel-spolsky-stack-exchange-interview-2016-12";
// set your api key
var apiKey = "<your api key>";
$.ajax({
url: newurl,
dataType: "json",
beforeSend: function(xhr){xhr.setRequestHeader('x-api-key', apiKey);},
success: function(data){
console.log(data.title);
}
})

Symfony 3, "ajax request" with fetch API, and CSRF

In twig i generate a csrf token ({{ csrf_token('my_intention') }}).
In Javascript i call a controller with ajax, in fact with the Fetch API (Ajax xmlHttpRequest tried too), POST request. Argument name containing the token passed in the request is 'token=abcdef...'.
AJAX:
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function (data) {
console.log(data);
};
httpRequest.open('POST', el.getAttribute("data-url"));
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
httpRequest.send(.......);
Fetch API:
fetch(el.getAttribute('data-url'), {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'token=' + encodeURIComponent(el.getAttribute('data-token'))
}).then(data => data.text()).then(data => {...}
In the controller action called i get the token sent as data from the POST request. I check the token like this in the controller:
$token = $request->request->get('token');
if (!$this->isCsrfTokenValid('my_intention', $token)) {
throw new InvalidCsrfTokenException("error csrf 2");
}
But Symfony say the token is not valid.
I'm not sure but i think token is not found in session variable. In isTokenValid() $this->storage->hasToken($token->getId()) return false.
In the browser, if i call the url directly, it's ok.
In twig i set the url to call in a data attribute like this data-url="{{ path('_check', {'id': transaction.id}) }}", then i read this data attribute from javascript and pass it to ajax/fetch function.
I tried ajax with jQuery $.post(... and it works. The only difference is Cookie:PHPSESSID... in the request header with jQuery not on my original code.
I don't understand, what is wrong with my code ?
Symfony 3.1.3
EDIT: resolved: i didn't pass credentials in headers request, so, no way for Symfony to find session and check token:
fetch(el.getAttribute('data-url'), {
method: 'post',
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest"
},
body: 'token=' + el.getAttribute('data-token'),
credentials: 'include'
}).then(data => data.text()).then(data => {
Even if you found an answer to your issue, I recommend you to take a look at this bundle which handles the token verification based on a Cookie which is defined server-side and that you should pass in each asynchronous request.
https://github.com/dunglas/DunglasAngularCsrfBundle

Spotify API key block / expires to fast

I've request a API key to get the users playlist. All my code works, but the only problem is that the key block or expires to fast. I use this code:
$.ajax({
url: "https://api.spotify.com/v1/users/" + $("#gebruiker").val() + "/playlists",
headers: {
Authorization: "Bearer " + my key
},
Host: "api.spotify.com",
Accept: "application/json",
type: "GET",
success: function (data){
//code
},
error: function (data) {
//code
}
});
When blocks or expires the API key from Spotify and what can you do about this?
Access tokens are deliberately set to expire after a short time, after which new tokens may be granted by supplying the refresh token originally obtained during the authorization code exchange. As explained in the https://developer.spotify.com/web-api/authorization-guide/

Resources