I'm trying to create a cross domain request with angular 1.4.7. I'm pretty new to this topic and especially in this scenario I'm not able to find any help via google.
Environment:
I try to call from the angular app A served by www.a.com the restful api's offered by the server B served by www.b.com.
The thing im struggling over is, that I have to authorise myself a via token in the http post. This token constelation should look like:
{
"account": {
"hashcode": "somehashcode"
},
"hashkey": "somehashkey"
};
I tested the api with Postman an it works well, but I'm failing to realise it with angular.
postman successful try picture 1
postman successful try picture 2
To enable cors in my app.js:
.config(['$httpProvider', function($httpProvider){
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common["X-Requested-With"];
}]);
An my request:
$http({
url: 'http://evori-api.azurewebsites.net/api/handshake',
method: 'POST',
data: authtoken,
headers: {
'Content-Type': 'application/json'
}
})
.then(function(data, status) {
console.log(data + status);
}, function() {
});
Any help would be appreciated. Even if you just got an article or blog that explains how such things should be done. I know there is probably just a dumb mistake or something but it drives me crazy.
Thanks a lot.
It seems like the problem wasn't me or my api call. The source of the problem was, that the server didn't handle the OPTION call that leads each cors request.
Related
I come to you in a time of great need. I've spent like a week on this and still can't figure it out. Please help.
Here is what I want to do:
I've got a WordPress website (http://test/test.wp/) on which you can do the following API call right in the browser when you are logged in:
$.ajax({
url: 'http://test/test.wp/wp-json/wp/v2/users/me',
method: 'GET',
beforeSend: function(xhr){
xhr.setRequestHeader( 'X-WP-Nonce', wpApiSettings.nonce );
}
}).done(function(response){
console.log(response);
}).fail(function(response){
console.log( response.responseJSON.message );
});
And it works just fine. You get a Json about the current user (I just need the ID)
Now, I got another website (subdomain) written in React (http://app.test) and I am trying to pretty much do the same GET request to WordPress to grab the ID of the currently logged in User.
The sites are interconnected and I am sort of trying to imitate a SSO between WordPress and React by simply grabbing the ID of the currently logged in user in WordPress and using it in the react subdomain
To achieve this I've taken care of the CORS so I can make GET request from React to WordPress with no problems.
I also shared my WordPress wordpress_logged_in_cffb670352ad40cd796ad890d27ee701 cookie with the React subdomain so I've got access to that (which, from what I understand is the only cookie needed to keep you authenticated)
So, with all of that said why is my request from React failing?
Axios({
method: 'get',
url: 'http://test/test.wp/wp-json/wp/v2/users/me',
headers: {
'X-WP-Nonce': '659cbfeec0', // <= It's needed to use the WP Api and it's correct. I mannually grabed it from WP with wpApiSettings.nonce
withCredentials: true, // <= From what I understand is the only thing needed to send the `wordpress_logged_in_cffb670352ad40cd796ad890d27ee701` cookie ???
},
})
.then(response => console.log(response))
.catch(err => console.log(err));
So why then the answer that I get is a 403 (Forbidden)?:
code: "rest_cookie_invalid_nonce"
data: {status: 403}
statusText: 'Forbidden'
message: "Cookie verification failed"
You can say that the answer is in the response that I get, but I really have no idea why that's the case.
Please help.
Desperate Coder.
I was passing the 'with-Credentials' in the Headers and was not sending the cookies in the request because of that.
The correct way of doing it is:
Axios.get(
'http://test/test.wp/wp-json/wp/v2/users/me',
{
withCredentials: true,
headers: { 'X-WP-NONCE': 'Your_Nonce' },
}
)
I am using Django with Angular JS to access the Google Drive API. I am following this document from Google. The FLOW.step1_get_authorize_url() gives me the URL similar to the sample URL mentioned on the page. But the problem is that after return HttpResponseRedirect(authorize_url) the browser does not redirect to the authorize_url and gives the error as shown in the picture below (Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8000' is therefore not allowed access. The response had HTTP status code 405).
But if I copy pasted the URL, it works fine.
The oauth2 function looks like this.
def index(request):
FLOW = flow_from_clientsecrets(
settings.GOOGLE_OAUTH2_CLIENT_SECRETS_JSON,
scope='https://www.googleapis.com/auth/drive',
redirect_uri='http://127.0.0.1:8000/oauth2callback/'
)
FLOW.params['access_type'] = 'offline'
authorize_url = FLOW.step1_get_authorize_url()
return HttpResponseRedirect(authorize_url)
And here is the oauth2callback function.
def auth_return(request):
credential = FLOW.step2_exchange(request.GET)
return HttpResponseRedirect("/mycustomurl")
I used this to enable CORS in the Django Server Side. Here is my part of service in Angular that makes the call to oauth2.
(function () {
'use strict';
angular.module('myApp')
.service('myService', function ($http) {
this.saveToDrive = function (startYear, endYear, shape) {
var config = {
params: {
start: '1999',
end: '2002',
action: 'download-to-drive'
},
headers: {
'Access-Control-Allow-Origin': '*',
'X-Requested-With': null
}
}
var promise = $http.get('/oauth2/', config)
.then(function (response) {
return response.data;
});
return promise;
};
});
})();
Please suggest what am I missing here. Any help or suggestions are highly appreciated.
I found it be a minor design issue rather than the code issue. I separated the logic that sends the oauth2 request to the client, and after the oauth2 request, I sent request to internal API with the params options. And now it's working fine.
I am facing a weird issue. I am running my angularjs app in nodejs server locally which calls a POST API from my app located on Google App Engine. The API is configured with all CORS headers required as follows:
def post(self):
self.response.headers.add_header("Access-Control-Allow-Origin", "*")
self.response.headers.add_header("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE,OPTIONS")
self.response.headers.add_header("Access-Control-Allow-Headers", "X-Requested-With, content-type, accept, myapp-domain")
self.response.headers["Content-Type"] = “application/json; charset=utf-8”
GET requests to the API work without issues.
POST requests to the API work but ONLY when I send the post data as a 'string of params' and NOT when post data is sent as an object which is the right way to do. Eventually I need to be able to upload pictures using this API so the first solution below might not work for me. Please help!
METHOD 1: This works:
postMessageAPI = "https://myapp-qa.appspot.com/message";
var postData = "conversationid=1c34b4f2&userid=67e80bf6&content='Hello champs! - Web App'";
var postConfig = {
headers: {
"MYAPP-DOMAIN" : "myapp.bz",
'Content-Type': 'application/json; charset=UTF-8'
}
};
$http.post(postMessageAPI, postData, postConfig).
success(function(data){
$log.log("POST Message API success");
}).
error(function(data, status) {
$log.error("POST Message API FAILED. Status: "+status);
$log.error(JSON.stringify(postData));
});
METHOD 2: This fails:
postMessageAPI = "https://myapp-qa.appspot.com/message";
var postData = ({
'conversationid' : '1c34b4f2',
'userid' : '67e80bf6',
'content' : 'Hello champs! - Web App'
});
var postConfig = {
headers: {
"MYAPP-DOMAIN" : "myapp.bz"
'Content-Type': 'application/json; charset=UTF-8'
}
};
$http.post(postMessageAPI, postData, postConfig).
success(function(data){
$log.log("POST Message API success");
}).
error(function(data, status) {
$log.error("POST Message API FAILED. Status: "+status);
$log.error(JSON.stringify(postData));
});
When I use METHOD 2 it fails with the following error in the console:
XMLHttpRequest cannot load https://myapp-qa.appspot.com/message.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://0.0.0.0:8000' is therefore not allowed access.
Please let me know if you have any solution. Thanks in advance.
The issue is most likely with Angular sending a pre-flight OPTIONS request to check the access headers from the server. I am not sure how OPTIONS requests are handled in your API, but I am betting these headers are not being added. I suggest installing Fiddler to monitor the actual requests to see what is going on with the headers. You may only be adding them to your POST responses.
See this answer for details on why METHOD 1 may work in this scenario, while METHOD 2 does not.
Here are some more details about pre-flight requests.
Is there a workaround to sending POST request cross-domain via Angular, besides using a proxy? Below request is refused, ie: OPTIONS , net::ERR_CONNECTION_REFUSED It's just form data I want to submit to friend's local server for school project.
$scope.postJSON = function(){
var objJson = angular.toJson($scope.event);
console.log(angular.toJson($scope.event));
delete $http.defaults.headers.common['X-Requested-With'];
$http({
method: 'POST',
url: 'http://friendslocalserver.com',
data: objJson
}).success(function() {
console.log("POST Json object worked!");
}).error(function(){
console.log("POST Json object failed!");
});
}
You don't need to configure AngularJS for CORS. Your friend's server needs to support CORS requests and probably whitelist your domain. This depends heavily on the HTTP server used.
I was trying to access api running in localhost using angular $resourses, chrome console gives me error saying ERR_INSECURE_RESPONSE.
I tried disabling web security in chrome. still same error. here is the angular factory that i used. How can I bypass this error and test my app.
ImpactPortal.factory('apiFactory', function ($resource) {
return $resource('https://localhost:8443/mifosng-provider/api/v1/client_impact_portal', {}, {
query: {
method: 'GET',
params: {},
isArray: true
}
})
});
Enabling CORS in Angular.js
var myApp = angular.module('myApp', [
'myAppApiService']);
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);
A server supporting CORS must respond to requests with several access control headers:
Access-Control-Allow-Origin: "*"
By default, CORS requests are not made with cookies. If the server includes this header, then we
can send cookies along with our request by setting the withCredentials option to true.
Access-Control-Allow-Credentials (optional)
If we set the withCredentials option in our request to true, but the server does not respond
with this header, then the request will fail and vice versa.
Only try this:
Go to https://[your-domain].com and then chrome block you with the famous page:
Your connection is not private
So go down to ADVANVCED and then proceed.
Your certificate is probably self-signed.
Remember to do that for each Chrome session.
You must authenticate first and then send each request along with the auth token.
I am using RestAngular so my settings might look a little different from what you are working on.
This will go in your application config :-
RestangularProvider.setDefaultHeaders({ 'X-Mifos-Platform-TenantId': 'default' });
and something like this will go in your controller/service
var login = Restangular.all('authentication?username=mifos&password=password').post().then(function(user) {
console.log(user);
}, function() {
console.log("There was an error saving");
});
Error 501 (net::ERR_INSECURE_RESPONSE) - 501 Not Implemented
The server either does not recognize the request method, or it lacks the ability to fulfill the request. Usually this implies future availability (e.g., a new feature of a web-service API).
Can you confirm that curl request is working fine
curl -k --user damien#email.com:password https://localhost:8443/mifosng-provider/api/v1/client_impact_portal
If it is working fine:
ImpactPortal.factory('apiFactory', function ($resource) {
return $resource('https://localhost:8443/mifosng-provider/api/v1/client_impact_portal', {}, {
query: {
method: 'JSONP',
params: {},
isArray: true
}
})
});
Try following this tutorial that consume an external API: http://www.toptal.com/angular-js/a-step-by-step-guide-to-your-first-angularjs-app