I cannot understand a behavior of code below. I wanted to learn how to use JWT in communication between frontend and backend (I use Angular17 and jdk21). Parts of code: Anngular: Interceptor: export const tokenInterceptor: HttpInterceptorFn = (req, next) => { const authService = inject(AuthService); if(authService.getToken()) { const cloned = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + authService.getToken()) }); console.log('Headers: ', cloned.headers); return next(cloned); } return next(req); }; AccountComponent: export class AccountComponent { authService = inject(AuthService); accountDetail$ = this.authService.getDetail(); } AuthService: login(data: LoginRequest): Observable<AuthResponse>{ var value = this.http.post<AuthResponse>(`${this.apiUrl}login`,data); return value.pipe( map((response) => { if(response.success){ localStorage.setItem(this.tokenKey, response.token); } return response; }) ); } logout = (): void => { localStorage.removeItem(this.tokenKey); }; getDetail = (): Observable<UserDetail> => { return this.http.get<UserDetail>(`${this.apiUrl}api/detail/1`); } app.config.ts: export const appConfig: ApplicationConfig = { providers: [provideRouter(routes), provideAnimationsAsync(), provideHttpClient(withInterceptors([tokenInterceptor]))] }; Java code: Filter: @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http.csrf(AbstractHttpConfigurer::disable).cors(AbstractHttpConfigurer::disable).authorizeHttpRequests( //ahr -> ahr.requestMatchers("/login", "/signup", "/signup/roles").permitAll().requestMatchers("/api/detail/1").authenticated()) ahr -> ahr.requestMatchers("/login", "/signup", "/signup/roles", "/api/detail/1").permitAll()) .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class) .build(); } JwtRequestFilter: @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String authHeader = request.getHeader("authorization"); String token = null; String username = null; Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String headerName = headerNames.nextElement(); System.out.println("Header " + headerName+": "); var headers = request.getHeaders(headerName); while (headers.hasMoreElements()) { String headerValue = headers.nextElement(); System.out.println(headerValue); } } if (Objects.nonNull(authHeader) && authHeader.startsWith("Bearer ")) { token = authHeader.substring(7); username = jwtUtil.extractUsername(token); } ... I can split my troubleshooting on 3 stages: Stage 1: In java filter active line: ahr -> ahr.requestMatchers("/login", "/signup", "/signup/roles").permitAll().requestMatchers("/api/detail/1").authenticated()) After log in I can see token in local storage When I go to the details I got an error: "CORS Missing Allow Origin" - and I didn't receive header 'authentication' - I can see it in backend prints, so it's correct backend behvior; I log out on frontend -> localStorage is empty Stage 2: In java filter active line: ahr -> ahr.requestMatchers("/login", "/signup", "/signup/roles", "/api/detail/1").permitAll()) After log in I can see token in local storage When I go to the details I can see details, and I can see header 'authentication' in backend logs I log out on frontend -> localStorage is empty Stage 3: In java filter active again line: ahr -> ahr.requestMatchers("/login", "/signup", "/signup/roles").permitAll().requestMatchers("/api/detail/1").authenticated()) After log in I can see token in local storage I go to the details and... I can see details and I can see header 'authentication' in backend logs!? Now when I log out and log in again or I close and open again a browser then still I can see details, but if firstly I log out and next I close the browser then after log in I got an error. My question how can I understand this behavior? It's totally weird for me. Did anybody have this problem? I checked backend using Postman - it seems that it works, also with authentication. Continue reading...