I am writing my first project to try my skills in Spring Boot and Angular. I have three endpoints: /register - this endpoint can access every person /login - this endpoint can access every person, response - token and token exp.time /users - this endpoint can access only authorized persons, who have valid JWT token, that they got as a response after successful login, response - List
My backend generates JWT token for authorization, I need to store it in local storage and add header Authorization: Bearer TOKEN, to all my requests, after login, to access endpoints that require authorization
My backend works great, i tested it several times with postman, and everything works as I wanted.
The problem is with my fronted. It receives my JWT token and stores it in localstorage, but my requests don't have Authorization header with token.
I tried many ways that I found on the internet but nothing helped.
checked token from local storage with postman
LoginComponent
import { Component } from '@angular/core';
import { CardModule } from 'primeng/card';
import { InputTextModule } from 'primeng/inputtext';
import { FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { FormBuilder } from '@angular/forms';
import { ButtonModule } from 'primeng/button';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { ImageModule } from 'primeng/image';
import { AuthService } from '../../services/auth.service';
import { Router } from '@angular/router';
import { UserLoginDto } from '../../interfaces/userLoginDto';
import { UserService } from '../../services/user.service';
import { LoginResponse } from '../../interfaces/loginResponse';
@Component({
selector: 'app-login',
standalone: true,
imports: [
CardModule,
InputTextModule,
ReactiveFormsModule,
ButtonModule,
RouterModule,
CommonModule,
ImageModule
],
templateUrl: './login.component.html',
styleUrl: './login.component.css',
})
export class LoginComponent {
loginForm!: FormGroup;
constructor(
private fb: FormBuilder,
private authService: AuthService,
private router: Router,
private userService: UserService
){}
ngOnInit(): void {
this.loginForm = this.fb.group({
email: ['', [Validators.required, Validators.email]],
password: ['', Validators.required]
});
}
get email() {
return this.loginForm.controls['email'];
}
get password() { return this.loginForm.controls['password']; }
onSubmit(){
if(this.loginForm.valid){
const userLoginDto: UserLoginDto = {
email: this.loginForm.value.email,
password: this.loginForm.value.password
};
this.userService.loginUser(userLoginDto).subscribe({
next: (response: LoginResponse) => {
console.log('User logged in successfully', response);
const token = response.token;
this.authService.setAuthToken(token);
this.router.navigate(['/home']);
},
error: (err) => console.error('Error registering user', err)
});
}
}
}
UserService
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { User } from '../interfaces/user';
import { UserRegisterDto } from '../interfaces/userRegisterDto';
import { UserLoginDto } from '../interfaces/userLoginDto';
import { LoginResponse } from '../interfaces/loginResponse';
@Injectable({
providedIn: 'root'
})
export class UserService {
private apiServerUrl = 'http://localhost:8080';
constructor(private http: HttpClient) { }
public getAllUsers(): Observable<User[]>{
return this.http.get<User[]>(`${this.apiServerUrl}/users`);
}
public registerUser(user: UserRegisterDto): Observable<UserRegisterDto>{
return this.http.post<UserRegisterDto>(`${this.apiServerUrl}/register`, user);
}
public loginUser(user: UserLoginDto): Observable<LoginResponse>{
return this.http.post<LoginResponse>(`${this.apiServerUrl}/login`, user);
}
}
AuthService
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private tokenKey: string = 'token';
getAuthToken(): string | null{
const token = window.localStorage.getItem(this.tokenKey);
console.log("Retrieved token:", token);
return token;
}
setAuthToken(token: string | null): void{
if(token !== null){
window.localStorage.setItem(this.tokenKey, token);
} else{
window.localStorage.removeItem(this.tokenKey)
}
}
}
AuthInterceptor
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { AuthService } from './services/auth.service';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(
private authService: AuthService,
){}
intercept(req: HttpRequest<any>, next: HttpHandler){
const authToken = this.authService.getAuthToken();
const authReq = req.clone({
headers: req.headers.set('Authorization', `Bearer ${authToken}`)
});
return next.handle(authReq);
}
}
main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptors } from '@angular/common/http';
import { routes } from './app/app.routes';
import { provideRouter } from '@angular/router';
import { AuthInterceptor } from './app/auth-interceptor';
bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes),
provideHttpClient(),
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
]
})
.catch((err) => console.error(err));
I am Angular 18, standalone project
I will be glad for any help, thank you all
I tried many methods to solve this, but I have same result. On one of the forums I read that it is necessary to add **AuthInterceptor ** and add it to main.ts, also I tried this version of **AuthInterceptor **: How to add Authorization Header to Angular http request?
Your interceptor is "old-style". There is a way to get it working through some configuration option that I don't remember at the moment - but the easiest is to generate new-style (functional) interceptor. It will look something like this:
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const authService = inject(AuthService);
const router = inject(Router);
const authToken = authService.getToken();
if (authToken) {
req = req.clone({
setHeaders: {
Authorization: `Bearer ${authToken}`
}
});
}
return next(req).pipe(
catchError((error) => {
if (error instanceof HttpErrorResponse && error.status === 401) {
router.navigate(['login']);
}
return throwError(() => error);
})
);
};
Additionally, you need to update app.config.ts
:
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes),
provideHttpClient(withInterceptors([authInterceptor]))
]
};
See more in the docs.