This article is the follow up of Angular 2+ and Ruby on Rails user authentication Part 1: Backend User Profile, Auth Service and Auth Router Guard Intro The premise is to show user profile info (name, nickname, email, etc) on route and make a guard for it, so when someone tries to reach it without being authenticated, gets redirected to route, we’ll also write an to wrap all of our auth related stuff in one place. /profile home Auth Service Auth Service First and foremost, we need to create an which will wrap all of Auth related states and actions in one place, in particular and user (user is logged in/out), and all off it (brace yourselves RxJS is incoming) Authetication Service login/logout actions authentication status asynchronously as a stream . ng g s services/auth s = service This is our authentication service ( ): ./src/app/services/auth.service.ts Looks intimidating at first glance, but trust me, there is nothing complicated, so let’s break it down: userSignedIn$ is a (of type boolean), which means it is an and an at the same time, which means we can control its value in our service, and observe its changes outside of it. Line 9: RxJs Subject Observer Observable Our constructor will initialize the login state by using TokenService’s method, which will validate current token (if exists) against the Rails backend, this operation is asynchronous and returns in its body an object that looks like this: validateToken() So we can use key to determine wether the user is logged in with a valid token or not (line 14). success Dollar sign ($) at the end of the name is a convention to specify that this is not a simple variable, but an observable stream of data which changes in time. Our method takes no params and returns an , we’ll call on , but before returning its response, we’ll map though it to change value to (line 19) in order to notify our observers that user successfully logged out, and then return the response to whomever is observing the result of method (line 20). logOutUser() Observable of Response signOut() Angular2TokenService userSignedIn$ false logOutUser() The method takes an object with email and password keys, and uses it to sign in from Angular2TokenService signIn() method. And again, before returning the response we will modify value to which will notify the observers that user logged in successfully**.** logInUser userSignedIn$ true, The method is similar to loginUser, but we have an additional password confirmation attribute in the input object. registerUser Let’s not forget to inject it into our main AppModule’s providers ( ): ./src/app/app.module.ts ... import {AuthService} from "./services/auth.service"; @NgModule({declarations: [AppComponent,HomeComponent,ToolbarComponent,AuthDialogComponent,LoginFormComponent,RegisterFormComponent,ProfileComponent],imports: [BrowserModule,FormsModule,HttpModule,AppRoutingModule,MaterializeModule,],providers: [ Angular2TokenService, ],bootstrap: [AppComponent]})export class AppModule { } AuthService Refactoring Login and Toolbar components to use AuthService Now we need to make some small changes to our and components in order to use AuthService instead of Angular2TokenService directly. Login Toolbar Refactoring the Toolbar Let’s start with ToolBarComponent class ( ): ./src/app/toolbar/toolbar.component.ts As you can see, we got rid of and injected our custom instead (line 16), we also created a method which will call action on our , and using Angular Router, redirect the user to when logout action completes (line 21). Angular2TokenService AuthService logOut() logOutUser AuthService home Now let’s change Toolbar’s template ( ): ./src/app/toolbar/toolbar.component.html Now we are using our AuthService’s Subject to change the state of the toolbar when user logs in or out, considering that is not a simple value, but an asynchrnous stream of values chaning in time, we need to use Angular’s async pipe to listen to its changes (lines 11, 12, 14, 15). We’ll also link the click event on to toobar component’s method we created earlier (line 15). userSignedIn$ userSignedIn$ logout button logOut() Refactoring the Login From Changes on login form will be extremely minimal, we just need to change the LoginFormComponent class ( ) ./src/app/login-form/login-form.component.ts The only thing we needed to do is getting rid of and replacing it with our and its method. Angular2TokenService AuthService logInUser Don’t forget to apply the same changes to RegisterFormComponent And that’s it, refactoring is over. User profile page Profile component First step is obvious, let’s generate our that will display current user’s info: ProfileComponent ng g c profile The component should be automatically imported in AppModule’s declarations. Profile route In our router module ( ), let’s declare the profile route: ./src/app/app-routing.module.ts Import the profile component: import {ProfileComponent} from "./profile/profile.component"; Declare the route: ... const routes: Routes = [{path: '',component: HomeComponent,pathMatch: 'full'},{path: 'home',component: HomeComponent}, ];... {path: 'profile',component: ProfileComponent} UI As for the design of profile page, it’ll be pretty simple, we’ll display user’s email, name, and user name in a and use its footer to add a logout button. Materialize Card Let’s inject Angular2TokenService into our ProfileComponent, and add a logout method ( ): ./app/profile/profile.component.ts We’ll be making use of to display user’s personal information, to implment the logout action, and the to redirect after logout completes, so we need to inject these in our (lines 14–16) Angular2TokenService AuthService Router ProfileComponent Nn line 18, we have a action which redirects the user to home when it completes. logOut Reimplementing the action for each component seems repetitive, but this is actually useful, because we can implement different post-logout behaviours for each component, for example redirecting to some other route instead of home. logOut Profile Component’s template, ( ./src/app/profile/profile.component.html) Angular2TokenService’s attribute provides information about our user if he is logged in (email, name, nickname, etc.), its value is when user is not logged in. currentUserData undefined One line 15, we are usign structural directive to test if there is any data to display, if not we will not show the user info card. *ngIf On line 31 we also have a logout button, linked to method of our class. logOut ProfileComponent Be sure to add a cleafix class to because Materialize doesn’t implement it. ./src/app/profile/profile.component.sass .clearfixoverflow: auto And this is what we get when we navigate to route while being logged in: /profile User info card Auth Route Guard Now the problem is, we still can navigate to route even if we are not logged in: /profile Angular’s Route Guards can help us to fix this issue. Route Guards are pretty easy to understand, it’s a simple class which implements interface, this interface demands us to implement a method**,** which returns a single boolean value ( ), and depending on that boolean value the Router will allow or forbid the activation of a route, the logic is up to us to implement, so let’s do that. CanActivate canActivate() or an Observable of type boolean, although I couldn’t manage to make them work properly Create an AuthGuard class in ( ): ./src/app/guards/auth.guard.ts As you can see, our AuthGuard class implements interface and its method, the logic is simple, Angular2TokenService’s userSignedIn() method returns a signle boolean value, we’ll use it to determine if user is signed in, if so, we allow the activation by returning true, of not, we’ll redirect to home and forbid the activation by returning false. CanActivate canActivate() Don’t forget to inject it in our AppModule’s providers: ... import {AuthGuard} from "./guards/auth.guard"; @NgModule({declarations: [AppComponent,HomeComponent,ToolbarComponent,AuthDialogComponent,LoginFormComponent,RegisterFormComponent,ProfileComponent],imports: [BrowserModule,FormsModule,HttpModule,AppRoutingModule,MaterializeModule,],providers: [ Angular2TokenService, AuthService, ],bootstrap: [AppComponent]})export class AppModule { } AuthGuard Now let’s protect our route, open and set profile route’s guard: /profile ./src/app/app-routing.module.ts import { NgModule } from '@angular/core';import { Routes, RouterModule } from '@angular/router';import {HomeComponent} from "./home/home.component";import {ProfileComponent} from "./profile/profile.component";import {AuthGuard} from "./guards/auth.guard"; const routes: Routes = [{path: '',component: HomeComponent,pathMatch: 'full'},{path: 'home',component: HomeComponent},{path: 'profile',component: ProfileComponent, }]; canActivate: [AuthGuard] @NgModule({imports: [RouterModule.forRoot(routes)],exports: [RouterModule],providers: []}) export class AppRoutingModule { } key takes an array of guards, in case you have several guards on a single route, all of them must return in order for the route to be activated. canActivate true Now, when we go to without being logged in, we’ll get redirected to home, and any Router Link with /profile as a route, will produce no effect when clicked on. /profile And there you go, a profile page, protected by a Route Guard. You can get the final code for this part on GitHub: https://github.com/avatsaev/angular-token-auth-seed/tree/profile Let me know if you have any remarks about the tutorial, I’ll be happy to help and correct it if something isn’t clear enough :) Thank you for reading this series, follow me on Twitter ( ) for more interesting stuff on Angular 2+ and Rails. https://twitter.com/avatsaev