Help us understand the problem. What is going on with this article?

Angular+Cognitoのユーザー認証にGuardを使う

はじめに

以前、Angular+Cognitoのユーザー認証付きSPAのサンプルという記事を書きましたが、このときは各コンポーネントでCognito認証済かどうかのチェックをのチェックを行っていましたが、AngluarにはGuardというルーティングを行うタイミングで、ルーティングの拒否、許可の分岐を行える仕組みがあります。
今回は、前回作成したサンプルをGuardを使った形に書き換えていきたいと思います。

手順

guardの作成

angluar-cliにはguardを作成するgenerateコマンドも要されているので、簡単にひな形を作成することが出来ました。

$ ng g guard guard/auth
auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    return true;
  }
}

また、サービスを追加するときと同様にapp.module.tsにインポートし、@NgModuleprovidersに追加しておきます。

guardの修正

前回の記事でcognito.service.tsに実装したisAuthenticated ()メソッドを使ってguard内で認証済み判定を行います。
angluar-cliで作成されたguardを見て分かる通り、canActivateはObservable、Promiseそれぞれのbooleanまたはbooleanを戻り値に取ることが出来ます。

auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { CognitoService } from './../service/cognito.service';

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(
    private cognitoService: CognitoService,
    private router: Router
  ) {

  }
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Promise<boolean> {
      return this.cognitoService.isAuthenticated()
      .then(data => {
        return Promise.resolve(true);
      }).catch(err => {
        this.router.navigate(['/login']);
        return Promise.resolve(false);
      });
    }
}

上記では、CognitoServiceとRouterをインポートしています。
Routerをインポートするのは、認証済み出なかった場合に、loginページにリダイレクトするためです。

Routerの設定

app-routing.module.tsを修正して、RouterでGuardを使用するように設定します。
認証が必要な、routes内のuploaduploadオブジェクトにcanActivateパラメータを追加して先ほど作成したGuardを指定します。

app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SignupComponent } from './public/signup/signup.component';
import { LoginComponent } from './public/login/login.component';
import { UploadComponent } from './secure/upload/upload.component';
import { FilesComponent } from './pages/files/files.component';
import { AuthGuard } from './guard/auth.guard';

const routes: Routes = [
  {
    path: 'signup',
    component: SignupComponent,
  },
  {
    path: 'login',
    component: LoginComponent,
  },
  {
    path: 'upload',
    component: UploadComponent,
    canActivate: [AuthGuard]
  },
  {
    path: 'files',
    component: FilesComponent,
    canActivate: [AuthGuard]
  },
  {
    path: '',
    redirectTo: '/upload',
    pathMatch: 'full'
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

コンポーネントの修正

上記までの手順でguardの設定が済んだので、各コンポーネントのコンストラクタ内で行っている認証チェックのロジックを削除してしまいます。
files.component.tsupload.component.tsそれぞれの以下の箇所を削除します。

files.component.ts
-    this.cognito.isAuthenticated()
-    .then(res => console.log(res))
-    .catch((err) => {
-      return console.log(err) || this.router.navigate(['/login']);
-    });

手順としては以上です。
開発サーバーを立ち上げて、それぞれのページにアクセスすると正しくルーティングされているのが確認できるかと思います。

今回のサンプルコード

https://github.com/daikiojm/angular-cognito-s3-file-uploader/tree/feature/guard

参考

angular.io
https://angular.io/guide/router

Auth0 + AngluarのGuardを使った例ですが、大変参考になりました🙏
https://qiita.com/ovrmrw/items/f7003a5df4aa58cb4857

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away