3.6: Improving Authentication
Right now, when we check to see if a user is logged in - we're only checking if there is an item in their local storage with the key 'token'.
As explained previously, this isn't entirely helpful for us. Is it invalid or expired? We don't know.
To help us improve our login and register method, we'll use a library for this provided by Auth0
called angular2-jwt
.
Look over the docs if you'd like.
In the docs, it lists the 'key features' of the library:
Send a JWT on a per-request basis using the explicit AuthHttp class
Decode a JWT from your Angular 2 app
Check the expiration date of the JWT
Conditionally allow route navigation based on JWT status
Sounds perfect!
Installing and Configuring angular2-jwt
Make sure you are in the root folder of your SPA
project and run the following command:
npm install @auth0/angular-jwt --save
Next, in our app.module.ts
file, we'll import the library
import { JwtModule } from '@auth0/angular-jwt';
// ...
import: [
// ...
JwtModule.forRoot({
config: {
tokenGetter: () => {
return localStorage.getItem('token');
},
whitelistedDomains: ['localhost:5000']
}
})
]
Updating loggedIn() method
In our auth.service.ts
class, let's start by injecting the JwtHelperService
provided by the library into our constructor.
constructor(private _http: HttpClient,
private _jwtHelperService: JwtHelperService) { }
Update the method in our service to check if a user has an unexpired token or not:
loggedIn() {
const token = this._jwtHelperService.tokenGetter();
if (!token) {
return false;
}
return !this._jwtHelperService.isTokenExpired(token);
}
Decoding the token
Next, we'll add a property to hold the information in the token and the JwtHelper.
decodedToken: any;
Update the login()
method to use the jwtHelperService:
login(model: any) {
return this._http.post<AuthUser>(this.baseUrl + 'login', model, { headers: new HttpHeaders()
.set('Content-Type', 'application/json') })
.map(user => {
if (user) {
localStorage.setItem('token', user.tokenString);
this.decodedToken = this._jwtHelperService.decodeToken(user.tokenString); // <--- Added
this.userToken = user.tokenString;
}
});
}
Displaying the Username in the Nav
In the nav.component.html
, let's use the AuthService
to display the username when a user is logged in:
What we currently have:
Welcome, user!
Let's change it to:
Welcome, {{ authService.decodedToken?.unique_name }}!
The decodedToken?
has a conditional null operator. If the page loads and it can't find this - it won't crash.
Retrieving User Information ASAP
Right now, if we're logged in and then refresh the page - we lose our username in the navbar and our information.
Instead of just loading the information in the navbar, we'll try loading all user information as soon as the root component of the application is initialized (before the nav component).
In app.component.ts
, update it to the following:
export class AppComponent implements OnInit {
constructor(
private _authService: AuthService,
private _jwtHelperService: JwtHelperService) {}
ngOnInit() {
const token = localStorage.getItem('token');
const user: User = JSON.parse(localStorage.getItem('user'));
if (token) {
this._authService.decodedToken = this._jwtHelperService.decodeToken(token);
}
}
}
Now, we should be able to refresh the page without losing our status and information.
Testing
Open up your browser, and try logging in!

Last updated