×
iFour Logo

Implementing Auth0 in Angular with NgRx

iFour Team - July 07, 2021

Listening is fun too.

Straighten your back and cherish with coffee - PLAY !

Sustainable

What is Auth0?

Auth0 is a versatile, drop-in solution to add authentication and authorization services to the applications. Auth0 is simple to implement and an adaptable authentication and authorization platform.

Auth0 is a secure service that ensures authentication and authorization functionality when implemented in your application. It works based on tokens and uses different identity providers. It includes several platforms as well as social networks.

When you build your solution to authenticate and authorize users, it can cost you money, time, and risk. To avoid these, we should use Auth0 in our application.

What is NgRx in Angular?

NgRx is a framework for creating reactive applications in Angular. NgRx provides libraries for the following:

  • Managing global and local state.
  • Isolation of side effects to promote a cleaner component architecture.
  • Entity collection management.
  • Integration with the Angular Router.
  • Developer tooling that enhances developer experience when building many different types of applications.

NgRx is an open-source library that provides reactive state management for Angular applications. NgRx provides a way to preserve data in your Angular application as a single source of truth which is inspired by Redux.

NgRx uses streams to communicate with a data store, this data store connects to your components and services and ultimately simplifies the complete method of data management in your Angular application. Rather than injecting services every place and managing communication between them, NgRx manages your application from only one source. Instead of working with individual components, you can work with in terms of its overall state using NgRx.

Implement Auth0 in Angular application with NgRx:

Add the Angular app in Auth0:

The first step is to add the angular application in Auth0.

Go to https://auth0.com/ to create an account in Auth0. You will see the dashboard of Auth0 as shown in the following image.

Click on create an application to integrate auth0 in the Angular application.

changeAuth0Dashboard
Figure 1 Auth0 Dashboard

After clicking on create application from the dashboard, you will be navigated to the following page. On this Page Write the name of your application and click on Single Page Web Applications as we are creating an Angular application.

changeAuth0Dashboard
Figure 2 Create Application Page

Once this is created, you will see the basic information like Name, Client ID, Domain, Client Server as well as application properties, Application URLs, ID token, etc. As we know out Angular will run on the domain HTTP(s)://localhost:4200 locally, so add these URLs into the correct fields of auth0. We have added both http://localhost:4200 and https://localhost:4200 in the fields as shown in the below image, so in the case where we need to switch to HTTPS, we do not face any problems.

From the same page, we will need values of Client ID and Domain to place in our angular application.

Auth0settings
Figure 3 Auth0 settings
 
Create an Angular app and Install the Dependencies

Now, we can create our Angular application with the following command:

ng new Auth0withNgrx

After creating an angular application, we will install Angular helpers from Auth0:

npm install @auth0/auth0-angular

 
Add the Auth service abstraction

Auth0 is a third-party library, so we will create abstraction for it. We will add a file called auth.service.ts.

auth.service.ts:
import { Injectable } from '@angular/core';
                    import { AuthService } from '@auth0/auth0-angular';
                    import { Observable } from 'rxjs';
                    @Injectable({
                      providedIn: 'root',
                    })
                    export class AuthenticationService {
                      constructor(public authService: AuthService) {}
                      get isLoggedIn$(): Observable {
                        return this.authService.isAuthenticated$;
                      }
                      getToken$(): Observable {
                        return this.authService.getAccessTokenSilently();
                      }
                      get user$(): Observable {
                        return this.authService.user$;
                      }
                      login(): void {
                        this.authService.loginWithRedirect();
                      }
                      logout(): void {
                        this.authService.logout({ returnTo: document.location.origin });
                      }
                    }
                    

Include AuthModule

We must include AuthModule form @auth0/auth0-angular in the app.module.ts file. Here we will include the values of Client ID and Domain that we found while creating application in Basic Information in Auth0 dashboard.

app.module.ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AuthModule } from '@auth0/auth0-angular';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { authReducer } from './store/auth.reducer';
import { AuthEffects } from './store/auth.effects';
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    StoreModule.forRoot({ auth: authReducer }),
    EffectsModule.forRoot([AuthEffects]),
    AuthModule.forRoot({
      domain: ' ',
      clientId: '',
      redirectUri: window.location.origin,
    }),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

                
Add NgRx

To add NgRx in our application, we need to include dependencies @ngrx/store and @ngrx/effects by executing the following commands:

ng add @ngrx/store@latest

ng add @ngrx/effects@latest

After adding dependencies in our application, we will create a separate folder for placing NgRx related files in it.

We will create a folder named “store” under the app and place the following four NgRx related files in that folder.

Add the Actions

We will create a file called auth.actions.ts under the store folder for adding actions. We will add the action to trigger the login for calling login as well as a corresponding action for completeness called loginComplete. Same for logout and logoutComplete. We will create an action to trigger when the auth0 redirects back to our angular application for telling the state that it must be changed.

auth.actions.ts:
import { createAction, props } from '@ngrx/store';
                  export const checkAuth = createAction('[Auth] checkAuth');
                  export const login = createAction('[Auth] login');
                  export const loginComplete = createAction(
                    '[Auth] loginComplete',
                    props<{ profile: any; isLoggedIn: boolean }>()
                  );
                  export const logout = createAction('[Auth] logout');
                  export const logoutComplete = createAction('[Auth] logoutComplete');
Add the reducer and the state

The state of our application will be stored in an object called auth with the values – userProfile and idLoggedIn.

{    auth: {
                    isLoggedIn,
                    userProfile }   }

We will create a reducer file called auth.reducer.ts under the store folder to add our state as an interface.

auth.reducer.ts:
import { Action, createReducer, on } from '@ngrx/store';
                      import * as authActions from './auth.actions';
                      export interface AuthState {
                        userProfile: any;
                        isLoggedIn: boolean;
                      }
                      export const initialState: AuthState = {
                        userProfile: null,
                        isLoggedIn: false,
                      };
                      const authReducerInternal = createReducer(
                        initialState,
                        on(authActions.loginComplete, (state, { profile, isLoggedIn }) => {
                          return {
                            ...state,
                            userProfile: profile,
                            isLoggedIn,
                          };
                        }),
                        on(authActions.logoutComplete, (state, {}) => {
                          return {
                            ...state,
                            userProfile: null,
                            isLoggedIn: false,
                          };
                        })
                      );
                      export function authReducer(
                        state: AuthState | undefined,
                        action: Action
                      ): AuthState {
                        return authReducerInternal(state, action);
                      }

The AuthState represents the value the auth property has in our state. The reducer only handles anything that goes on inside of the auth property.

We have set the initialState and create the reducer to pass the initialState. We must add state manipulation when a specific action comes in.

We will add the profile we received if the login is completed with the action loginComplete, and also set the isLoggedIn. We will reset the userProfile to null and isLoggedIn to false when the action logoutComplete is thrown.

Planning to Hire dedicated Angular Developer ?
Your Search ends here.

 
Add the effects

We will use effects for the asynchronous work to do when we are trying to manipulate the state after async actions have finished. We will create auth.effects.ts file for implementing effects.

The following 3 are actions to listen to:

The login, the logout and the checkAuth action.


auth.effects.ts:
import { Injectable } from '@angular/core';
                  import { Actions, createEffect, ofType } from '@ngrx/effects';
                  import { combineLatest, of } from 'rxjs';
                  import { switchMap, tap } from 'rxjs/operators';
                  import { AuthenticationService } from '../auth.service';
                  import * as fromAuthActions from './auth.actions';
                  @Injectable()
                  export class AuthEffects {
                    constructor(
                      private actions$: Actions,
                      private authService: AuthenticationService
                    ) {}
                    login$ = createEffect(
                      () =>
                        this.actions$.pipe(
                          ofType(fromAuthActions.login),
                          tap(() => this.authService.login())
                        ),
                      { dispatch: false }
                    );
                    checkAuth$ = createEffect(() =>
                      this.actions$.pipe(
                        ofType(fromAuthActions.checkAuth),
                        switchMap(() =>
                          combineLatest([this.authService.isLoggedIn$, this.authService.user$])
                        ),
                        switchMap(([isLoggedIn, profile]) => {
                          if (isLoggedIn) {
                            return of(fromAuthActions.loginComplete({ profile, isLoggedIn }));
                          }
                          return of(fromAuthActions.logoutComplete());
                        })
                      )
                    );
                    logout$ = createEffect(() =>
                      this.actions$.pipe(
                        ofType(fromAuthActions.logout),
                        tap(() => this.authService.logout()),
                        switchMap(() => of(fromAuthActions.logoutComplete()))
                      )
                    );
                  }

The login effect will call the authService.login() action and won’t dispatch any other actions then.

The logout action will call the authService.logout() method and will return the logoutComplete.

When we will get redirected from Auth0 to our app again, we will throw the checkAuth action. We will collect the latest information got updated by the service of Auth0 and add it to our state. We have collected isLoggedIn$ and user$ properties and update the state with it. If isLoggedIn is true-which should be the case after the redirect- then we can return a loginComplete action, otherwise, we will reset the state with a logoutComplete action

 
Add the selectors

We will build selectors to make the consumption in components clear which we want from the state and provide it.

We will create a selector for the isLoggedIn and the user-profile property as well as the auth property from the state object.


auth.selector.ts:
                  import { createFeatureSelector, createSelector } from '@ngrx/store';
                  import { AuthState } from './auth.reducer';
                  export const getAuthFeatureState = createFeatureSelector('auth');
                  export const selectCurrentUserProfile = createSelector(
                    getAuthFeatureState,
                    (state: AuthState) => state.userProfile
                  );
                  export const selectIsLoggedIn = createSelector(
                    getAuthFeatureState,
                    (state: AuthState) => state.isLoggedIn
                  );
                  
                
Build component

To consume the values in the state of selectors, the component will consume the selectors. And it dispatches the action checkAuth() when the checkAuth() is loaded to update the information in the state.

It also provides two methods for login and logout.


app.component.ts:
import { Component, OnInit } from '@angular/core';
import { select, Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { checkAuth, login, logout } from './store/auth.actions';
import {
selectCurrentUserProfile,
selectIsLoggedIn
} from './store/auth.selectors';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
title = 'Auth0withNgrx';
loggedIn$: Observable | undefined;
profile$: Observable | undefined;
constructor(private store: Store) {}
ngOnInit() {
this.loggedIn$ = this.store.pipe(select(selectIsLoggedIn));
this.profile$ = this.store.pipe(select(selectCurrentUserProfile));
this.store.dispatch(checkAuth());
}
logout() {
this.store.dispatch(logout());
}
login() {
this.store.dispatch(login());
}
}
/any>
                

We will use the information in the template as needed.

We will display the UserProfile, Name, and Email of the user who logged in.


app.component.html:
<div class="toolbar" role="banner">
      
<span style="text-align: center;margin-left: 725px; font-size: larger;">Welcome To Auth0</span>
<div class="spacer">&nbsp;</div></div>
<div class="content" role="main"><div><p><button>Logout</button>
is logged in {{ loggedIn }}</p>
<div>
<img />
<!-- <pre>{{ profile | json }}</pre> --><pre>Email: {{ profile.email}}</pre>

<pre>


Name: {{ profile.nickname}}</pre>
</div>
</div>
<ng-template><button></button></ng-template></div>
<ng-template> </ng-template> 
 

When we run the project, we will see the following output:

Figure4Output
Figure 4 Output
 

When we click on this button, we will be redirected to the page provided by Auth0.

Figure5Output
Figure 5 Output
 

You need to sign up first either using your email id or your google account. Then you can log in to the system by entering valid credentials and it will redirect you to the information page as follows:

Figure6Output
Figure 5 Output

Conclusion

  • In this blog, we have used the Auth0 service in our angular application for authentication and authorization.
  • We can say that it is more convenient to use the Auth0 service rather than creating our solution for authorization and authentication.
Implementing Auth0 in Angular with NgRx Table of Content 1. What is Auth0? 2. What is NgRx in Angular? 3. Implement Auth0 in Angular application with NgRx: 3.1 Create an Angular app and Install the Dependencies 3.2 Add the Auth service abstraction 4. Include AuthModule 4.1 Add NgRx 4.2 Add the Actions 4.3 Add the reducer and the state 4.4 Add the effects 4.5 Add the selectors 4.6 Build component 5 Conclusion What is Auth0? Auth0 is a versatile, drop-in solution to add authentication and authorization services to the applications. Auth0 is simple to implement and an adaptable authentication and authorization platform. Auth0 is a secure service that ensures authentication and authorization functionality when implemented in your application. It works based on tokens and uses different identity providers. It includes several platforms as well as social networks. When you build your solution to authenticate and authorize users, it can cost you money, time, and risk. To avoid these, we should use Auth0 in our application. What is NgRx in Angular? NgRx is a framework for creating reactive applications in Angular. NgRx provides libraries for the following: Managing global and local state. Isolation of side effects to promote a cleaner component architecture. Entity collection management. Integration with the Angular Router. Developer tooling that enhances developer experience when building many different types of applications. NgRx is an open-source library that provides reactive state management for Angular applications. NgRx provides a way to preserve data in your Angular application as a single source of truth which is inspired by Redux. NgRx uses streams to communicate with a data store, this data store connects to your components and services and ultimately simplifies the complete method of data management in your Angular application. Rather than injecting services every place and managing communication between them, NgRx manages your application from only one source. Instead of working with individual components, you can work with in terms of its overall state using NgRx. Implement Auth0 in Angular application with NgRx: Add the Angular app in Auth0: The first step is to add the angular application in Auth0. Go to https://auth0.com/ to create an account in Auth0. You will see the dashboard of Auth0 as shown in the following image. Click on create an application to integrate auth0 in the Angular application. Figure 1 Auth0 Dashboard After clicking on create application from the dashboard, you will be navigated to the following page. On this Page Write the name of your application and click on Single Page Web Applications as we are creating an Angular application. Figure 2 Create Application Page Once this is created, you will see the basic information like Name, Client ID, Domain, Client Server as well as application properties, Application URLs, ID token, etc. As we know out Angular will run on the domain HTTP(s)://localhost:4200 locally, so add these URLs into the correct fields of auth0. We have added both http://localhost:4200 and https://localhost:4200 in the fields as shown in the below image, so in the case where we need to switch to HTTPS, we do not face any problems. From the same page, we will need values of Client ID and Domain to place in our angular application. Figure 3 Auth0 settings   Create an Angular app and Install the Dependencies Now, we can create our Angular application with the following command: ng new Auth0withNgrx After creating an angular application, we will install Angular helpers from Auth0: npm install @auth0/auth0-angular Read More: The Complete Guide To Angular Security   Add the Auth service abstraction Auth0 is a third-party library, so we will create abstraction for it. We will add a file called auth.service.ts. auth.service.ts: import { Injectable } from '@angular/core'; import { AuthService } from '@auth0/auth0-angular'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root', }) export class AuthenticationService { constructor(public authService: AuthService) {} get isLoggedIn$(): Observable { return this.authService.isAuthenticated$; } getToken$(): Observable { return this.authService.getAccessTokenSilently(); } get user$(): Observable { return this.authService.user$; } login(): void { this.authService.loginWithRedirect(); } logout(): void { this.authService.logout({ returnTo: document.location.origin }); } } Include AuthModule We must include AuthModule form @auth0/auth0-angular in the app.module.ts file. Here we will include the values of Client ID and Domain that we found while creating application in Basic Information in Auth0 dashboard. app.module.ts: import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AuthModule } from '@auth0/auth0-angular'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; import { authReducer } from './store/auth.reducer'; import { AuthEffects } from './store/auth.effects'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule, StoreModule.forRoot({ auth: authReducer }), EffectsModule.forRoot([AuthEffects]), AuthModule.forRoot({ domain: ' ', clientId: '', redirectUri: window.location.origin, }), ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } Add NgRx To add NgRx in our application, we need to include dependencies @ngrx/store and @ngrx/effects by executing the following commands: ng add @ngrx/store@latest ng add @ngrx/effects@latest After adding dependencies in our application, we will create a separate folder for placing NgRx related files in it. We will create a folder named “store” under the app and place the following four NgRx related files in that folder. Add the Actions We will create a file called auth.actions.ts under the store folder for adding actions. We will add the action to trigger the login for calling login as well as a corresponding action for completeness called loginComplete. Same for logout and logoutComplete. We will create an action to trigger when the auth0 redirects back to our angular application for telling the state that it must be changed. auth.actions.ts: import { createAction, props } from '@ngrx/store'; export const checkAuth = createAction('[Auth] checkAuth'); export const login = createAction('[Auth] login'); export const loginComplete = createAction( '[Auth] loginComplete', props<{ profile: any; isLoggedIn: boolean }>() ); export const logout = createAction('[Auth] logout'); export const logoutComplete = createAction('[Auth] logoutComplete'); Add the reducer and the state The state of our application will be stored in an object called auth with the values – userProfile and idLoggedIn. { auth: { isLoggedIn, userProfile } } We will create a reducer file called auth.reducer.ts under the store folder to add our state as an interface. auth.reducer.ts: import { Action, createReducer, on } from '@ngrx/store'; import * as authActions from './auth.actions'; export interface AuthState { userProfile: any; isLoggedIn: boolean; } export const initialState: AuthState = { userProfile: null, isLoggedIn: false, }; const authReducerInternal = createReducer( initialState, on(authActions.loginComplete, (state, { profile, isLoggedIn }) => { return { ...state, userProfile: profile, isLoggedIn, }; }), on(authActions.logoutComplete, (state, {}) => { return { ...state, userProfile: null, isLoggedIn: false, }; }) ); export function authReducer( state: AuthState | undefined, action: Action ): AuthState { return authReducerInternal(state, action); } The AuthState represents the value the auth property has in our state. The reducer only handles anything that goes on inside of the auth property. We have set the initialState and create the reducer to pass the initialState. We must add state manipulation when a specific action comes in. We will add the profile we received if the login is completed with the action loginComplete, and also set the isLoggedIn. We will reset the userProfile to null and isLoggedIn to false when the action logoutComplete is thrown. Planning to Hire dedicated Angular Developer ? Your Search ends here. See here   Add the effects We will use effects for the asynchronous work to do when we are trying to manipulate the state after async actions have finished. We will create auth.effects.ts file for implementing effects. The following 3 are actions to listen to: The login, the logout and the checkAuth action. auth.effects.ts: import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { combineLatest, of } from 'rxjs'; import { switchMap, tap } from 'rxjs/operators'; import { AuthenticationService } from '../auth.service'; import * as fromAuthActions from './auth.actions'; @Injectable() export class AuthEffects { constructor( private actions$: Actions, private authService: AuthenticationService ) {} login$ = createEffect( () => this.actions$.pipe( ofType(fromAuthActions.login), tap(() => this.authService.login()) ), { dispatch: false } ); checkAuth$ = createEffect(() => this.actions$.pipe( ofType(fromAuthActions.checkAuth), switchMap(() => combineLatest([this.authService.isLoggedIn$, this.authService.user$]) ), switchMap(([isLoggedIn, profile]) => { if (isLoggedIn) { return of(fromAuthActions.loginComplete({ profile, isLoggedIn })); } return of(fromAuthActions.logoutComplete()); }) ) ); logout$ = createEffect(() => this.actions$.pipe( ofType(fromAuthActions.logout), tap(() => this.authService.logout()), switchMap(() => of(fromAuthActions.logoutComplete())) ) ); } The login effect will call the authService.login() action and won’t dispatch any other actions then. The logout action will call the authService.logout() method and will return the logoutComplete. When we will get redirected from Auth0 to our app again, we will throw the checkAuth action. We will collect the latest information got updated by the service of Auth0 and add it to our state. We have collected isLoggedIn$ and user$ properties and update the state with it. If isLoggedIn is true-which should be the case after the redirect- then we can return a loginComplete action, otherwise, we will reset the state with a logoutComplete action   Add the selectors We will build selectors to make the consumption in components clear which we want from the state and provide it. We will create a selector for the isLoggedIn and the user-profile property as well as the auth property from the state object. auth.selector.ts: import { createFeatureSelector, createSelector } from '@ngrx/store'; import { AuthState } from './auth.reducer'; export const getAuthFeatureState = createFeatureSelector('auth'); export const selectCurrentUserProfile = createSelector( getAuthFeatureState, (state: AuthState) => state.userProfile ); export const selectIsLoggedIn = createSelector( getAuthFeatureState, (state: AuthState) => state.isLoggedIn ); Build component To consume the values in the state of selectors, the component will consume the selectors. And it dispatches the action checkAuth() when the checkAuth() is loaded to update the information in the state. It also provides two methods for login and logout. app.component.ts: import { Component, OnInit } from '@angular/core'; import { select, Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { checkAuth, login, logout } from './store/auth.actions'; import { selectCurrentUserProfile, selectIsLoggedIn } from './store/auth.selectors'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit{ title = 'Auth0withNgrx'; loggedIn$: Observable | undefined; profile$: Observable | undefined; constructor(private store: Store) {} ngOnInit() { this.loggedIn$ = this.store.pipe(select(selectIsLoggedIn)); this.profile$ = this.store.pipe(select(selectCurrentUserProfile)); this.store.dispatch(checkAuth()); } logout() { this.store.dispatch(logout()); } login() { this.store.dispatch(login()); } } /any> We will use the information in the template as needed. We will display the UserProfile, Name, and Email of the user who logged in. app.component.html: Welcome To Auth0   Logout is logged in {{ loggedIn }} {{ profile | json }} -->Email: {{ profile.email}} Name: {{ profile.nickname}}   When we run the project, we will see the following output: Figure 4 Output   When we click on this button, we will be redirected to the page provided by Auth0. Figure 5 Output   You need to sign up first either using your email id or your google account. Then you can log in to the system by entering valid credentials and it will redirect you to the information page as follows: Figure 5 Output Conclusion In this blog, we have used the Auth0 service in our angular application for authentication and authorization. We can say that it is more convenient to use the Auth0 service rather than creating our solution for authorization and authentication.

Categories

Ensure your sustainable growth with our team

Talk to our experts
Sustainable
Sustainable
 

Blog Our insights

A comprehensive guide on how to hire Frontend developers in 2022
A comprehensive guide on how to hire Frontend developers in 2022

Table of Content 1.What frontend stack to choose for your project? 2.Where to find the right frontend developers? 3.Hiring frontend developers: a step-by-step guide 4.Technical...

Read More
Why construction software is essential for your construction business?
Why construction software is essential for your construction business?

Table of Content 1. Increased profits with reduced risks 2. Powerful integration with accounting software 3. Streamlines key operations with the power of automation 4....

Read More
Why do .NET developers choose Angular over React?
Why do .NET developers choose Angular over React?

Table of Content 1. Angular offers several built-in libraries similar to .NET 2. Angular's syntax is much closer to C# 3. Angular uses TypeScript, a strongly-typed...

Read More