Issue
I am trying to send a GET request with Angular to my Spring Boot application. To be authenticated, this is how I pass the token to the headers:
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor() {}
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
const token = getCookieValue('token');
if (token) {
const authRequest = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(authRequest);
}
return next.handle(request);
}
}
Browser gives me this error:
Access to XMLHttpRequest at 'http://localhost:8080/api/user-profile/get-data' 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.
This is my configuration in Spring Boot:
public class SecurityConfiguration implements WebMvcConfigurer {
private final JwtFilter jwtFilter;
private final DataSource dataSource;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:4200")
.allowedMethods("*");
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable);
http.sessionManagement(sess -> sess.sessionAuthenticationStrategy(sessionAuthenticationStrategy()));
http.authorizeHttpRequests(auth ->
auth
.requestMatchers("/", "/api/auth/oauth").authenticated() // also tried with "/api/user-profile/**"
.requestMatchers("/", "/api/auth/**").permitAll()
.anyRequest().authenticated()
);
http.httpBasic(withDefaults());
http.oauth2Login(withDefaults());
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
And this is how I can send a request and prevent a CORS error:
Sending a basic request (without token):
this.http.get(environment.apiBaseUrl + 'user-profile/get-data').subscribe(result => {
console.log(result);
})
In Spring Boot, replaced .requestMatchers("/", "/api/auth/**").permitAll()
with .requestMatchers("/", "/api/auth/**", "/api/user-profile/**").permitAll()
.
Now I don't receive an error message but I can send a request without being authenticated and this is not my goal.
This is how I try to read the token:
@AllArgsConstructor
@Component
public class JwtFilter extends OncePerRequestFilter {
private final CustomUserService customUserService;
private Jwt jwt;
@Override
protected void doFilterInternal(HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String token = null;
String username = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
token = authorizationHeader.substring(7);
// Check if token is valid
try {
jwt.isTokenValid(token, customUserService.loadUserByUsername(jwt.extractUsername(token)));
}
catch (Exception e) {
Response responseObj = Response.builder()
.code("UNAUTHORIZED")
.status(HttpStatus.UNAUTHORIZED)
.timestamp(LocalDateTime.now())
.messages(Collections.singletonList("Invalid token"))
.build();
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
String json = mapper.writeValueAsString(responseObj);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write(json);
return;
}
username = jwt.extractUsername(token);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = customUserService.loadUserByUsername(username);
if (jwt.isTokenValid(token, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
filterChain.doFilter(request, response);
}
}
I don't know what I am doing wrong, but authorizationHeader
is always null
.
Solution
This is how I resolved this issue:
In Angular, I created the file proxy.conf.json in src.
{
"/api": {
"target": "http://localhost:8080",
"pathRewrite": {
"^/api": "/api/"
},
"secure": false,
"changeOrigin": true
}
}
In angular.json I added the following into "serve": {
"options": {
"browserTarget": "angl:build",
"proxyConfig": "src/proxy.conf.json"
},
In package.json I replaced "start": "ng serve",
with "start": "ng serve --proxy-config src/proxy.conf.json",
.
Problem solved, and it does exactly what I wanted. Nothing changed in Spring Boot.
Answered By - xRay
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.