Integrating Auth0 and Formio with Angular(5)

In this article, I am going to show you how to implement social authentication(Facebook, LinkedIn, Github) with Auth0. I will also show you how to integrate formio in Angular.

Getting Setup

I am going to use angular-cli to create an Angular project. You must install angular-cli on your machine

sudo npm install -g angular/cli

Creating Angular project

ng new angular-auth0-test

It will create a new project and install all the dependencies for the project.

What we will build

I am going to build a simple angular application. In this demo application, you can log in to the system by using your GitHub, Facebook, and Google account. You can also register your complaint by submitting the form to the formio application. Let me show you the design of my demo application.

 

Installing Auth0

Now I would like to show you how to install Auth0 in the Angular project. You need to install the auth0-js external npm plugin.

npm install --save auth0-js

You also need to add the auth0 javascript file into angular-cli.json file.

 //angular-cli.json
// ... 
"scripts": [
        "../node_modules/auth0-js/build/auth0.js"
      ],
//...

Setting up Auth0 Account

First of all, you need to signup to Auth0 account. After Signed up successfully now you need to create new client or application. I have created an Angular Aspose application.

You also need to get your Client Id and Client Secret to integrating angular app with Auth0

You can also connect Auth0 to Facebook, Github, and Google 

Creating Auth Service

We need to AuthService to interact with Auth0. I am going to create new AuthService in my Angular project. Any component can inject the AuthService to interact with Auth0.

//auth/auth.service.ts

@Injectable()
export class AuthService {

  auth0 = new auth0.WebAuth({
    clientID: 'rdw4tCARJ6r6avcLozhYaTn2e7Rghl2344', //add your clientId here
    domain: 'haidermalik.auth0.com', //add your domain name
    responseType: 'token id_token',
    audience: 'http://localhost:8083/api/',
    redirectUri: `${ENV.BASE_URI}/callback`,
    scope: 'openid'
  });
  userProfile: any;

  constructor(public router: Router) {}

  public login(): void {
    this.auth0.authorize();
  }

  public handleAuthentication(): void {
    this.auth0.parseHash((err, authResult) => {
      if (authResult && authResult.accessToken && authResult.idToken) {
        window.location.hash = '';
        this._getProfile(authResult);
        this.router.navigate(['/home']);
      } else if (err) {
        this.router.navigate(['/home']);
        console.log(err);
      }
    });
  }

  private _getProfile(authResult) {
    // Use access token to retrieve user's profile and set session
    this.auth0.client.userInfo(authResult.accessToken, (err, profile) => {
      if (profile) {
        this.setSession(authResult, profile);
      } else if (err) {
        console.warn(`Error retrieving profile: ${err.error}`);
      }
    });
  }

  private setSession(authResult, profile): void {
    // Set the time that the access token will expire at
    const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
    localStorage.setItem('access_token', authResult.accessToken);
    localStorage.setItem('id_token', authResult.idToken);
    localStorage.setItem('expires_at', expiresAt);
    localStorage.setItem('profile', JSON.stringify(profile));
    this.userProfile = profile;
    console.log(this.userProfile);
  }

  public logout(): void {
    // Remove tokens and expiry time from localStorage
    localStorage.removeItem('access_token');
    localStorage.removeItem('id_token');
    localStorage.removeItem('expires_at');
    // Go back to the home route
    this.router.navigate(['/']);
  }

  public isAuthenticated(): boolean {
    // Check whether the current time is past the
    // access token's expiry time
    const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
    return new Date().getTime() < expiresAt;
  }

}

You have to add your clientId. When you click on the login button. Angular Application will call the Auth0 authorize method. After Authenticated successfully, the handleAuthentication  method will be called and saved this access token to localStorage.

Creating Callback Component

Let me show you how to create new callback component.

ng g c callback
//callback.component.html
<div class="loading">
  <img src="assets/loading.svg" alt="loading">
</div>

Auth0 will use this callback component to display the loader on the screen. It indicates that the system is busy with authenticating you from Auth0.

Adding Routes

I will add all my routes in app.routes.ts file. I will add all these routes in root AppModule. Angular provides RouterModule for adding routing. We have a method RouterModule.forRoot. This method will take the routes array.

//app.routes.ts
import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { CallbackComponent } from './callback/callback.component';
import {ComplaintViewComponent} from './complaint-view/complaint-view.component';

export const ROUTES: Routes = [
  { path: '', component: HomeComponent },
  { path: 'callback', component: CallbackComponent },
  { path: 'complaint', component: ComplaintViewComponent },
  { path: '**', redirectTo: '' }
];

Adding Navbar

I have added the bootstrap nav bar in the app.component.html file. I have used the router-outlet to display the dynamic content on this section.

//app.component.html
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
  <a class="navbar-brand" routerLink="['home']">Aspose Angular</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor01"
          aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>

  <div class="collapse navbar-collapse" id="navbarColor01">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link" [routerLink]="['home']">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item active">
        <a class="nav-link" [routerLink]="['complaint']">Complaint</a>
      </li>
    </ul>
    <ul class="navbar-nav ml-auto">
      <li class="nav-item">
        <button
          class="btn btn-primary btn-margin"
          *ngIf="!auth.isAuthenticated()"
          (click)="auth.login()">
          Log In
        </button>
      </li>
      <li class="navbar-item">
        <button
          class="btn btn-primary btn-margin"
          *ngIf="auth.isAuthenticated()"
          (click)="auth.logout()">
          Log Out
        </button>
    </ul>
  </div>
</nav>

<main class="container">
    <div class="row row-margin">
      <div class="col-md-8">
        <router-outlet></router-outlet>
      </div>
    </div>
</main>

 

Setting up Formio Account

I will use Formio to submit the data from the Form. You have to create new Angular project on the Formio dashboard

Creating new Form on Formio

You need to create a new form in the project. I have created a complaint form in my project

 

 

 

 

 

 

 

 

 

 

 

 

 

Complaint Form

Formio is very good drag and drop plugin. You can design your app by using drag and drop feature. I have created three fields in my complaint form. You can see that I have firstName, lastName and description field in my form

Submitting the Form to Formio

If you want to render the complaint form in your Angular project, you have to create a new complaint-view component in your project.

ng g c complaint-view

You have to copy your live project URL and add this URL as a template file.

//complaint-view/complaint-view.component.html
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-complaint-view',
  template: '<formio src="https://bdtpdgjewsrxied.form.io/complaint"></formio>',
  styleUrls: ['./complaint-view.component.css']
})
export class ComplaintViewComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

Source Code:

You can access the complete source code from this repository: https://github.com/HaiderMalik12/aspose-ng-test

Conclusion

You have learned how to integrate formio and Auth0 in the Angular project.

  • Auth0 allows you to authenticate and authorize apps and APIs with any identity provider running on any stack on any device or cloud.
  • Auth0 provides SDKs for all popular web, mobile, and native platforms, allowing for deep integration with the language and stack of your preference.
  • With Auth0 you can enable Multifactor Authentication in minutes
Design Pattern used:
  • Modular design
  • Unidirectional data flow
  • Predictable state management
  • Communication layer for async requests
  • Decoupled presentational layer from core layer
  • Dependency Injection
Formio Advantages:
  • You can build complex customized forms within minutes.
  • One of the best features of Formio is FormBuilder which allows you to build forms using Drag and Drop
  • If you want to display the complex data on the table then formio is a perfect choice for that kind of applications
  • It also allows you to add Authentication, Roles, and Permission in your project

 

 

 

 

Leave a Comment: