CORS with AngularJS and JAX-RS - angularjs

I am writing a web application using AngularJS on the front end and JAX-RS on the backend. The front end can make HTTP post requests successfully to the backend when the CORS extension in chrome has 'enable CORS' on. When it is off, it comes back with an error -
The 'Access-Control-Allow-Origin' header contains multiple values 'http://127.0.0.1:XYZXX, *', but only one is allowed. Origin 'http://127.0.0.1:XYZXX' is therefore not allowed access.
The backend has a CORSFilter.java file configured as below -
public class CORSFilter implements ContainerResponseFilter {
#Override
public ContainerResponse filter(ContainerRequest request,
ContainerResponse response) {
response.getHttpHeaders().add("Access-Control-Allow-Origin", "*");
response.getHttpHeaders().add("Access-Control-Allow-Headers",
"origin, content-type, accept, authorization");
response.getHttpHeaders().add("Access-Control-Allow-Credentials","true");
response.getHttpHeaders().add("Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS, HEAD");
return response;
}
}
I have tried suggestions in various stackoverflow posts like deleting the X-REQUESTED-WITH and setting UseXDomain to true -
delete $http.defaults.headers.common['X-Requested-With'];
$http.defaults.useXDomain = true;
I have also tried changing the content-type to Form/URLEncoded instead of Application/JSON. None seem to enable sending the POSTs except the Chrome extension - which makes me think the solution should be on client side.
Please help! - Thanks in advance.

Related

Can't get token from server using fetch or axios

I'm using ReactJs to build a video call app.
I also up agora-token-service into railway. Testing is oke. But when i try to fetch data, it's has a ploblem, I also tried to fix it but it didn't work. mode: 'no-cors also didn't work
i need a solution please!
You are using http and trying to access content from https thats way it's giving this error.
try to host this website or you can use temporary service like ngrok
use npm i ngrok
See enabling CORS references below, hope this helps.
How to allow CORS in react.js?
It is better to add CORS enabling code on Server Side. To enable CORS in NodeJS and ExpressJs based application following code should be included-
var app = express();
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
In response, the server returns a Access-Control-Allow-Origin header with Access-Control-Allow-Origin: *, which means that the resource can be accessed by any origin.
Access-Control-Allow-Origin: *
This pattern of the Origin and Access-Control-Allow-Origin headers is the simplest use of the access control protocol. If the resource owners at https://bar.other wished to restrict access to the resource to requests only from https://foo.example (i.e., no domain other than https://foo.example can access the resource in a cross-origin manner), they would send:
Access-Control-Allow-Origin: https://foo.example
Note: When responding to a credentialed requests request, the server must specify an origin in the value of the Access-Control-Allow-Origin header, instead of specifying the "*" wildcard.

Getting Access-Control-Allow-Headers in preflight error

I have created angular js app in which I have integrate twitch api , the api is
return $http({
url: "https://api.twitch.tv/kraken/streams",
method: "GET",
params: { channel: channel, limit: 1 },
headers: { "Client-Id": "XXXXXXXXXXXXXXX" }
})
the problem is when I reload the page the api is working but when my state changes without page reload I am getting cross origin error from this api.
the error is
Failed to load https://api.twitch.tv/kraken/streams?channel=eliazOne&limit=1: Request header field RefreshToken is not allowed by Access-Control-Allow-Headers in preflight response.
anyone has idea how to resolve cross error
When you make a request to a different domain this is called a cross domain request. Also known as a CORS request.
When you POST / PUT data to a different domain it will make an OPTIONS request first. This is to ensure that the server has Access-Control-Allow-Headers in place on the response. These headers should permit access to the domain you are making the request from. If these headers are not present then when the OPTIONS request is made it will fail and the POST / PUT will never be made.
See here for more info https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests
The simple answer is to just add these headers to your server.
I don't know if this is something Angular does on its own by default or if it's a bug elsewhere in your code, but you or Angular is sending a RefreshToken header as part of your failing request, which is not allowed per Access-Control-Allow-Headers response header in the pre-flight OPTIONS request.
$ curl -XOPTIONS https://api.twitch.tv/kraken/streams -is | grep Headers
Access-Control-Allow-Headers: Accept, Accept-Language, Authorization, Client-Id, Twitch-Api-Token, X-Forwarded-Proto, X-Requested-With, X-Csrf-Token, Content-Type, X-Device-Id
This is something all cross-origin requests do. The browser sends an OPTIONS request to make sure the real request it's about to make is allowed by the criteria set by the cross-origin server.
You need to add a ?callback=? with the URL you are passing along with a callback function. Please follow the link How to use JQuery to Access Twitch streams
This is JQuery example but the concept is same.
$.getJSON('https://api.twitch.tv/kraken/streams/' + name + '?callback=?',
function(channel){
if (channel["stream"] == null) {
$("#all").append("<p>" + channel._links.self + "</p>");
}
else {
$("#all").append("<p>Fail</p>");
}
});
});

Windows Authentication is not working with WebAPI when called through Angular

I have two Projects, one is MVC (using Angular) and other is WebAPI. Windows Authentication is working fine in MVC (thanks to this article)
However, when I am making AJAX calls from MVC site through Angular to WebAPI then I get following error:
HTTP Error 401.2 - Unauthorized You are not authorized to view this
page due to invalid authentication headers.
Most likely causes:
No authentication protocol (including anonymous)is selected in IIS.
Only integrated authentication is enabled, and a client browser was used that does not support integrated authentication.
Integrated authentication is enabled and the request was sent through a proxy that changed the authentication headers before they
reach the Web server.
The Web server is not configured for anonymous access and a required authorization header was not received.
The "configuration/system.webServer/authorization" configuration section may be explicitly denying the user access.
I read this post but it is talking about HttpClient (while I am using JQuery or Angular) to make calls.
PLEASE NOTE: If I hit the WebAPI URL through Browser then Authentication works fine. So it must be something to do with AJAX request.
This is my code in Global.asax
protected void Application_BeginRequest()
{
if (ValidateRequest())
{
//var origin = Request.Headers["Origin"];
Response.Headers.Remove("Access-Control-Allow-Origin");
Response.AddHeader("Access-Control-Allow-Origin", matchedOrigin);
Response.Headers.Remove("Access-Control-Allow-Headers");
Response.AddHeader("Access-Control-Allow-Headers", CustomConfig.HEADERS);
Response.Headers.Remove("Access-Control-Allow-Methods");
Response.AddHeader("Access-Control-Allow-Methods", CustomConfig.METHODS);
}
// This is to avoid "Method 405 Not allowed" error
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
Response.Flush();
Response.End(); //Send the Empty Response for Options (Preflight Request)
}
}
I have done enough research but couldn't find a solution. So couple of things.
How can I resolve my above issue
Secondly what's the best approach for using Windows Authentication based on my scenario (And Project setup).
If it works in the browser directly but not when JavaScript is involved it will be a CORS issue so check you have it all enabled, including handling pre-flight OPTIONS verb.
In your case you will also need to check you are passing credentials e.g.
[EnableCors(origins: "http://myclient.azurewebsites.net", headers: "*",
methods: "*", SupportsCredentials = true)]
Note with credentials I don't think you can have a wildcard origin - needs explicit list.
See this link: https://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#credentials.
In your Angular $http request make sure you have the property withCredentials: true.
Or if you are making a JQuery ajax call then:
xhrFields: {
withCredentials: true
}
If you still have pre-flight problems try a custom message handler like this (change the origin(s)):
public class ExampleMessageHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (request.Headers.Contains("Origin") && request.Method.Method == "OPTIONS")
{
var response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
response.Headers.Add("Access-Control-Allow-Origin", "http://localhost:8080/");
response.Headers.Add("Access-Control-Allow-Credentials", "true");
response.Headers.Add("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Authorization");
response.Headers.Add("Access-Control-Allow-Methods", "DELETE, POST, PUT, OPTIONS, GET");
}
return base.SendAsync(request, cancellationToken);
}
}
Then:
public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new ExampleMessageHandler());

Not able to get response from API through angular?

My code is as below
$scope.LoadSearchResults = function () {
$scope.hotels = '';
$scope.allData = '';
var mydata = '';
$http({
url: 'myurl',
Authorization : 'code',
method: 'POST',
header: { 'Content-type': 'text/json' }
})
.success(function (mydata) {
$scope.hotels = JSON.parse(JSON.stringify(mydata.SearchResponse.Hotels.Hotel));
$scope.allData = JSON.parse(JSON.stringify(mydata.SearchResponse.Hotels.Hotel));
$scope.AllLocality($scope.allData);
})
.error(function (mydata) {
$scope.hotels = "Failed";
console.log(JSON.stringify(mydata));
});
}
and getting error is
"Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://example.com/some-page. (Reason: CORS header 'Access-Control-Allow-Origin' missing)."
How could I solve this problem?
this is not an Angular problem.
the reason is you are firing a cross origin request (e.g. your app sits on a domain and the request specified by url: 'myurl' is for a different domain) and HTTP does not allow it unless permissions are specifically added by the server receiving the request by adding a CORS header to the response.
to solve your problem you please check here one of the 4 options (I am sure you can find more depending on your specific setup):
make your app fire the request to the same domain, which is normally the preferred and most secure approach (e.g. the web app hosting the angular code is also responsible of responding to the xhr you are doing via $http)
if you have control on how the server creates the response, it should be fairly easy to add such headers (I cannot add an example here as it is entirely dependent on the web server or application gateway you are using)
if you don't have control over the server response (and most importantly its headers) you can add your own server in the middle that would act as a request proxy, thus making your JS app firing the request to your server (not incurring CORS problems) and the server itself making the proxy request to the 3rd party provider
if you just need GET requests (which doesn't seem the case from your snippet) you can use angular's $http JSONP if the server supports this type of requests.
Hi I have got it same issue but now i have resolved it by using below:
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Authorization");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
please pass header on controller after parent::__construct();

AngularJS not detecting Access-Control-Allow-Origin header?

I am running an angular app on a local virtualhost (http://foo.app:8000). It is making a request to another local VirtualHost (http://bar.app:8000) using $http.post.
$http.post('http://bar.app:8000/mobile/reply', reply, {withCredentials: true});
In the Network tab of Chrome Developer Tools I of course see the OPTIONS request, and the response includes the header:
Access-Control-Allow-Origin: http://foo.app:8000
However, the POST request is cancelled with the following error:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://foo.app:8000' is therefore not allowed access.
Has anyone experienced this? The Access-Control-Allow-Origin header is very plainly included in the response of the OPTIONS request, so I can't for the life of me figure out why the POST is acting the header was missing.
Access-Control-Allow-Credentials is also set to true.
It's a bug in chrome for local dev. Try other browser. Then it'll work.
There's a workaround for those who want to use Chrome. This extension allows you to request any site with AJAX from any source, since it adds 'Access-Control-Allow-Origin: *' header to the response.
As an alternative, you can add this argument to your Chrome launcher: --disable-web-security. Note that I'd only use this for development purposes, not for normal "web surfing". For reference see Run Chromium with Flags.
As a final note, by installing the extension mentioned on the first paragraph, you can easily enable/disable CORS.
I was sending requests from angularjs using $http service to bottle running on http://localhost:8090/ and I had to apply CORS otherwise I got request errors like "No 'Access-Control-Allow-Origin' header is present on the requested resource"
from bottle import hook, route, run, request, abort, response
#https://github.com/defnull/bottle/blob/master/docs/recipes.rst#using-the-hooks-plugin
#hook('after_request')
def enable_cors():
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS, PUT'
response.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept'
I experienced this exact same issue. For me, the OPTIONS request would go through, but the POST request would say "aborted." This led me to believe that the browser was never making the POST request at all. Chrome said something like "Caution provisional headers are shown" in the request headers but no response headers were shown. In the end I turned to debugging on Firefox which led me to find out my server was responding with an error and no CORS headers were present on the response. Chrome was actually receiving the response, but not allowing the response to be shown in the network view.
CROS needs to be resolved from server side.
Create Filters as per requirement to allow access and add filters in web.xml
Example using spring:
Filter Class:
#Component
public class SimpleFilter implements Filter {
#Override
public void init(FilterConfig arg0) throws ServletException {}
#Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse response=(HttpServletResponse) resp;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(req, resp);
}
#Override
public void destroy() {}
}
Web.xml:
<filter>
<filter-name>simpleCORSFilter</filter-name>
<filter-class>
com.abc.web.controller.general.SimpleFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>simpleCORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I just ran into this problem today. It turned out that a bug on the server (null pointer exception) was causing it to fail in creating a response, yet it still generated an HTTP status code of 200. Because of the 200 status code, Chrome expected a valid response. The first thing that Chrome did was to look for the 'Access-Control-Allow-Origin' header, which it did not find. Chrome then cancelled the request, and Angular gave me an error. The bug during processing the POST request is the reason why the OPTIONS would succeed, but the POST would fail.
In short, if you see this error, it may be that your server didn't return any headers at all in response to the POST request.
It can also happen when your parameters are wrong in the request. In my case I was working with a API that sent me the message
"No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 401."
when I send wrong username or password with the POST request to login.
Instead of using $http.get('abc/xyz/getSomething') try to use
$http.jsonp('abc/xyz/getSomething')
return{
getList:function(){
return $http.jsonp('http://localhost:8080/getNames');
}
}
If you guys are having this problem in sails.js just set your cors.js to include Authorization as the allowed header
/***************************************************************************
* *
* Which headers should be allowed for CORS requests? This is only used in *
* response to preflight requests. *
* *
***************************************************************************/
headers: 'Authorization' // this line here

Resources