Skip to content

User Authentication

Travis Tidwell edited this page Sep 5, 2018 · 14 revisions

Now that you have rendered a form, you will probably want to allow your users to authentication into your Form.io project from within your own application. To do this, you will be using the Form.io Authentication Service. You can install this provider into your application using the combination of the FormioAuthService and FormioAuthConfig which is used to provide the configurations to this service.

index.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormioModule } from 'angular-formio';
import { FormioAuthService, FormioAuthConfig } from 'angular-formio/auth';
import { MainComponent } from './main';

@NgModule({
  imports: [
    BrowserModule,
    FormioModule
  ],
  declarations: [
    MainComponent
  ],
  providers: [
    FormioAuthService,
    {
      provide: FormioAuthConfig, 
      useValue: {
        app: {
          appUrl: 'https://myproject.form.io',
          apiUrl: 'https://api.form.io'
        },
        login: {
          form: 'user/login'
        },
        register: {
          form: 'user/register'
        }
      }
    }
  ],
  bootstrap: [
    MainComponent
  ]
})
export class AppModule {}

Notice how we are configuring all of our application specifics within the Authentication Configuration provided to the Authentication Service. This allows all authentication to occur against our own Form.io project.

Now that you have an Authentication service in place, then next thing you will want to do is provide the Routes to allow the user to login to your application.

Authentication Routes

To provide some routes for your users to authenticate, it is first important to create a new module which will be used to serve as the landing page for your users when they login and register. To do this, we will create a new auth.module.ts which will contain the following code.

ng g module auth

auth.module.ts

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FormioAuth, FormioAuthRoutes } from 'angular-formio/auth';
@NgModule({
  imports: [
    FormioAuth,
    RouterModule.forChild(FormioAuthRoutes())
  ]
})
export class AuthModule {}

What this allows us to do is create a new route which will load the User Login and User Register page within our application. We can also configure the routes to provide our own components for any of the states within the routing. For example, lets suppose we wish to provide our own Component for login, where we can then define our own template. We can do this by declaring our own LoginComponent class, and extending the base as follows.

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FormioAuthModule, FormioAuthService, FormioAuthRoutes, FormioAuthLoginComponent } from 'angular-formio/auth';

@Component({
  template:
    '... YOUR OWN TEMPLATE HERE ...'
})
export class UserLoginComponent extends FormioAuthLoginComponent {
  constructor(service: FormioAuthService) {
    super(service);
  }
}

@NgModule({
  imports: [
    FormioAuthModule,
    RouterModule.forChild(FormioAuthRoutes({
      login: UserLoginComponent
    }))
  ]
})
export class AuthModule {}

You can also provide your own custom components for the register as well as auth components giving you full flexibility to provide your own business logic when logging in.

Once you have registered the module, the next thing you need to do is mount this module at a certain path within your main application. You can do this with the loadModule method within Angular 2.

index.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, Routes } from '@angular/router';
import { FormioModule } from 'angular-formio';
import { FormioAuthService, FormioAuthConfig } from 'angular-formio/auth';
import { MainComponent } from './main';

@NgModule({
  imports: [
    BrowserModule,
    FormioModule,
    RouterModule.forRoot([
      {
        path: 'auth',
        loadChildren: './auth/auth.module#AuthModule'
      }
    ])
  ],
  declarations: [
    MainComponent
  ],
  providers: [
    FormioAuthService,
    {
      provide: FormioAuthConfig, 
      useValue: {
        app: {
          appUrl: 'https://myproject.form.io',
          apiUrl: 'https://api.form.io'
        },
        login: {
          form: 'user/login'
        },
        register: {
          form: 'user/register'
        }
      }
    }
  ],
  bootstrap: [
    MainComponent
  ]
})
export class AppModule {}

Authentication Properties

Once a user is authenticated into the system, they are then established within the Service provider along with other properties that you can use within your application. These properties are as follows.

  • user - The authenticated user.
  • ready - A promise that is evaluated when all authentication is ready to be consumed.

As an example, lets suppose you wish to add a User link within your header for the user information when the user is logged in, but then show a Login link when they are not logged in. This could be done with the following code.

<ul class="nav navbar-nav navbar-right">
  <li routerLinkActive="active" *ngIf="!auth.authenticated"><a routerLink="auth">Login | Register</a></li>
  <li *ngIf="auth.authenticated"><a routerLink="home" (click)="auth.logout()"><span class="glyphicon glyphicon-off"></span> Logout</a></li>
</ul>

Authentication Events

Now that you are able to provide your own authentication mechanism, you may also want to perform certain operations when Authentication events occur within your application. The service includes a number of events that you can subscribe to which are as follows.

  • onLogin - Triggered when the user logs in.
  • onLogout - Triggered when the user logs out.
  • onRegister - Triggered when the user registers.
  • onUser - Called anytime the user object is established from the server.
  • onError - Called for any errors that occur during the authentication process.
  • ready - Promise that is triggered when all authentication systems are ready.

In order to register for these events, you can do as follows.

main.component.ts

import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { FormioAuthService } from 'angular-formio/auth';

@Component({
  selector: 'formio-app',
  template: require('./main.html')
})
export class MainComponent {
  constructor(private auth: FormioAuthService, private router: Router) {
    this.auth.onLogin.subscribe(() => {
      this.router.navigate(['/']);
    });

    this.auth.onLogout.subscribe(() => {
      this.router.navigate(['/']);
    });

    this.auth.onRegister.subscribe(() => {
      this.router.navigate(['/']);
    });
  }
}

Full Working Example

For a full working application example of how this works, please take a look at the Angular Demo Application project.