Install library using command
npm install @uoa/auth
In your app.module.ts import following, eg:
import { AuthModule, CognitoConfigService, StorageService } from '@uoa/auth';
Include AuthModule
in your imports[], add CognitoConfigService and StorageService as a provider:
{ provide: CognitoConfigService, useClass: AppAuthConfigService }
{ provide: StorageService, useClass: AppStorageService },
You will need to create this AppAuthConfigService class, which assigns each property from your environment file. here is an example:
import { Injectable } from '@angular/core';
import { CognitoConfigService } from '@uoa/auth';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class AppAuthConfigService extends CognitoConfigService {
constructor() {
super();
this.codeChallengeMethod = environment.auth.codeChallengeMethod;
this.cognitoAwsRegion = environment.auth.cognitoAwsRegion;
this.cognitoClientId = environment.auth.cognitoClientId;
this.cognitoDomain = environment.auth.cognitoDomain;
this.cognitoUserPoolId = environment.auth.cognitoUserPoolId;
this.scopes = environment.auth.scopes;
this.redirectUri = environment.auth.redirectUri;
this.logoutUri = environment.auth.logoutUri;
this.bearerTokenUrlFilter = environment.privateUrlKeyWords.whoNeedBearerToken;
}
}
In environment config whoNeedBearerToken will be as follow:
whoNeedBearerToken: [{ url: 'apiUrl', optional: false }],
Default value of optional is false. If you set it to true token will not be added when user is not loggedIn. You can further define either public or protected paths to ensure correct headers are passed with request. If you application is partial protected and mostly public you can define protectedPaths as follow.
whoNeedBearerToken: [{ url: 'apiUrl', optional: true, protectedPaths: ['user', 'answers/save'] }],
If you application is partial public and mostly protected you can define publicPaths as follow.
whoNeedBearerToken: [{ url: 'apiUrl', optional: true, publicPaths: ['home', 'questions/careers', 'interests/personalAttributes' ] }],
Path values are list of API end points which will be checked if they are part of endpoint called (apiUrl/path
).
You will need to create this AppStorageService class and implement all the abstract methods (getItem, setItem, removeItem). In order to implement storageService class there are two recommendations.
- Use Ionic storage if you are building Ionic project.
Install ionic storage using command
npm install @ionic/storage-angular
In your app.module.ts import following, eg:
import { IonicStorageModule } from '@ionic/storage-angular';
Include IonicStorageModule.forRoot()
in your imports[],
AppStorageService class implementation using IonicStorage:
import { Injectable } from '@angular/core';
import { StorageService } from '@uoa/auth';
import { Storage } from '@ionic/storage-angular';
@Injectable({
providedIn: 'root',
})
export class AppStorageService implements StorageService {
constructor(private storage: Storage) {}
getItem(key: string): Promise<any> {
return this.storage.get(key);
}
setItem(key: string, val: any): Promise<void> {
this.storage.set(key, val);
}
removeItem(key: string): void {
this.storage.remove(key);
}
}
- Use localforage if you are building angular Project.
Install localforage storage using command
npm install localforage
AppStorageService class implementation using localforage:
import { Injectable } from '@angular/core';
import { StorageService } from '@uoa/auth';
import * as localforage from 'localforage';
@Injectable({
providedIn: 'root',
})
export class AppStorageService implements StorageService {
getItem(key: string): Promise<any> {
return localforage.getItem(key);
}
setItem(key: string, val: any): void {
localforage.setItem(key, val);
}
removeItem(key: string): void {
localforage.removeItem(key);
}
}
If you want to use different storage, it is upto you.
Import guards from library and add it to your routes, here is an example:
import { AuthGuard, LoginSuccessGuard } from '@uoa/auth';
const routes: Routes = [
{
path: '',
redirectTo: 'home',
pathMatch: 'full',
},
{
path: 'home',
canActivate: [LoginSuccessGuard],
loadChildren: () => import('./pages/home/home.module').then((m) => m.HomePageModule),
},
{
path: 'protected',
canActivate: [AuthGuard],
loadChildren: () => import('./pages/protected/protected.module').then((m) => m.ProtectedPageModule),
},
{
path: '**',
redirectTo: '/home',
},
];
Add LoginSuccessGuard
to default route if you are not protecting all pages.
If you want to make whole app protected then your routes will be as follow:
import { AuthGuard } from '@uoa/auth';
const routes: Routes = [
{
path: '',
redirectTo: 'home',
pathMatch: 'full',
},
{
path: 'home',
canActivate: [AuthGuard],
loadChildren: () => import('./pages/home/home.module').then((m) => m.HomePageModule),
},
{
path: 'protected',
canActivate: [AuthGuard],
loadChildren: () => import('./pages/protected/protected.module').then((m) => m.ProtectedPageModule),
},
{
path: '**',
redirectTo: '/home',
},
];
In order to get logged in user details, use method:
this.loginService.getUserInfo();
or
this.loginService.userInfo$
In order to check if user is authenticated or not, use method:
this.loginService.isAuthenticated();
after calling this method you can use loggedIn observable from loginService.
this.loginService.loggedIn$
It returns Promise.
In order to logout user, use method:
this.loginService.logout();
If you don't want to use refreshtoken to get new token in your application, you can set it to false inside AppAuthConfigService. Default value is true.
this.useRefreshToken = false;
Similarly If you don't want to navigate to login page when token is expired in your application, you can set 'navigateWithoutToken' to false inside AppAuthConfigService. Default value is true.
this.navigateWithoutToken = false;
In your app.module.ts import ErrorPagesModule, eg:
import { ErrorPagesModule } from '@uoa/error-pages';
Include ErrorPagesModule in your imports[].
Create an ErrorRoutingModule to define the error page child route
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { ErrorPagesModule, ErrorPage } from '@uoa/error-pages';
@NgModule({
imports: [ErrorPagesModule, RouterModule.forChild([{ path: '', component: ErrorPage }])],
exports: [RouterModule],
})
export class ErrorRoutingModule {}
Go to routing module of application and add error route to routes. Here is an example:
{
path: 'error/:errorCode',
loadChildren: () => import('./error-routing.module').then((m) => m.ErrorRoutingModule),
}