I am working on an Angular project and I have login page and during submitting login API, I am facing CORS error. I am attaching screenshot of it also. Any suggestion would be appreciated.
API Service.ts:
constructor( private http: HttpClient ) { }
httpOptionsPost = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Allow-Methods' : 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers' : 'Origin, Content-Type, Accept, X-Custom-Header, Upgrade-Insecure-Requests',
})
};
httpOptionsGet = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
})
};
_login(username, password) {
const url = this.domain + '/api/login?username='+username+'&password='+password;
return this.http.post(url, {}, this.httpOptionsPost);
}
Login Component:
this.apiService._login(data.username, data.password).subscribe((resp: any) => {
const resobj = JSON.parse(JSON.stringify(resp));
console.log(resobj);
})
You need to set up proxy configuration for running the app locally.
A short example is:
// create a file proxy.config.json
{
"/api": {
"target": "http://example.com/", // put your actual domain
"secure": false // true or false depending on your needs.
}
}
Then run your project passing the proxy conf to ng-serve or configure it in the package.json.
For instance:
ng serve --proxy-config proxy.conf.json
or
npm start -- --proxy-config proxy.conf.json
Or simply configure it in the angular.json.
Then, in your code, remove the usage of the domain, or assign the domain to localhost using environment.dev.ts if the domain is not the same as where you are going to deploy you app.
I'm referring to the domain variable in this block.
_login(username, password) {
const url = this.domain + '/api/login?username='+username+'&password='+password;
return this.http.post(url, {}, this.httpOptionsPost);
}
More details in https://www.positronx.io/setting-up-angular-proxy-configuration-via-angular-json/ and / or in the official webpack site for advanced proxy configurations
Cors preflight should be handled at server side code. In your case try adding below annotation onto your controller class.
#CrossOrigin("*")
#PostMapping("/user")
public User userController(){
}
And hope you have a configuration class for handling the CORS, if not try adding one. Sample code for reference.
#Configuration
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
List<String> allowedMethods=new ArrayList<>();
allowedMethods.add("GET");
allowedMethods.add("POST");
allowedMethods.add("PUT");
allowedMethods.add("DELETE");
CorsConfiguration cors=new CorsConfiguration();
cors.setAllowedMethods(allowedMethods);
http.cors().configurationSource(request -> cors.applyPermitDefaultValues());
http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().requestMatchers(EndpointRequest.to("loggers")).hasRole("ADMIN").and().httpBasic();
}}
in your question , the pc_coder answer is right:
cors is related with backend. Be sure you allowed from api to reach requests
like the link:
How does Access-Control-Allow-Origin header work?
I'm not quite familiar with Angular. However, I had the same CORS issue with Vue.js and the solution is to change the add these lines :
module.exports = {
devServer: {
proxy: 'https://yourdomain'
}
}
and also replace the https://yourdomain/login to localhost when you do .get or .post, for example : 'http://localhost:8082/login'
I'm not sure if this would work for you since I am also very new at this, but it did work for me.
Before browser makes a call to your API URL from the angular client application, it will send a preflight request (An HTTP OPTIONS call). this will happen only when your client side application and server side applications are residing in different sub domains or domains. It is the responsibility of the server side application to control whether the cross origin request should be served or not. I see that you are setting the CORS headers in your request header. but it should be received from the API server. so remove that from the angular end and make the proper changes in the server side code.
By default, the Same-Origin-Policy (SOP) forbids request to a different resource. Everything should be loaded from the same source. This is to prevent websites to load data from different servers without the users knowledge. However, there are circumstances where this is required. To cover such case and still provide high safety measurements, CORS was created.
With CORS it is possible to send requests to a server different than the original one.
For this the webserver which is receiving the request must be configured accordingly. In your case this means, you have to adjust the CORS settings in the application which is providing the login API you are calling and allow localhost:4200 to be able to send CORS requests.
Related
I have a gateway with some APIs developed with Java Spring boot. But when I am calling the APIs from my react project the below error is thrown.
Access to XMLHttpRequest at 'http://localhost:8081/testgw/hello' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I have added the #CrossOrigin annotation to my rest controller as below.
#CrossOrigin(origins= {"*"}, maxAge = 4800, allowCredentials = "false" )
#RestController
public class FTController {
#GetMapping("/hello")
public String getHello() {
return "Hello World!";
}
}
And I am calling the API from my react project as below
var url = "http://localhost:8081/testgw/hello";
axios.get(url, {
headers: {
'Authorization' : 'Basic [AuthKey]',
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Methods':'GET,POST,OPTIONS,DELETE,PUT'
}
})
.then(
function(response) {
console.log("response --> " + response);
}).catch(function(error) {
console.log(error);
}
);
I am not getting rid of this problem. Please let me know what should I do to solve this.
After a lots of struggling I am able to get rid of this issue. Generally adding the #CrossOrigin annotation over the REST controller class the request methods should fix the issue.
But if adding the annotation doesn't solve the issue then it's generating from your browser. In that case you can overcome the issue by running the browser disabling the web security.
For windows you can run goggle chrome disabling the web security by following the below steps
Open run (Press Window Key + R)
Write the below command
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
Press Enter
This question already has answers here:
CORS issue - No 'Access-Control-Allow-Origin' header is present on the requested resource
(8 answers)
Closed 1 year ago.
I tried to make a connection between my Angular frontend and a REST Endpoint in Java / Spring (which I didn't developed and don't know so well). By GET, all works. By POST, I receive the message in the terminal
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
and, in the Network tab from the dev instruments, an error 403 on OPTIONS method
Request Method: OPTIONS
Status Code: 403
Remote Address: xx.xx.xx.xx:xxxx
Referrer Policy: strict-origin-when-cross-origin
So, I found this case after several searching in internet and the cause is CORS settings: usually, in this scenario, a OPTIONS call is sent before a POST; but, due to CORS, an OPTIONS call is not allowed. So, I tried to set this row on my controller
#CrossOrigin(origins = "*", methods = {RequestMethod.OPTIONS, RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE})
This time the error changed in
Multiple CORS header 'Access-Control-Allow-Origin' not allowed
But the code I added is the only similar to #CrossOrigin, I dind't found others similar.
So, my question is: which code can I search in the controller or also in other classes, which usually has the same role of the mentioned decorator?
(The app uses Spring Security; I didn't developed it and I am not so expert in Spring Security).
Edit
I have done exactly is in this discussion (is not exactly similar to mine) but, in this case, I receive this new error:
has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.
What can I do?
In your spring boot project add the below code to your controller.
#CrossOrigin(allowedHeaders =
{"Orgin", "X-Requested-With", "Content-Type", "Accept", "Authorization"},
methods = {RequestMethod.POST, RequestMethod.GET, RequestMethod.PUT,
RequestMethod.DELETE}
)
This will solve your cross-origin issue if your services are running on the local server/any server which has any proxies.
You can add a global policy to allow access implementing WebMvcConfigurer.
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("*")
.allowedOrigins("*")
.allowedHeaders("*");
}
}
Access to XMLHttpRequest at 'http://www.----------.com/efsapi/api/AdvanceQuote?
segmentcode=--&customercode=--&por=--&fdc=--&toscode=--' from origin
'http://localhost:8080' has been blocked by CORS policy: Response to preflight
request doesn't pass access control check: No 'Access-Control-Allow-Origin' header
is present on the requested resource (edited)
This error in i am facing in angularjs and we are using java as backend. tried the below code in front-end
'Access-Control-Allow-Origin': true,
'Content-Type': 'application/json; charset=utf-8',
"X-Requested-With": "XMLHttpRequest
Could you please tell how to handle this CORS error? (Platforms Angularjs & Java)
The problem you face is that the java backend blocks the client request and you need to allow the origin of the client in the backend.
From the spring cors guide
Enabling CORS for a single method:
So that the RESTful web service will include CORS access control headers in its response, you just have to add a #CrossOrigin annotation to the handler method:
#CrossOrigin(origins = "http://localhost:9000")
#GetMapping("/greeting")
public Greeting greeting(#RequestParam(required=false, defaultValue="World") String name) {
System.out.println("==== in greeting ====");
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
Enabling CORS globally:
As an alternative to fine-grained annotation-based configuration, you can also define some global CORS configuration as well. This is similar to using a Filter based solution, but can be declared within Spring MVC and combined with fine-grained #CrossOrigin configuration. By default all origins and GET, HEAD and POST methods are allowed.
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:9000");
}
};
}
For reference take a look at the original source: https://spring.io/guides/gs/rest-service-cors/
I've read a bunch of questions around this but none seem to be similar to my edge-case where I already have my JWT.
I'm using the Auth0 (note auth-zero, not Oauth) in my frontend to gain a JWT which is loaded with scopes and authentication for my backend. When I login to my frontend client I get a nice JWT with an access_token. If I copy that token I can make a direct curl request to my backend microservices
curl -X GET -H "Authorization: Bearer TOKEN_HERE" -H "Cache-Control: no-cache" "http://192.168.0.109:39885"
And this works as expected, I get a 200 response. Nice.
Now when I try the same curl request through my Zuul proxy I get a nasty 401.
The configuration I have for my gateway is:
#EnableHystrix
#EnableZuulProxy
#EnableEurekaClient
#SpringBootApplication
public class EdgeServiceApplication {
public static void main(String[] args) {
SpringApplication.run(EdgeServiceApplication.class, args);
}
}
Now reading the documentation and this conversation from the brilliant Dr Syer I know I need to allow the headers to go downstream which I've done:
zuul:
sensitiveHeaders:
routes:
instances:
path: /instances/**
serviceId: instance-service
restore:
path: /restore/**
serviceId: restore-service
Setting sensitiveHeaders empty should allow everything (for testing of course).
Looking further at the docs I see I need to add #EnableOAuth2Sso to my Zuul configuration. This is where I get confused/things break.
From what I know, #EnableOAuth2Sso is for generating and validating tokens. I don't want to do that. I already have my nice token ready for my microservice (which validates it down there).
How do I tell Zuul to not mess with my JWTs and just send them along?
I've solved this, there was to many things wrong with my code to detail but the gist of the issue was:
I was trying to send the entire JWT to the microservice when I should have just been sending the access_token
When I tried sending the access_token, ember-simple-auth0 actually sends the id_token by default
I needed to configure Zuul to pass CORS requests straight to the microservices
Once I started sending the access_token rather than the id_token it was easy to start debugging the issue.
To tell ember-simple-auth0 to use the access_token instead add a new authorizer with the following:
// app/authorizers/application.js
import Ember from 'ember';
import BaseAuthorizer from 'ember-simple-auth/authorizers/base';
const {
isPresent,
debug
} = Ember;
export default BaseAuthorizer.extend({
authorize(sessionData, block) {
let userToken = sessionData['accessToken'];
if (isPresent(userToken)) {
block('Authorization', `Bearer ${userToken}`);
} else {
debug('Could not find the authorization token in the session data for the jwt authorizer.');
}
}
});
Then remember to tell your adapter to use the new authorizer:
export default DS.JSONAPIAdapter.extend(DataAdapterMixin, {
authorizer: 'authorizer:application',
});
To forward CORS to your microservices use:
spring:
mvc:
dispatch-options-request: true
And making sure you're not stripping the headers from the request with:
zuul:
sensitiveHeaders:
routes:
instances:
path: /instances/**
serviceId: instance-service
stripPrefix: false
restore:
path: /restore/**
serviceId: restore-service
stripPrefix: false
Hopefully someone finds this useful.
In switching from Spring Cloud Brixton.M5 to Brixton.RC1 my ZuulProxy no longer passes Authorization headers downstream to my proxied services.
There's various actors in play in my setup, but most all of them are fairly simple:
- AuthorizationServer: runs separately; hands out JWTs to clients
- Clients: get JWTs from OAuth server; each with access to a subset of resources.
- ResourceServers: consume JWTs for access decisions
- MyZuulProxy: proxies various resource servers; should relay JWTs.
It should be noted that MyZuulProxy has no security dependencies whatsoever; It passed the Authorization: Bearer {JWT} header it receives to the ResourceServers, pre-RC1. MyZuulProxy is explicitly not a Client itself, and does not use #EnableOAuth2SSO or similar at the moment.
What could I do to get MyZuulProxy to relay the JWTs to the ResourceServers again when using Spring Cloud Brixton.RC1?
There's very little code to post: It's just #EnableZuulProxy, #EnableAuthorizationServer and #EnableResourceServer in three different jars. My Clients are not Spring applications.
Update: Fixed in https://github.com/spring-cloud/spring-cloud-netflix/pull/963/files
Sensitive headers can also be set globally setting zuul.sensitiveHeaders. If sensitiveHeaders is set on a route, this will override the global sensitiveHeaders setting.
So use:
# Pass Authorization header downstream
zuul:
sensitiveHeaders: Cookie,Set-Cookie
So pending a fix for https://github.com/spring-cloud/spring-cloud-netflix/issues/944, jebeaudet was kind enough to provide a workaround:
#Component
public class RelayTokenFilter extends ZuulFilter {
#Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
// Alter ignored headers as per: https://gitter.im/spring-cloud/spring-cloud?at=56fea31f11ea211749c3ed22
Set<String> headers = (Set<String>) ctx.get("ignoredHeaders");
// We need our JWT tokens relayed to resource servers
headers.remove("authorization");
return null;
}
#Override
public boolean shouldFilter() {
return true;
}
#Override
public String filterType() {
return "pre";
}
#Override
public int filterOrder() {
return 10000;
}
}
Set the sensitiveHeaders globally helped me solve the issue
zuul:
sensitiveHeaders: Cookie,Set-Cookie
Please note that the property name is sensitiveHeaders not sensitive-headers
[I use spring-cloud-starter-zuul version:1.3.1.RELEASE ]