Angular17 frontend doesn't send header with JWT to Java backend

Discussão em 'Angular' iniciado por MichalM, Novembro 19, 2024.

  1. MichalM

    MichalM Guest

    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...

Compartilhe esta Página