Cross-Domain ajax error with bearer authentication - 401 Unauthorized - ajax

So... i'm making a cross domain (CORS) call. When i initially make it on the page, it works just fine (noting that cross-domain issues aren't really a problem), but when i make another request later to the same server adding a bearer authorization token to the header, it is failing with a 401 Unauthorized.
Also, when i run this code from the same domain, both calls run successfully (identifying that the token is ok...)
Thoughts?
$.ajax({
url: apiPath.userMetaUrl(),
xhrFields: {
withCredentials: true
},
cache: false,
error: function (xhr, ajaxOptions, thrownError) {
console.log("url: " + apiPath.userMetaUrl());
console.log("fn loadUserMetaData xhr.status: " + xhr.status);
console.log("fn loadUserMetaData xhr.responseText: " + xhr.responseText);
console.log("fn loadUserMetaData thrownError: " + thrownError);
},
dataType: "json",
jsonpCallback: "callback",
beforeSend : setHeader,
success: function (data) {
//woohoo!
}
}
function setHeader(xhr) {
xhr.setRequestHeader('Authorization', 'Bearer ' + authenticatedInfo.access_token);
}
Again, running this code from same domain as apiPath.userMetaURL() works fine. On a different domain, the initial call without adding request header works fine. Access-Control-Allow-Orign has the cross-domain URL added. Access-Control-Allow-Headers has Authorization added.
xhr.status returns 0 and responseText/thrownError are blank.

JSONP != ajax
These requests you are making are simply adding <script> tags to your DOM. It's just wrapped in an ajax syntax for ease of use. You can't modify the request headers in this fashion. You need to create a CORS ajax request, and configure your server to handle them.
Executing jsonp requests on the same domain though... I believe jQuery just uses an xmlHttpRequest though. For cross-domain, it uses <script> tags. This would explain the behavior you are seeing.
Consider the following.
$.ajax({
url: 'http://google.com',
dataType: 'jsonp',
beforeSend: function(xhr) { xhr.setRequestHeader('foo', 'bar'); }
});
Look at your network traffic. It will create the request, but you will not see the foo header.

Related

NTLM is automatically added instead of Bearer in AJAX Calls while calling API

In my website, something weird is happening while running in Internet Explorer. My website and API are hosted separately. API is having anonymous authentication with token based authorization. MVC website is having windows authentication. Most of the times everything works as expected. But sometimes what happens is while calling the API from javascript my Authorization is headed changed to NTLM instead of Bearer. I am giving some screenshots of the same scenario.
Successful API Call:
401 Unauthorized Call:
My Ajax is as follows:
$.ajax({
url: src,
type: 'GET',
cache: false,
async: true,
data: (parameters),
headers: {
'Authorization': 'Bearer ' + sessionStorage.getItem('token')
},
contentType: 'application/json'
dataType: 'json',
success: successCallback,
error: function (xhr, textStatus, errorThrown) {
ErrorPopup("error occur");
}
,
beforeSend: function (xhr, settings) { xhr.setRequestHeader('Authorization', 'Bearer ' + sessionStorage.getItem('token')); }
});
I have debugged all API calls and always authorization header is set to Bearer ... still, somehow some way NTLM is taking control of it and making my API calls unauthorized. Please share some insights how could I solve this. I cannot change authentication in IIS as it's beyond my control. If you need any more inputs I can provide that too.
It looks like there is a redundancy in your authorization headers (headers array + beforeSend). Remove one of them and test (reason : RFC 2616 says that several headers with the same name should be concatenated on the same line, and maybe the server is replying with an NTLM authorization request to such a request that it doesn't allow).

get the information from Naver LINE API through http request

I have a question on the chat app, Naver LINE. There is an API that provides login authentication called LINE login.
I've follow the instructions on the documents and run the querystring and I got a callback URL that gives me the code look like this,
https://sample.com/callback?code=b5fd32eacc791df&state=123abc
Now, the document says I need to use the code in a http request using post method. I got the following,
XMLHttpRequest cannot load https://api.line.me/v1/oauth/accessToken/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://xxxxxxxxxxxxxxxxxxxxxxxxxxx' is therefore not allowed access. The response had HTTP status code 404.
Below is the request I wrote,
$.ajax({
url: "https://api.line.me/v1/oauth/accessToken/",
type: "POST",
xhrFields: {
withCredentials: true
},
crossDomain: true,
data: JSON.stringify(data),
dataType: "json",
success: function (response) {
var resp = JSON.parse(response)
alert(resp.status);
},
error: function (xhr, status, state, error) {
alert("error", xhr, status);
console.log(xhr);
console.log(status);
console.log(state);
console.log(error);
}
});
data is the credentials I put in so LINE would pass me the user's information.
Is there anything I did wrong? If so, how can I fix this?
Thanks ahead.

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);
}
})

Logging into an expressjs app with CORS

I have expressjs sitting on a nodejs server and I have a client side cordova app making ajax requests to certain routes.
This is fine until I need to make a POST request to login using passportjs, there is a 302 redirect that takes place so I get this 302 Moved Temporarily when making this call
$('body').on('submit', '#logIn', function(e){
e.preventDefault();
var formData = $(this).serialize();
$.ajax({
url: "http://mydomain.io:3300/login",
data: JSON.stringify(formData),
type: "POST",
crossDomain: true,
dataType: "json",
async: true,
success: function(response){
alert('succeeded!');
console.log(response);
alert(response);
},
failure: function(message){
alert("failed");
console.log(message);
alert(message);
}
});
});
So my question is how is it possible using CORS to login to the app using client side ajax?
CORS is not your problem here.
Passport wants to redirect your user (based on the values you've passed to passport.authenticate). For instance:
app.get('/auth/facebook/callback',
passport.authenticate('facebook', { successRedirect: '/',
failureRedirect: '/login' }));
Passport will tell the browser to redirect to / or /login by returning a 302. You can remove the redirect by removing the second parameter to passport.authenticate:
app.get('/auth/facebook/callback',
passport.authenticate('facebook'));
This will call next() on successful authentication (and return 401 otherwise).
The examples here use FacebookStrategy, but it works with any strategy.

Basic Authentication and jQuery/ajax call

I would like to call OData .NET web service that authenticates users via basic authentication.
I use following ajax call:
var fullUri = APIUri + "?$format=json";
$.ajax({
url: fullUri,
contentType: "application/json",
dataType: "jsonp",
type: 'GET',
jsonp: '$callback',
beforeSend: function setHeader(xhr) {
xhr.setRequestHeader('Authorization', token);
},
success: callback,
error: function (xhr, ajaxOptions, thrownError) {
alert(thrownError);
},
});
The results are unusable for me:
Calls are blocked because of CORS (until I will paste API url and try to load it in chrome). I tried local html file and html file uploaded to the same domain/port, but authentication fails (according to Chrome console).
Once I enter service URL into chrome address bar, I am asked to provide login name and password by Chrome. If I enter them, they are cached and used even I assign them in beforeSend. How to blocks this behavior?
I've tried a lot of examples how to configure jsonp, headers etc, but did not find working solution yet.
IIS server response header is also configured using "Access-Control-Allow-Origin" value="*".
You can set the HTTP Password and Username in the AJAX Call directly:
$.ajax({
url: fullUri,
contentType: "application/json",
username: <login>,
password: <password>,
...
Use the following to support CORS:
jQuery.support.cors = true;
Regarding the call, are you using HTTPS? Is the certificate valid?

Resources