Search code examples
angularangular-ui-routerauth0angular-router

Angular 2 UI-Router Authentication


I'm trying to implement JWT authentication in my angular 4 project. The server side is all set, only the front end need some extra work.

I found this auth0/angular2-jwt library. But my concern is that I use ui-router in my project while the library seems to design for ngRoute (not sure). Does this UI-Router/ngRoute thing matter? Can I just use this library in my project?

Or is there any other authentication library that is designed for Angular 2/4 with UI-Router?


Solution

  • This works for any routing preference you use. The general items you will consistently find yourself using is the 'tokenNotExpired' and of course the adding of the token to local storage and decoding it.

    I have used this on half a dozen projects in production, and it can be as complex as you want (or as minimal, which is typically how I use it). angular2-jwt is a library that works perfectly for the handling of JWT in Angular 4+ projects as has always been well maintained.

    auth.service

    import { Injectable } from '@angular/core';
    import { Router } from '@angular/router';
    import { UserService } from './user.service';
    import { tokenNotExpired, JwtHelper } from 'angular2-jwt';
    import { Observable } from 'rxjs/Observable';
    import { BehaviorSubject } from 'rxjs/Rx';
    
    @Injectable()
    export class AuthService {
      jwtHelper: JwtHelper = new JwtHelper();
      _authChange: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
      authChange = this._authChange.asObservable();
    
      constructor(private userService: UserService,
                  private router: Router) { }
    
      login(emailAndPassword) {
        return this.userService.login(emailAndPassword)
        .map(
          res => {
            localStorage.setItem('token', res.token);
            this._authChange.next(!this._authChange.getValue());
            return this.loggedIn;
          }
        );
      }
    
      logout() {
        localStorage.removeItem('token');
        this._authChange.next(!this._authChange.getValue());
        this.router.navigate(['/']);
      }
    
      getUserName() {
        if ( this.loggedIn() ) {
          return this.jwtHelper.decodeToken(localStorage.getItem('token')).user.username;
        } else {
          return '';
        }
      }
    
      getId() {
        if ( this.loggedIn() ) {
          return this.jwtHelper.decodeToken(localStorage.getItem('token')).user._id;
        } else {
          return '';
        }
      }
    
      loggedIn() {
        return tokenNotExpired();
      }
    
      isAuthChange(): Observable<boolean> {
        return this.authChange;
      }
    
    }
    

    user.service

    import { Injectable } from '@angular/core';
    import { HttpClient, HttpHeaders } from '@angular/common/http';
    import 'rxjs/add/operator/timeout';
    
    import { Observable } from 'rxjs/Observable';
    import 'rxjs/add/operator/map';
    import 'rxjs/add/operator/catch';
    
    
    @Injectable()
    export class UserService {
    
      // Headers
      headers = new HttpHeaders()
                  .set('Content-Type', 'application/json')
                  .set('charset', 'UTF-8' );
    
      constructor(private http: HttpClient) { }
    
      register(user): Observable<any> {
        console.log('Attempting to insert user doc into tempuser collection');
        console.log (user);
        return this.http.post('/api/tempuser', JSON.stringify(user), { headers: this.headers }).timeout(1500);
      }
    
      login(credentials): Observable<any> {
        return this.http.post('/api/login', JSON.stringify(credentials), { headers: this.headers });
      }
    
    }
    

    I provide both these services in the root app.module, and import AuthService in other components to access things like authService.isLoggedIn() to return a boolean if a user is logged in as well authService.getUserName() to return the user name as a string.