unable to send Cross domain ajax requests with Angular - angularjs

I am facing a problem in sending cross domain request to a web api(api.worldbank.org) . It says
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://127.0.0.1' is therefore not allowed access.
So as someone suggested, i used this-
app.config( function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
);
but still the error is same and also no change occurs in headers with or without adding this code.
Complete code is this-
'use strict';
var app=angular.module('myapp',[]);
app.config( function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
);
app.factory('dataFactory',function($http){
var O={};
O.getLifeExpectancy=function(){
var dataToSend={};
$http({
method:'GET',
url:'http://api.worldbank.org/countries/in/indicators/SP.DYN.LE00.IN?format=json&date=2000:2015'
}).then(function(data){
dataToSend=data;
});
return dataToSend;
};
Am i doing something wrong ?
is $http and $httpProvider two different things, because no change is reflected in headers with or without app.config code.
here are my headers in both the situations-
Accept:application/json, text/plain, / Accept-Encoding:gzip,
deflate, sdch Accept-Language:en-US,en;q=0.8 Cache-Control:max-age=0
Connection:keep-alive Host:api.worldbank.org Origin:127.0.0.1
Referer:127.0.0.1/myApp/ User-Agent:Mozilla/5.0 (Windows NT
10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36

This messages says that your server-side code doesn't allow request from different domain, so the best solution is to enable CORS with header Access-Control-Allow-Origin: '*' at the server-side.
EDIT: If your Angular app will run in browser - you need to set CORS server-side or just make some proxy on your domain (some browsers on default block such requests).
But if you're doing Cordova/PhoneGap mobile app you'll be able to disable it in config.xml so currently for testing purposes you can just disable it in your browser.

Related

React-call to "Asp.Net Core with identity server" gives CORS-errors

Ill try to keep this short to save digital rain forest. Please ask If I missed any details.
I have an "asp .net 3.1 core + react"-project template in VS, with built in Identity server. This works ok, but I now want to do my react project in a separate project. So I started a new create-react-app-project.
So, from my new react project, when I call OidcConfigurationController. The controller method is called and I can step through the code on server side. Then I get a client error "Failed to fetch", which, by internet wizdom, seems to indicated CORS-error.
This is what I got when I inspect the header in chrome dev toolbar->network
Request URL: https://localhost:5001/authentication/_configuration/MyProject.Web
Referrer Policy: strict-origin-when-cross-origin
:authority: localhost:5001
:method: GET
:path: /authentication/_configuration/MyProject.Web
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9,sv;q=0.8
origin: http://localhost:3000
referer: http://localhost:3000/
sec-ch-ua: "Google Chrome";v="87", " Not;A Brand";v="99", "Chromium";v="87"
sec-ch-ua-mobile: ?0
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
These are relevant lines in startup.cs
ConfigureServices()
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
//builder.WithOrigins("http://localhost:3002/", "https://localhost:3001")
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
services.AddSingleton<ICorsPolicyService>((container) => {
var logger = container.GetRequiredService<ILogger<DefaultCorsPolicyService>>();
return new DefaultCorsPolicyService(logger)
{
AllowAll = true
};
});
Configure()
app.UseCors(MyAllowSpecificOrigins); // I also tried to switch order on these 2 rows
app.UseIdentityServer();
Nothing I do here seems to change the Referrer Policy in the header, still get the exact same message
The React-call is just a plain fetch(address-of-the-controller-that-it-hits).
I have also tried to start a new Server Side-project (asp net core api) and set same CORS-policy, I can call this api from my react client without getting any errors)
So, in the request, you see the origin: http://localhost:3000 header is used. That is the source for the CORS request. But the request is for this URL:
https://localhost:5001/authentication/_configuration/MyProject.Web
Could it not be that there's a redirect from insecure HTTP to HTTPS that is interfering?
Do make sure you set the CORS settings in IdentityServer as well.
See the CORS documentation for more details.
As side note, IIS might cause CORS issues as well, see this answer for details:
IIS hijacks CORS Preflight OPTIONS request

CSRF token missing or incorrect. Django + AngularJS

I'm getting CSRF token missing or incorrect error while doing a POST request to a remote django api from my localhost machine.
My settings on AngularJS:
.config(['$httpProvider', function($httpProvider){
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
but im still getting the CSRF token missing or incorrect error.
I check what headers are being sent and apparently angular is not sending HTTP_X_CSRFTOKEN.
But I can see that the cookie csrftoken=something is sent.
Does anyone know what is going on?
Request Header
POST /s/login/ HTTP/1.1
Host: server.somewhere.io:8000
Connection: keep-alive
Content-Length: 290
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: http://localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
Content-Type: application/json;charset=UTF-8
Referer: http://localhost/thesocialmarkt/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en;q=0.8,en-US;q=0.6,pt-BR;q=0.4,pt;q=0.2
Cookie: csrftoken=hiYq1bCNux1mTeQuI4eNgi97qir8pivi; sessionid=1nn1phjab5yd71yfu5k8ghdch2ho6exc
As #Chris Hawkes pointed to this stackoverflow answer given by #Ye Liu
Since the angular app isn't served by django, in order to let the
cookie to be set, angular app needs to do a GET request to django
first.
I verified that as long as you don't make http get request, csrftoken cookie doesn't get set. So only
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
would not work. You first need to make if not real then mock http get request to django rest_framework.
Update: Your comments pushed me to further study it, Please read this blog where is has mentioned as,
CLIENT-SIDE GENERATED CSRF-TOKENS. Have the clients generate and send
the same unique secret value in both a Cookie and a custom HTTP
header. Considering a website is only allowed to read/write a Cookie
for its own domain, only the real site can send the same value in both
headers
So lets try with this single request first.
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
where you are injecting $cookies to the controller/service.
If it works then may be writing interceptors would be good choice, and would help you to debug as well.
I am sure you are using AngularJs version at least 1.2, See this changeset
and in recent commit Angular http service checking csrf with this code,
var xsrfValue = urlIsSameOrigin(config.url)
? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName]
: undefined;
if (xsrfValue) {
reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
}
So it's necessary that you are sending same token which is present in cookie.
Further to analyse use developer tool of your browser to see request/response with the http request and analyse headers and cookies.
if you are using $http in AngularJS for ajax request and if you are facing any CSRF token issue then use this:
$http.defaults.xsrfCookieName = 'csrftoken';
$http.defaults.xsrfHeaderName = 'X-CSRFToken';

Cross origin issue with ajax, angular and Zuul

I have zuul server implemented which does the routing to all my microservices. I have a seperate UI project which is in angular. I am trying to make an AJAX call from the UI app to a specific microservices which routes through Zuul but I am getting this error.
XMLHttpRequest cannot load http://localhost:8006/user/v1/userassociations. 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:63342' is therefore not allowed access. The response had HTTP status code 403.
But When I directly try to hit the api in local host which is hosted at http://localhost:4444/user/v1/userassociations it works perfectly fine. I have the below CORS configuration added to the actual api.
#Override
public void addCorsMappings(final CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("PUT", "GET", "DELETE", "OPTIONS", "PATCH", "POST");
}
The problem is only happening when i try to hit the api via zuul I tried to add the same configuration to Zuul but it is not working.
I know it is the same origin issue but there must be a solution our microservices are suppose to go public so anyone can make the request from any domain.
Below is the Working AJAX call:- if i change the url to http://localhost:8006/user/v1/userassociations which is via zuul i get the cross origin.
var service = {};
service.userContextCall = function()
{
return $http({
url:'http://localhost:4444/user/v1/userassociations',
method: 'GET',
headers: {'Content-Type':'application/json',
'userContextId':'1234567890123456'}
}).success(function(response){
return response;
}).error(function(error){
return error;
});
};
return service;
Header that Iam receiving for when i hit the api via Zuul.
Request URL:http://localhost:8006/user/v1/userassociations
Request Method:OPTIONS
Status Code:403 Forbidden
Remote Address:[::1]:8006
Response Headers
view source
Allow:GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length:20
Date:Tue, 23 Feb 2016 18:51:15 GMT
Server:Apache-Coyote/1.1
X-Application-Context:apigateway:8006
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, usercontextid
Access-Control-Request-Method:GET
Connection:keep-alive
Host:localhost:8006
Origin:http://localhost:63342
Referer:http://localhost:63342/icpAccountHolder/app/index.html
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
Header when i direclty hit the api the working one.
Request URL:http://localhost:4444/user/v1/userassociations
Request Method:GET
Status Code:200 OK
Remote Address:[::1]:4444
Response Headers
view source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://localhost:63342
Content-Type:application/json;charset=utf-8
Date:Tue, 23 Feb 2016 18:54:19 GMT
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
Vary:Origin
X-Application-Context:userassociations-v1
Request Headers
view source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:localhost:4444
Origin:http://localhost:63342
Referer:http://localhost:63342/icpAccountHolder/app/index.html
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
userContextId:1234567890123456
Can anyone help me with this.
The fix seems to be using the ANGEL.SR6 spring cloud version instead of BRIXTON. But In case you want to use Brixton this is what i wrote to override the CORS filter in Zuul.
#Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource= new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowCredentials(true);
corsConfig.addAllowedOrigin("*");
corsConfig.addAllowedHeader("*");
corsConfig.addAllowedMethod("OPTIONS");
corsConfig.addAllowedMethod("HEAD");
corsConfig.addAllowedMethod("GET");
corsConfig.addAllowedMethod("PUT");
corsConfig.addAllowedMethod("POST");
corsConfig.addAllowedMethod("DELETE");
corsConfig.addAllowedMethod("PATCH");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfig);
return new CorsFilter(urlBasedCorsConfigurationSource);
}

CSRF Cookie not set when posting request with AngularJs - Django Backend

I'm building a web app with angularjs and django and I'm submitting form via Ajax request.
My problem is that when posting an Ajxa request with angular (ng-file-upload precisely) the csrfmiddlewaretoken expected by django is not set.
From my lectures on angular documentation and other forums I ended up with the following configuration.
In the config part of angular :
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$httpProvider.defaults.withCredentials = true;
and in my controller the code for sending the request is :
Upload.upload({
url: 'http://localhost:8000/image',
headers: {
'X-CSRFToken': $cookies['csrftoken']
},
data: {file: file}
})
With that code the request send has the following headers :
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,de;q=0.2,fi;q=0.2
Connection:keep-alive
Content-Length:16582
Content-Type:multipart/form-data; boundary=----WebKitFormBoundarybWo821vSwcejTATP
Cookie:csrftoken=bC2UpXurGXAg3AUZgSqMVlUs8TKfussS
Host:localhost:8000
Origin:http://127.0.0.1:8000
Referer:http://127.0.0.1:8000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36
X-CSRFToken:UeSt4LoqgU9L28JQBdVbS2IJJXOMQK6n
However for django to be able to handle csrf protection correctly the following header is missing
Cookie:_ga=GA1.1.1358238168.1447425523; XSRF-TOKEN=zWIM6q7O2Nz3PLm8TMUJSLFVRF8bKUbr; csrftoken=UeSt4LoqgU9L28JQBdVbS2IJJXOMQK6n
So far and despite having seen a lot of forums about this topic I didn't manage to set this header. if I try to set it programmatically via :
Upload.upload({
url: 'http://localhost:8000/image',
headers: {
'Cookie': 'csrftoken='+$cookies['csrftoken']
},
data: {file: file}
})
I end up with the following error in my console :
Refused to set unsafe header "Cookie"
My problem is really how to configure the cookie header from the client side. My django code is fine.
I have been struggling with this for quite a time now. Any help would be appreciated ! Thanks
If you added in the csrftoken to client headers: {'X-CSRFToken': $cookies['csrftoken']} means your client is most probably ready, but for security matter if you interact with django api from external application he will still block the request returning unsafe header "Cookie".
try the following configuration to allow the cross site request over your app:
pip install django-cors-headers
and then add it to your installed apps in your settings.py:
INSTALLED_APPS = (
...
'corsheaders',
...
)
You will also need to add a middleware class to listen in on responses and make sure you respect the order as follow:
MIDDLEWARE_CLASSES = (
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
)
and finally add this settings variable:
CORS_ORIGIN_ALLOW_ALL = True
This should be enough but for more customized configuration you can check django-cors-headers

AngularJS - How to connect to Twitter application-only authentication via Oauth2?

I try to receive an accessToken from the Twitter application-only authentication but I keep receiving a 405 (Method Not Allowed) response from the twitter api. Anybody knows how to solve this? I'm desperately stuck..
I am aware of the fact that:
- best practice is doing this from serverside, but I wanted to try this out with angular on client side
- X-Requested-With should be deleted from the header
This is the factory I created:
twitterServices.factory('Connect', function($http){
var factory = {};
var baseUrl = 'https://api.twitter.com/';
var bearerToken = function(){
var consumerKey = encodeURIComponent('****');
var consumerSecret = encodeURIComponent('****');
var tokenCredentials = btoa(consumerKey + ':' + consumerSecret);
return tokenCredentials;
};
factory.fetchAccessToken = function(scope){
var oAuthurl = baseUrl + "oauth2/token";
var headers = {
'Authorization': 'Basic ' + bearerToken(),
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
};
$http.defaults.useXDomain = true;
delete $http.defaults.headers.common['X-Requested-With'];
$http({method: 'POST', url: oAuthurl, headers: headers, data: 'grant_type=client_credentials'}).
success(function(data, status){
scope.status = status;
scope.data = data;
}).
error(function(data, status){
scope.status = status;
scope.data = data || "Request failed";
});
};
factory.fetchTimeLine = function(scope){
scope.fetchAccessToken();
//the rest
};
return factory;
});
This is the header request/response in Chrome:
Request URL:`https://api.twitter.com/oauth2/token`
Request Method:OPTIONS
Status Code:405 Method Not Allowed
Request Headersview source
:host:api.twitter.com
:method:OPTIONS
:path:/oauth2/token
:scheme:https
:version:HTTP/1.1
accept:*/*
accept-encoding:gzip,deflate,sdch
accept-language:en-US,en;q=0.8
access-control-request-headers:accept, authorization, content-type
access-control-request-method:POST
origin:`http://localhost`
referer:`http://localhost/test/app/
user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.69 Safari/537.36
Response Headersview source
content-length:0
status:405 Method Not Allowed
version:HTTP/1.1
My Console shows the following:
OPTIONS https://api.twitter.com/oauth2/token 405 (Method Not Allowed) angular.js:9312
OPTIONS https://api.twitter.com/oauth2/token Origin http://localhost is not allowed by Access-Control-Allow-Origin. angular.js:9312
XMLHttpRequest cannot load https://api.twitter.com/oauth2/token. Origin http://localhost is not allowed by Access-Control-Allow-Origin. (index):1
Check:
Twitter :Application-only authentication error Origin null is not allowed by Access-Control-Allow-Origin
and:
https://dev.twitter.com/discussions/1291
I ran into a similar issue when working with the google API where in request from localhost are denied even if you register it with the system.
We got around this issue by adding a multipart name to our /etc/hosts file and binding it to 127.0.0.1
for example
127.0.0.1 www.devsite.com
This has resolved the most basic issues that I have had writing angular services for APIs
update by request:
One of the ways that companies control access to their APIs is through whitelisting. When you register an application with the service that platform will typically add the domain you list in your application to its whitelist. This is Generally done to force you in to using separate API keys for separate services. This can make work on the dev side difficult when you are testing locally.
In this case I believe that twitter has specifically banned requests using localhost to prevent the use of 3rd party tools and bots.
Binding the domain you registered with your API key into your hosts file will cause any web requests on your machine to that domain to skip a dns lookup and instead route the request to your local dev server. This means that locally you will test your code by visiting:
www.devsite.com:[what ever port your local server is running on]
This may not be the solution to 100% of api access problems but it is one of the most common that I have experienced.
Note based on other responses:
There are Multiple reasons why you might experience a CORS related error. But just because you have received one doesn't mean that it isn't possible to implement your code on the front end. Generally in Angular CORS is encountered when:
a) you have failed to format your request correctly
-- one example of this might be you have added a header to indicate json is an expected result when infact the response it text.
b) the service or API is configured with a whitelist that needs to include explicitly either "localhost" or some other domain as discussed in this post.

Resources