I'm building a frontend app with React and Redux and I'm using axios to perform my requests. I would like to get access to all the fields in the header of the response. In my browser I can inspect the header and I can see that all the fields that I need are present(such as token, uid, etc...), but when I call
const request = axios.post(`${ROOT_URL}/auth/sign_in`, props);
request.then((response)=>{
console.log(response.headers);
});
I get just
Object {content-type: "application/json; charset=utf-8", cache-control: "max-age=0, private, must-revalidate"}
Here my browser network tab,as you can see all the other fields are present.
Bests.
In case of CORS requests, browsers can only access the following response headers by default:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
If you would like your client app to be able to access other headers, you need to set the Access-Control-Expose-Headers header on the server:
Access-Control-Expose-Headers: Access-Token, Uid
This really helped me, thanks Nick Uraltsev for your answer.
For those of you using nodejs with cors:
...
const cors = require('cors');
const corsOptions = {
exposedHeaders: 'Authorization',
};
app.use(cors(corsOptions));
...
In the case you are sending the response in the way of res.header('Authorization', `Bearer ${token}`).send();
I was facing the same problem. I did this in my WebSecurity.java, it's about the setExposedHeaders method in the CORS configuration.
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.setAllowedOrigins(Arrays.asList(FRONT_END_SERVER));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
configuration.setAllowedHeaders(Arrays.asList("X-Requested-With","Origin","Content-Type","Accept","Authorization"));
// This allow us to expose the headers
configuration.setExposedHeaders(Arrays.asList("Access-Control-Allow-Headers", "Authorization, x-xsrf-token, Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, " +
"Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
I hope it works.
Faced same problem in asp.net core
Hope this helps
public static class CorsConfig
{
public static void AddCorsConfig(this IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.WithExposedHeaders("X-Pagination")
);
});
}
}
According to official docs:
This may help if you want the HTTP headers that the server responded with. All header names are lower cased and can be accessed using the bracket notation. Example: response.headers['content-type'] will give something like: headers: {},
There is one more hint that not in this conversation.
for asp.net core 3.1
first add the key that you need to put it in the header, something like this:
Response.Headers.Add("your-key-to-use-it-axios", "your-value");
where you define the cors policy (normaly is in Startup.cs) you should add this key to WithExposedHeaders like this.
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowAnyOrigin()
.WithExposedHeaders("your-key-to-use-it-axios"));
});
}
you can add all the keys here.
now in your client side you can easily access to the your-key-to-use-it-axios by using the response result.
localStorage.setItem("your-key", response.headers["your-key-to-use-it-axios"]);
you can after use it in all the client side by accessing to it like this:
const jwt = localStorage.getItem("your-key")
Custom HTTP headers can not be accessed on client-side due to CORS restrictions. You need to add Access-Control-Expose-Headers setting on the server-side.
What are Access-Control-Expose-Headers?
Please go to https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
By default only these HTTP headers are exposed:
Cache-Control
Content-Language
Content-Length
Content-Type
Expires
Last-Modified
Pragma
For custom HTTP headers, you need to customize Access-Control-Expose-Headers in response headers.
If you are using Django on the server side you can use django-cors-headers (https://pypi.org/project/django-cors-headers/) for CORS settings management.
For example, with django-cors-headers you can add a list of HTTP headers that are to be exposed to the browser by CORS_ALLOW_HEADERS setting
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = list(default_headers) + [
'my-custom-header',
]
In case you're using Laravel 8 for the back-end side with CORS properly configured, add this line to config/cors.php:
'exposed_headers' => ['Authorization'],
In axios CORS requests, browsers can access only few headers by default.
But if you need to access a custom header from response, you have to send response with Access-Control-Expose-Headers form your backend server.
Hare is a example for Nodejs backend and Reactjs front end:
res.header('Access-Control-Expose-Headers', 'x-xsrf-token');
return res.header("x-xsrf-token", token).status(200)
.send({
id: user.id,
email: user.email,
});
res.header('Access-Control-Expose-Headers', 'x-xsrf-token');
for this line I can log my custom header like
axios.post("/login", {
email: emailInput.current.value,
password: passwordInput.current.value,
})
.then(function (response) {
console.log(response.headers["x-xsrf-token"]);
});
Without Access-Control-Expose-Headers in your response you will get undefine in console log. Check your response header in network tab that it contains the header with your custom name with it.
For the SpringBoot2 just add
httpResponse.setHeader("Access-Control-Expose-Headers", "custom-header1, custom-header2");
to your CORS filter implementation code to have whitelisted custom-header1 and custom-header2 etc
try like this
.then(res =>{
console.log(res);
console.log(res.headers['x-total-count']);
setTotalRecords(res.headers['x-total-count']);
setTableData(res.data);
});
for django help
CORS_EXPOSE_HEADERS = [
'your header'
]
For Spring Boot 2 if you don't want to use global CORS configuration, you can do it by method or class/controller level using #CrossOrigin adnotation with exposedHeaders atribute.
For example, to add header authorization for YourController methods:
#CrossOrigin(exposedHeaders = "authorization")
#RestController
public class YourController {
...
}
If you are using Django without django-cors-headers, you can write custom middleware.
class CustomCorsMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response['Access-Control-Expose-Headers'] = 'MY-HEADER, ANOTHER-HEADER'
return response
You can also set other CORS heades here.
Then you should register your middleware by inserting it at the beggining of the MIDDLEWARE list in your project's settings.py file.
MIDDLEWARE = [
'myapp.middleware.CustomCorsMiddleware',
...
]
[expanding on what #vladimir said]
if you're using Django
and django-cors-headers to allow/control CORS,
you should set the following, in your settings.py
CORS_EXPOSE_HEADERS = ['yourCustomHeader']
I facing issue with fetching data from my laravel server.
This is client side code:
private surveysUrl =
'http://107.170.59.79/services/public/api/v1/countries';
private headers = new Headers({'Content-Type': 'application/json'});
constructor(private http: Http) { }
getSurveys(): Promise<Survey[]> {
return this.http.get(this.surveysUrl)
.toPromise()
.then(response => response.json() as Survey[])
.catch(this.handleError);
}
But I am receiving as error as:
XMLHttpRequest cannot load
{{link set in variable "surveysUrl"}}. The 'Access-Control-
Allow-Origin' header has a value '{{Some random link}}' that is not
equal to the supplied origin. Origin 'http://localhost:4200' is therefore
not allowed access.
How can I fix this error?
PS: I am not allowed to post more than two links so I had to remove links from the error message. I have replaced it with {{ }} to make it readable.
If you are using apache then you need to allow the origin access i.e.
Header set Access-Control-Allow-Origin "*"
include this in .htaccess file.
Yes, I know what you are thinking - yet another CORS question, but this time I'm stumped.
So to start off, the actual error message:
XMLHttpRequest cannot load http://localhost/Foo.API/token. The
value of the 'Access-Control-Allow-Origin' header in the response must
not be the wildcard '*' when the request's credentials mode is
'include'. Origin 'http://localhost:5000' is therefore not allowed
access. The credentials mode of requests initiated by the
XMLHttpRequest is controlled by the withCredentials attribute.
I'm not sure what is meant by credentials mode is 'include'?
So when I perform the request in postman, I experience no such error:
But when I access the same request through my angularjs web app, I am stumped by this error. Here is my angualrjs request/response. As you'll see the response is OK 200, but I still receive the CORS error:
Fiddler Request and Response:
The following image demonstrates the request and response from web front-end to API
So based on all the other posts I've read online, it seems like I'm doing the right thing, that's why I cannot understand the error. Lastly, here is the code I use within angualrjs (login factory):
CORS Implementation in API - Reference purposes:
Method 1 used:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
EnableCrossSiteRequests(config);
}
private static void EnableCrossSiteRequests(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*")
{
SupportsCredentials = true
};
config.EnableCors(cors);
}
}
Method 2 used:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
The issue stems from your Angular code:
When withCredentials is set to true, it is trying to send credentials or cookies along with the request. As that means another origin is potentially trying to do authenticated requests, the wildcard ("*") is not permitted as the "Access-Control-Allow-Origin" header.
You would have to explicitly respond with the origin that made the request in the "Access-Control-Allow-Origin" header to make this work.
I would recommend to explicitly whitelist the origins that you want to allow to make authenticated requests, because simply responding with the origin from the request means that any given website can make authenticated calls to your backend if the user happens to have a valid session.
I explain this stuff in this article I wrote a while back.
So you can either set withCredentials to false or implement an origin whitelist and respond to CORS requests with a valid origin whenever credentials are involved
If you are using CORS middleware and you want to send withCredentials boolean true, you can configure CORS like this:
var cors = require('cors');
app.use(cors({credentials: true, origin: 'http://localhost:5000'}));
Customizing CORS for Angular 5 and Spring Security (Cookie base solution)
On the Angular side required adding option flag withCredentials: true for Cookie transport:
constructor(public http: HttpClient) {
}
public get(url: string = ''): Observable<any> {
return this.http.get(url, { withCredentials: true });
}
On Java server-side required adding CorsConfigurationSource for configuration CORS policy:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
// This Origin header you can see that in Network tab
configuration.setAllowedOrigins(Arrays.asList("http:/url_1", "http:/url_2"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
configuration.setAllowedHeaders(Arrays.asList("content-type"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...
}
}
Method configure(HttpSecurity http) by default will use corsConfigurationSource for http.cors()
If you're using .NET Core, you will have to .AllowCredentials() when configuring CORS in Startup.CS.
Inside of ConfigureServices
services.AddCors(o => {
o.AddPolicy("AllowSetOrigins", options =>
{
options.WithOrigins("https://localhost:xxxx");
options.AllowAnyHeader();
options.AllowAnyMethod();
options.AllowCredentials();
});
});
services.AddMvc();
Then inside of Configure:
app.UseCors("AllowSetOrigins");
app.UseMvc(routes =>
{
// Routing code here
});
For me, it was specifically just missing options.AllowCredentials() that caused the error you mentioned. As a side note in general for others having CORS issues as well, the order matters and AddCors() must be registered before AddMVC() inside of your Startup class.
If it helps, I was using centrifuge with my reactjs app,
and, after checking some comments below, I looked at the centrifuge.js library file, which in my version, had the following code snippet:
if ('withCredentials' in xhr) {
xhr.withCredentials = true;
}
After I removed these three lines, the app worked fine, as expected.
Hope it helps!
I develop a project using backbone, underscore, require .js and REST API.
I've got error Cross-Origin Request Blocked The Same Origin Policy disallows reading the remote resource at...
NOTE : I've configured Access-Control-Allow in server side already. Still, the error still appear.
I found a solution, using ajaxPrefilter, then here I've tried in my project :
router.js :
start: function() {
Backbone.history.start({pushState: true});
},
initialize: function() {
$.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
options.url = options.url;
});
}
Here is my backbone view :
var _wl = new MyModel();
_wl.save(_item,{
success: function(res) {
console.log(res);
}
});
I still got `Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://example.com/api/MyWebs. This can be fixed by moving the resource to the same domain or enabling CORS.
Could any one tell me what did I wrong here?
Any helps and ideas would be appreciated.
Can you check if the reponse from http://example.com/api/MyWebs carries back correctly configured CORS headers like "Access-Control-Allow-Origin" ,""Access-Control-Allow-Headers",""Access-Control-Allow-Methods" e.t.c. This can be done by having the dev tools open in chrome/firefox and inspecting the response headers.
Here are a couple of things to ensure if CORS has been configured properly:
Response Headers:
Check if you have configured the Access-Control-Allow-Origin header properly. Initially you can set the value of it to "*" for testing purpose and then later on specify the specific host.
If you are using custom headers make sure that you have added them to the allowed list using "Access-Control-Allow-Headers". The custom headers names are specifed as a comma separated list.
If you want to support PUT,DELETE and POST requests with certain media types, then make sure that you add "Access-Control-Allow-Methods".
Server Side:
Check if you have added code to handle the pre-flight request that comes with OPTIONS method.
EG:
if(containerRequestContext.getRequest().getMethod().equalsIgnoreCase("OPTIONS")) {
// code to check if the request is made from a allowed origin and if everything is fine abort with success / forbidden.
}
Check if each response sent from the server is made with the above response headers correctly set.
EG:
Language/Framework: Jersey Framework,Java
Each response will pass thru the below Filter and the following response headers will be added to them.
#PreMatching
#Provider
public class SecurityResponseFilter implements ContainerResponseFilter {
private static final Logger LOGGER = Logger.getLogger(SecurityResponseFilter.class);
#Override
public void filter(ContainerRequestContext containerRequestContext,ContainerResponseContext containerResponseContext) throws IOException {
try {
containerResponseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
containerResponseContext.getHeaders().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE");
containerResponseContext.getHeaders().add( "Access-Control-Allow-Headers", "tk_a,tk_r" );
} catch (Exception e) {
LOGGER.error("Error occured while processing request.",e);
throw e;
}
}
}
In the client side if you need to send custom headers, you could do it as follows :
$.ajaxPrefilter(function(options,originalOptions,jqXHR) {
jqXHR.setRequestHeader("tk_a",$.cookie("tk_a"));
jqXHR.setRequestHeader("tk_r",$.cookie("tk_r"));
});
I have two app with nodejs and angularjs.nodejs app has some code like this :
require('http').createServer(function(req, res) {
req.setEncoding('utf8');
var body = '';
var result = '';
req.on('data', function(data) {
// console.log("ONDATA");
//var _data = parseInput( data,req.url.toString());
var _data = parseInputForClient(data, req.url.toString());
switch (req.url.toString()) {
case "/cubes":
{
and this app host on http://localhost:4000.angularjs app host with node http-server module on localhost://www.localhost:3030.in one of my angularjs service i have some thing like this :
fetch:function(){
var data = '{somedata:"somedata"}';
return $http.post('http://localhost:4000/cubes',data).success(function(cubes){
console.log(cubes);
});
}
but when this service send a request to server get this error:
XMLHttpRequest cannot load http://localhost:4000/cubes. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3030' is therefore not allowed access.
so i search the web and stackoverflow to find some topic and i find this and this . according to these topics i change the header of response in the server to something like this :
res.writeHead(200, {
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": "*"
});
res.end(JSON.stringify(result));
but this dose'nt work.I try with firefox,chrome and also check the request with Telerik Fiddler Web Debugger but the server still pending and i get the Access Control Allow Origin error.
You do POST request, which generates preflight request according to CORS specification: http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ and https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Your server should also respond to OPTIONS method (besides POST), and return Access-Control-Allow-Origin there too.
You can see it's the cause, because when your code creates request in Network tab (or in Fiddler proxy debugger) you should see OPTIONS request with ORIGIN header