I have small project where I want to send a cookie from my angular 18 frontend to my spring boot backend java version 17 in tomcat 10.1.
Regardless if I run tomcat inside of eclipse or as a regular tomcat with catalina.sh I get CORS problem.
I have tried to set the cors filter up when running with ‘ng serve’ on port 4200 and tomcat running in eclipse on 8080. I have got it working-ish with a cors setup in tomcat web.xml with CorsFilter and calls from my angular.
I’ve looked at many tutorials on the web and questions here at stackoverflow. On thing I noticed is that many explanation end up setting up session cookies to do validate users. I don’t want a session cookie. I want a regular cookie, it kind of keeping track of a user. But I’m going to expand this small project and maybe need to handle more cookies.
Here follows code that I believe help you tell me what I have done wrong.
Angular code.
export class CabinService {
private baseURL = environment.domain;
public httpClient = inject(HttpClient);
headers: HttpHeaders;
constructor() {
this.headers = new HttpHeaders();
this.headers = this.headers.set('cookie', 'cabinCTRLclientID=a88ce069-74f6-43be-be27-5c02901bb246');
}
getClients(): Observable<Client[]> {
console.log("CabinService - getClients - headers", this.headers);
return this.httpClient.get<Client[]>(this.baseURL + "clients", { headers: this.headers });
}
Java code
@GetMapping("/clients")
public String getClients(@CookieValue(value = Util.CLIENT_ID_COOKIE_NAME, defaultValue = "") String clientId,
HttpServletRequest request) {
List<Client> clients;
try {
clients = Util.getClients(request.getLocalAddr(), clientId);
} catch (CabinException e) {
logger.error("Failed to get the clients", e);
clients = new ArrayList<Client>();
}
Gson gson = new Gson();
return gson.toJson(clients, List.class);
}
The cors filter in web.xml for tomcat.
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>http://localhost:4200</param-value>
</init-param>
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>10</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
If you need more info I will provide.
I know pictures are not really popular but here are a few.
When I make the call from Postman, the backend gets the cookie. As you can see the cookie "clientId" is populated and the request has the cookie.
The flowing image is when I call from the angular app. As you can see the cookie clientId is empty and the cookie field in the request is null.
This is from the devtools in firefox where the the header contains the cookie.
The problem is that the cookie I send from angular in header does not get all the way in to my Spring boot service. When I send the call via Postman, http://localhost:8080/cabinctrlws/api/clients, it works. This is why I believe it has to do with my CorsFilter.
On the other hand, I might be wrong and that's why I entered this question.
Any help is appreciated. Sorry for the bad spelling.
Edit 1
I tried Roar S solution. I probably got it wrong. I only found one class with the Configuration annotation so added Roar solution. Tell me if I got it wrong.
@Configuration
public class AppConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(@NonNull CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:4200")
.allowedMethods("GET", "POST", "OPTIONS", "HEAD").allowCredentials(true);
}
};
}
}