import { Injectable } from '@angular/core' ; import { AuthCredentials } from '../model/auth-credentials' ; import { ApiService } from './api.service' ; @ Injectable ( ) export class AuthService { private jwtHelper : JwtHelper ; constructor ( private apiService ) { this . jwtHelper = new JwtHelper ( ) ; } public logIn ( creds ) { return this . apiService . login ( creds ) ; } public logOut ( ) { localStorage . removeItem ( 'token' ) ; } public setToken ( token ) { localStorage . setItem ( 'token' , token ) ; } public isAuthenticated ( ) { return ! this . isTokenExpired ( ) ; } public getUserId ( ) { return this . jwtHelper . getUserId ( this . getToken ( ) ) ; } public isUserAdmin ( ) { return this . jwtHelper . isUserAdmin ( this . getToken ( ) ) ; } private getToken ( ) { return localStorage . getItem ( 'token' ) ; } private isTokenExpired ( ) { const token = this . getToken ( ) ; if ( null == token ) { return true ; } return this . jwtHelper . isTokenExpired ( token ) ; } } /**

    This class has been ripped directly from the auth0 angular2-jwt library.
    I don't need any of the other classes, just this one.

    Ref: https://github.com/auth0/angular2-jwt/blob/master/angular2-jwt.ts
*/ export class JwtHelper { public urlBase64Decode ( str ) { let output = str . replace ( /-/g , '+' ) . replace ( /_/g , '/' ) ; switch ( output . length % 4 ) { case 0 : { break ; } case 2 : { output += '==' ; break ; } case 3 : { output += '=' ; break ; } default : { throw new Error ( 'Illegal base64url string!' ) ; } } return this . b64DecodeUnicode ( output ) ; } private b64decode ( str ) { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' ; let output = '' ; str = String ( str ) . replace ( /=+$/ , '' ) ; if ( str . length % 4 === 1 ) { throw new Error ( '\'atob\' failed: The string to be decoded is not correctly encoded.' ) ; } for ( let bc = 0 , bs , buffer , idx = 0 ; buffer = str . charAt ( idx ++ ) ; ~ buffer && ( bs = bc % 4 ? bs * 64 + buffer : buffer , bc ++ % 4 ) ? output += String . fromCharCode ( 255 & bs >> ( - 2 * bc & 6 ) ) : 0 ) { buffer = chars . indexOf ( buffer ) ; } return output ; } private b64DecodeUnicode ( str ) { return decodeURIComponent ( Array . prototype . map . call ( this . b64decode ( str ) , ( c ) => { return '%' + ( '00' + c . charCodeAt ( 0 ) . toString ( 16 ) ) . slice ( - 2 ) ; } ) . join ( '' ) ) ; } public decodeToken ( token ) { const parts = token . split ( '.' ) ; if ( parts . length !== 3 ) { throw new Error ( 'JWT must have 3 parts' ) ; } const decoded = this . urlBase64Decode ( parts [ 1 ] ) ; if ( ! decoded ) { throw new Error ( 'Cannot decode the token' ) ; } return JSON . parse ( decoded ) ; } public getTokenExpirationDate ( token ) { let decoded ; decoded = this . decodeToken ( token ) ; if ( ! decoded . hasOwnProperty ( 'exp' ) ) { return null ; } const date = new Date ( 0 ) ; date . setUTCSeconds ( decoded . exp ) ; return date ; } public getUserId ( token ) { return this . decodeToken ( token ) . id ; } public isUserAdmin ( token ) { return this . decodeToken ( token ) . admin ; } public isTokenExpired ( token , offsetSeconds ? ) { const date = this . getTokenExpirationDate ( token ) ; offsetSeconds = offsetSeconds || 0 ; if ( date == null ) { return false ; } return ! ( date . valueOf ( ) > ( new Date ( ) . valueOf ( ) + ( offsetSeconds * 1000 ) ) ) ; } }