After following this tutorial, I set out to implement a login feature in my Angular app that communicates with a backend built on Spring Boot, utilizing Spring Security.
The issue at hand is clear: Somewhere within my code, the authorization header is not being properly added.
https://i.sstatic.net/jkZ60.png
In my jwt.interceptor.ts file, I have included some console.log commands to pinpoint where the problem lies:
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private authenticationService: AuthenticationService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let currentUser = this.authenticationService.currentUserValue;
console.log(currentUser);
console.log(request.headers);
if (currentUser) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentUser.token}` // mimicking what I do in Postman for access
}
});
}
return next.handle(request);
}
}
Upon checking the console, it's odd that while the currentUser instance seems to contain a JWT token in its body, attempting to print out its token field (which is defined in the class) returns undefined.
https://i.sstatic.net/4v44R.png
Additionally, although an Authorization header is attached to the request, the value of Bearer turns out to be undefined.
https://i.sstatic.net/TUg2t.png
In my authorization service (authorization.service.ts), an object with the key currentUser is retrieved from local storage and its value is extracted. This information is stored upon logging in by taking a user from the /authenticate endpoint, stringify-ing it, and saving it in local storage. When accessing currentUserValue, I grab the .value field:
constructor(private httpClient: HttpClient) {
this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser')));
this.currentUser = this.currentUserSubject.asObservable();
}
.......
public get currentUserValue(): User {
return this.currentUserSubject.value;
}
How can I ensure that the token is correctly added to my Authorization header?
I stumbled upon a workaround for this issue:
In the authentication.service, adjust the constructor as follows (and add the field to the class):
constructor(private httpClient: HttpClient) {
this.tokenString = new BehaviorSubject<any>(JSON.parse(localStorage.getItem('currentUser'))).value.jwt;
}
Then, retrieve that field when setting the authorization header. While this solution resolves the immediate problem, I am open to better approaches.
Here's a more refined way to address this challenge:
Firstly, introduce a string field named jwt to your User class. Then, modify the constructor like so since currentUser can only be accessed once:
constructor(private httpClient: HttpClient) {
this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser')));
this.tokenString = this.currentUserSubject.value.jwt;
this.currentUser = this.currentUserSubject.asObservable();
}