Jwt authentication with Angular and spring - java

I am building the authentication for my angular app using JWT token.
For any request to the rest api, I want that spring MVC check for the token in the header of the http request except when the http request is /login (to create a new token).
I am having an issue with my cors filter. It is sending a 401 status after the user is logged in successfully. The token sent in the "authorization" header is not taken into account.
angular service
getListe(): Promise<any> {
let header = new Headers();
header.append("authorization", localStorage.getItem("token"))
return this.http.get(URL_API_REST + 'liste', header)
.toPromise()
.then(response => response.json())
.catch(this.handleError);
}
Spring Cors Filter
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request= (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
response.setHeader("Access-Control-Expose-Headers", "x-requested-with");
if(!request.getRequestURI().equals("/rest/rest/login")) {
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");
response.setStatus(HttpServletResponse.SC_OK);
}
/*if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
*/
chain.doFilter(req, res);
}
Spring Authentication Filter
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request= (HttpServletRequest) servletRequest;
String token = request.getHeader("token");
if(token != null){
System.out.println("Présence d'un token");
}
else{
if(!request.getRequestURI().equals("/rest/rest/login"))
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
filterChain.doFilter(request, response);
}
Is there something am I missing ?

I don't have time to try to analyze code now, but I recommend you this project in GitHub that show a simple login system using JWT and Java. I've used it as an example to implement JWT in some of my systems and it worked perfectly. Hope it helps.

I had a hard time dealing with this issue, but I hope the answers will spare the time for some.
Actually, I figured out that my angular wasn't sending the header authorization in the request headers. To solve that issue, I used the RequestOptions in my service Angular.
service Angular
getListe(): Promise<any> {
let header = new Headers();
header.append("authorization", localStorage.getItem("token"))
let options = new RequestOptions({headers: header})
return this.http.get(URL_API_REST + 'liste', options)
.toPromise()
.then(response => response.json())
.catch(this.handleError);
}

Related

Getting Preflight request doesn't pass access control check error while communicating between Spring and Angular

I am trying to write a custom filter, that checks for the user authentication using Spring 4.2.
While making a request from the angular application, I get the following error:
Access to XMLHttpRequest from origin http://localhost:4200 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
The header included in the angular Application is:
const requestHeaderObject = {
headers: request.headers
.append('Content-Type', 'application/json')
.append('Access-Control-Allow-Origin', '*')
.append('logged_user_id', 'userId')
.append('auth_token', 'authToken')
}
The code of my Filter in Spring is:
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// Fetching all the header params from request
HttpServletRequest httpRequest = (HttpServletRequest) request;
Enumeration<String> headerNames = httpRequest.getHeaderNames();
String loggedUserId = null;
String authToken = null;
if (headerNames != null) {
while (headerNames.nextElement() != null && headerNames.hasMoreElements()) {
loggedUserId = httpRequest.getHeader('logged_user_id');
authToken = httpRequest.getHeader('auth_token');
}
}
if (loggedUserId == null || authToken == null) {
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
mapper.writeValue(response.getWriter(), getErrorDetailsMap());
return;
}
ApplicationContext appContext = AppContextConfig.getApplicationContext();
AccessManager accessManager = (AccessManager) appContext.getBean(AccessManager.class);
if(accessManager.isValidToken(loggedUserId, authToken) == false) {
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
mapper.writeValue(response.getWriter(), getErrorDetailsMap());
return;
}
filterChain.doFilter(request, response);
}
I have done the following but was not successful:
Adding #CrossOrigin mapping to all the controllers
Adding the following code in my filter:
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
Disabling cors in the security configuration by overriding the configure method as follows:
http.cors().disable();
Changed the headers in the angular applications.
Also I have tried to write another filter and passing the headers in that filter and calling it before my actual filter.

Custom header param - Spring Boot

I'm having trouble trying to send a custom header param from my frontend to the controller.
I've set the endpoint to get the header param:
public ResponseEntity<DashboardBean> atualizarDadosDashboard(#RequestHeader(name = "idEmpresa") Long idEmpresa){
But when I try to consume this endpoint, I get failed response and the application doesn't log any error.
Here I have the browser console showing the failed request:
The second dashboard request is a OPTIONS type. The first is the GET request.
Here you can see the failed request headers with the custom header "idEmpresa":
I'm using Angular on the frontend. As you can see below, I'm adding the header to the request:
....
protected httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': this.token,
'idEmpresa': String(this.idEmpresa)
})
};
atualizarDashboard(): Observable<DashboardModel> {
return this.httpClient.get<DashboardModel>(this.baseUrl, this.httpOptions);
}
....
On my spring boot application there is nothing on the logs about this request!!
Problem solved.
I have a CORS Filter in my application. I had to add my custom header param to the
Access-Control-Allow-Headers
list to allow it. After that, the endpoint was consumed and worked as expected.
This is how my Filter is now:
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCORSFilter implements Filter {
private final Log logger = LogFactory.getLog(this.getClass());
#Override
public void init(FilterConfig fc) throws ServletException {
logger.info("SimpleCORSFilter loaded");
}
#Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"x-requested-with, authorization, Content-Type, " +
"Authorization, credential, X-XSRF-TOKEN, idEmpresa");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, resp);
}
}
#Override
public void destroy() {
}
}

SpringMVC - CORS filtering doesn't work on 'Authorization' header [duplicate]

This question already has answers here:
CORS issue - No 'Access-Control-Allow-Origin' header is present on the requested resource
(8 answers)
Closed 4 years ago.
I am trying to add OAuth 2.0 in spring mvc app. User should be authenticated in order to get a api call. I have set a headers in spring mvc controller as:
#RequestMapping(value = "/admin-api/get-all-order", method = RequestMethod.GET)
public ResponseEntity getAllOrders(#RequestHeader("Authorization") String bearerToken) {
try {
List<OrderModel> order = orderService.getAllOrders();
return new ResponseEntity(order, HttpStatus.OK);
} catch (HibernateException e) {
return new ResponseEntity(e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
For requesting api I have used angular 5. I make a api call in angular like:
return this.http.get<T>(this.getAllOrderUrl, {
headers: {
"Authorization": "bearer " + JSON.parse(localStorage.getItem("token"))["value"],
"Content-type": "application/json"
}
}).catch(error => {
return this.auth.handleError(error);
})
But it gave me a strange error.
I have already enabled a CORS for 'localhost:4200'. CORS filtering works fine on other request.
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods",
"ACL, CANCELUPLOAD, CHECKIN, CHECKOUT, COPY, DELETE, GET, HEAD, LOCK, MKCALENDAR, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, REPORT, SEARCH, UNCHECKOUT, UNLOCK, UPDATE, VERSION-CONTROL");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"X-PINGOTHER,Content-Type,X-Requested-With,Accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,Key");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
If I tried in postman it give me a desired result.
Response Header
What am I doing wrong? Please help me out. Hoping for positive response thanks!
If you want to enable CORS without using filters or without config file just add
#CrossOrigin
to the top of your controller and it work.

How to avoid Cross-Origin-Resource-Sharing(CORS) while using axios in Vuejs?

I have developed a web application using Vue js. I am using axios for making API calls. And I am using Web services for API. I have included CORS filter in my API for ‘Allow-Control-Allow-origin’.
I have used axios like this:
axios.get('http://192.26.3.51:8097/FeedbackPhase2/login) .then(response => { this.fb1 = response.data this.vh = this.fb1.length })
And in my CORS filter:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
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", "Content-Type, Accept, X-Requested-With, remember-me");
chain.doFilter(req, res);
}
The problem is, when I load the page in different browsers, I am getting an Error like this:
Failed to load http://192.26.3.51:8097/FeedbackPhase2/login: 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:8080' is therefore not allowed access.
and
Error: Network Error
at createError (webpack-internal:///179:16)
at XMLHttpRequest.handleError (webpack-internal:///178:87)
What should I do? Please guide me.

404 for OPTIONS method in Google AppEngine with Java and Angular.js

I am using Angular.js with AppEngine on Java.
For every HTTP request, Angular.js issues an OPTIONS request before actual request, which returns an HTTP 404 error for me.
Can anybody please tell me why?
In AppEngine how to enable the configuration for OPTIONS method?
edit: I created a filter to handle OPTIONS request. Now I add the Allow header with GET, POST, DELETE, PUT, OPTIONS, HEAD as value and respond with status code 200. But still it shows 404.
Finally got it working.
I wrote the code like this:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) response;
HttpServletRequest req = (HttpServletRequest) request;
resp.setHeader("Cache-Control", "max-age=3600");
resp.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
resp.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");
resp.setHeader("Access-Control-Allow-Origin", "www.myapp.com");
resp.setHeader("Access-Control-Allow-Credentials", "true");
if (req.getMethod().equals("OPTIONS")) {
resp.flushBuffer();
} else {
chain.doFilter(request, resp);
}
}
I just wrote the resp.setHeader("Access-Control-Allow-Origin", "*"); before.
After writing the whole headers, it started working.

Categories

Resources