Reputation: 3564
I'm building an application with Spring and Angular and for now, I'm trying to implement the security phase using Spring security and (JWT)
The problem is that when I send the Authorization header from Angular Spring does not receive it!
even tho I'm sure it's already in the request (from chrome dev tools).
Also when I send the same request with the same header from ARC (Advanced REST Client from chrome) spring receives it and returns the data!
On then Angular side I'm using the HttpInterceptor
of course to add the token to requests like so:
export class HttpInterceptorService implements HttpInterceptor{
private _api = `${environment.api}/api`;
constructor(
private _authService: AuthenticationService
) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{
if(req.url.startsWith(this._api)){
req = req.clone({
setHeaders: {
Authorization: `Bearer ${this._authService.getToken()}`
}
});
}
return next.handle(req);
}
}
And this is what I'm doing inside spring:
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private JwtUserDetailsService jwtUserDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
private List<String> excludedURLsPattern = Arrays.asList(new String[]{"/authenticate"});
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return excludedURLsPattern
.stream()
.anyMatch(urlPattern -> request.getRequestURL().toString().contains(urlPattern));
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
System.out.println("=== request URL: "+request.getRequestURL());
final String requestTokenHeader = request.getHeader("Authorization");
System.out.println("=== requestTokenHeader: "+requestTokenHeader);// in this line I always get null (when using Angular not ARC) !!
String username = null;
String jwtToken = null;
// JWT Token is in the form "Bearer token". Remove Bearer word and get
// only the Token
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
System.out.println("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
System.out.println("JWT Token has expired");
}
} else {
logger.warn("JWT Token does not begin with Bearer String");
}
// Once we get the token validate it.
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
// if token is valid configure Spring Security to manually set
// authentication
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// After setting the Authentication in the context, we specify
// that the current user is authenticated. So it passes the
// Spring Security Configurations successfully.
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
And this is the message I get:
2020-10-14 15:11:17.664 WARN 9856 --- [nio-5000-exec-1] c.s.c.security.config.JwtRequestFilter : JWT Token does not begin with Bearer String
Upvotes: 4
Views: 1902
Reputation: 353
Springboot-3
under your security configuration class public SecurityFilterChain filterChain(HttpSecurity http)
bean
add following line before http.build()
anywhere
cors(Customizer.withDefaults())
and create a new class as global configuration CorsConfiguration
implement method addCorsMapping
from WebMvcConfigurer
class, finally allow methods, originas, header under implemented method, this should work
Upvotes: 0
Reputation: 3564
ok I will leave the solution here in case someone needed it.
as described in this blog and since I'm using Sring Security I must enable CORS at Spring security level
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...// this one right here
}
}
Upvotes: 3