CoderX
CoderX

Reputation: 1032

Deciding between various methods for authentication in Angular 4

I have read two tutorials of implementing Authentication in Angular 4.

The first one overrides the RouterOutlet class, and declare public routes, where the login is not required.

However, the second approach is to use canActivate AuthGuard Interface provided by Angular 4.
I am struggling to find out which approach is the correct or efficient one to implement.

Moreover, how can I implement authorization in Angular 4. I read about canActivateChild interface, but it seems too complicated.

Upvotes: 0

Views: 127

Answers (2)

CoderX
CoderX

Reputation: 1032

I have written two Guards, one for implementing the Authentication and the other one for Authorization.

//Guard for Authentication
@Injectable()
export class AuthGuard implements CanActivate {
    constructor(private loginService: LoginService, private router: Router) { }
    canActivate() {
      if(this.loginService.isLoggedIn()){
        return true;
      }
      this.router.navigate(['/home']);
      return false;
    }
}

//Guard for Authorization
@Injectable()
export class AdminAuthGuard implements CanActivate {
    constructor(private loginService: LoginService, private router: Router) { }
    canActivate() {
      return this.loginService.checkSession().map(res=>{
            let resJSON = res.json();
            let isAllowed = (resJSON.length > 0 && resJSON[0].authority === "ROLE_ADMIN") ? true : (this.router.navigate(['/home']), false);
            return isAllowed;
          });
    }
}

Is this Implementation correct, or should I follow some other? (Although its working fine, but I am looking for a better approach).
The routing file for my application is as follows:

const appRoutes: Routes = [
    {
        path: '',
        redirectTo: '/home',
        pathMatch: 'full'
    },
    {
        path: 'home',
        component: HomeComponent
    },
    {
        path: 'adminPage',
        component: MyAccountComponent,
        canActivate: [AuthGuard, AdminAuthGuard] 
    }
];  

So, whenever I am logged in as the administrator, I can access the adminPage, whereas, if I login as a normal user, I am not able to access the webpage.

The loginService has been implemented as follows:

//Login Service
@Injectable()
export class LoginService {
  private serverPath:string = AppConst.serverPath; //'http://127.0.0.1:8888'
  constructor(private http:Http, private router:Router) { }
  isLoggedIn() {
      return localStorage.getItem('xAuthToken') !== null;
    }
  //Server will send back the Token for the user.   
  sendCredential(username: string, password: string) {
    let url = this.serverPath+'/token';
    let encodedCredentials = btoa(username+":"+password);
    let basicHeader = "Basic "+encodedCredentials;
    let headers = new Headers({
        'Content-Type' : 'application/x-www-form-urlencoded',
        'Authorization' : basicHeader
    });
    return this.http.get(url, {headers: headers});
  }
  //Server returns a JSONARRAY respresenting the roles of the user.
  checkSession() {
    let url = this.serverPath+'/checkSession';
    let headers = new Headers({
        'x-auth-token' : localStorage.getItem('xAuthToken')
    });
    return this.http.get(url, {headers: headers});
  }
  logout() {
    let url = this.serverPath+'/user/logout';
    let headers = new Headers({
        'x-auth-token' : localStorage.getItem('xAuthToken')
    });
    return this.http.post(url, '', {headers: headers});
  }
}

Upvotes: 0

Sangwin Gawande
Sangwin Gawande

Reputation: 8166

I would recommend you to use AuthGuard.

Following is a simple example how you can implement AuthGuard.

Module.ts

// Routes
const routes : Routes = [
{
    path: '',
    component: HomeComponent,
    canActivate : [AuthService] //<== Activate AuthGuard
},
{
    path: 'login',
    component: LoginComponent
},
{
    path: '**',
    redirectTo: ''
}
];
'

@NgModule({
    declarations: [
    AppComponent,
    LoginComponent,
    HomeComponent
    ],
    providers: [AuthService], //<== Add AuthService here
    bootstrap: [AppComponent]
})

AuthService

import { Injectable }     from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot }    from '@angular/router';

@Injectable() 
export class AuthService implements CanActivate {

    constructor(private router: Router) {}

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        let url: string = state.url; //<== Get URL if needed

        if (localStorage.getItem('token')) { // <== Check for token
            return true;
        }else {
            this.router.navigate(['/login']);
            return false;
        }
    }
}

Upvotes: 1

Related Questions