IonicでCognito認証してみた
こんにちは、森田です。
Cognitoの認証機能を試すべく、Ionic(Angular)を用いて行っていきます。
Cognitoとは?
モバイル・Webアプリ向けのユーザ認証をマネージドで提供しているAWSサービスです。
直接メールアドレスなどでのサインインはもちろんのこと、Google、Facebook、Amazon などのソーシャル ID プロバイダーや、エンタープライズ ID プロバイダーを通してもサインインすることができます。
AWS リソースのアクセスコントロールをユーザに対して設定もできますので、ログインユーザのみコンテンツを配布するというようなことも容易に行えます。
また、50,000MAUまで無料で使用できるので、小規模なサービスとかであれば無料で使えそうです。
環境
- Ionic 5.4.16
- Angular 12.0.5
- npm 7.15.1
- amazon-cognito-identity-js 5.0.3
やってみた
Cognito ユーザプールの作成
今回はCognitoのユーザプールを使用して認証を行います。
コンソールでユーザプールを作成していきます。
メールアドレスを利用してサインアップを行いますので、標準属性にemail
を指定します。
続いてアプリクライアントを追加します。
名前を設定し、アプリクライアントの作成を行います。
あとは、デフォルトで進めていき、ユーザプールの作成を完了させます。
Ionic アプリケーションの作成
今回は、blank
テンプレートを使用して作成していきます。
ionic start cognito-demo blank
アプリケーションのディレクトリに移動し、ログイン、サインアップ、認証コードの入力ページをそれぞれ作成します。
ionic g page login ionic g page sign-up ionic g page confirm
cognitoの処理用にサービスそ作成します。
ionic g service cognito-service
sdkを追加します。
npm install --save amazon-cognito-identity-js
CognitoUserPoolオブジェクトを作成し、オブジェクトのAttributeでCognitoの操作を行います。 プールIDとアプリクライアントIDが必要となりますので、環境変数から読み込みます。
cognito-service.service.ts
import { Injectable } from '@angular/core'; import * as AWSCognito from "amazon-cognito-identity-js"; import { environment } from '../environments/environment'; @Injectable({ providedIn: 'root' }) export class CognitoServiceService { _POOL_DATA = environment.cognito_data; //サインアップ用の関数 signUp(email, password) { return new Promise((resolved, reject) => { const userPool = new AWSCognito.CognitoUserPool(this._POOL_DATA); let userAttribute = []; userAttribute.push( new AWSCognito.CognitoUserAttribute({ Name: "email", Value: email }) ); userPool.signUp(email, password, userAttribute, null, function(err, result) { if (err) { reject(err); } else { resolved(result); } }); }); } //メールアドレス確認用の関数 confirmUser(verificationCode, userName) { return new Promise((resolved, reject) => { const userPool = new AWSCognito.CognitoUserPool(this._POOL_DATA); const cognitoUser = new AWSCognito.CognitoUser({ Username: userName, Pool: userPool }); cognitoUser.confirmRegistration(verificationCode, true, function(err, result) { if (err) { reject(err); } else { resolved(result); } }); }); } //認証用の関数 authenticate(email, password) { return new Promise((resolved, reject) => { const userPool = new AWSCognito.CognitoUserPool(this._POOL_DATA); const authDetails = new AWSCognito.AuthenticationDetails({ Username: email, Password: password }); const cognitoUser = new AWSCognito.CognitoUser({ Username: email, Pool: userPool }); cognitoUser.authenticateUser(authDetails, { onSuccess: result => { resolved(result); }, onFailure: err => { reject(err); }, newPasswordRequired: userAttributes => { userAttributes.email = email; delete userAttributes.email_verified; cognitoUser.completeNewPasswordChallenge(password, userAttributes, { onSuccess: function(result) {}, onFailure: function(error) { reject(error); } }); } }); }); } }
ログインページ、サインアップページにそれぞれ処理を追加します。
login.page.ts
import { Component, OnInit } from '@angular/core'; import { CognitoServiceService} from "../cognito-service.service"; import { SignUpPage } from "../sign-up/sign-up.page"; import {AlertController } from "@ionic/angular"; @Component({ selector: 'app-login', templateUrl: './login.page.html', styleUrls: ['./login.page.scss'], }) export class LoginPage { email: string; password: string; signUpPage = SignUpPage; constructor( public CognitoSerive:CognitoServiceService, public alertController: AlertController ) { } login(){ this.CognitoSerive.authenticate(this.email, this.password) .then(res =>{ console.log(res); this.login_alert("ログインに成功しました"); }, err =>{ console.log(err); this.login_alert("ログインに失敗しました"); }); } async login_alert(header) { const alert = await this.alertController.create({ cssClass: 'my-custom-class', header: header, buttons: ['OK'] }); await alert.present(); } }
sign-up.page.ts
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { CognitoServiceService} from "../cognito-service.service"; import { AlertController } from "@ionic/angular"; @Component({ selector: 'app-sign-up', templateUrl: './sign-up.page.html', styleUrls: ['./sign-up.page.scss'], }) export class SignUpPage { email: string; password: string; constructor( public alertController: AlertController, public router: Router, public CognitoService: CognitoServiceService ) {} async register() { this.CognitoService.signUp(this.email, this.password).then( res => { localStorage.setItem('mail', this.email); this.router.navigateByUrl('/confirm'); }, err => { console.log(err); this.presentAlert(err["message"]); } ); } async presentAlert(alert_message) { const alert = await this.alertController.create({ cssClass: 'my-custom-class', header: 'エラーが発生しました', message: alert_message, buttons: ['OK'] }); await alert.present(); } }
confirm.page.ts
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { CognitoServiceService} from "../cognito-service.service"; import {AlertController } from "@ionic/angular"; @Component({ selector: 'app-confirm', templateUrl: './confirm.page.html', styleUrls: ['./confirm.page.scss'], }) export class ConfirmPage { code : string; constructor( public alertController: AlertController, public router: Router, public CognitoService: CognitoServiceService, ) { } func(){ const mail = localStorage.getItem('mail'); console.log(this.code); this.verifyUser(String(this.code), mail); } verifyUser(verificationCode ,mail) { this.CognitoService.confirmUser(verificationCode, mail).then( res => { console.log(res); this.auth_verify(); this.router.navigateByUrl('/login'); }, err => { alert(err.message); } ); } async auth_verify() { const alert = await this.alertController.create({ cssClass: 'my-custom-class', header: '認証されました', buttons: ['OK'] }); await alert.present(); } }
HTMLなどについては、GitHubに載せてますのでそちらから参照ください。
アプリケーションの動作確認
まずは、サインアップページで登録を行います。
すると、登録したメールアドレスにコードが送られてきますので、このコードを入力しメールアドレスの認証を行います。
その後、ログインページより登録したメールアドレスとパスワードでログインが可能となります。
コンソールでも登録したユーザが確認できます。
最後に
今回は、Ionicを用いてCognito認証を試してみましたが、 認証時にIDトークンも取得していますので、このIDトークンを利用してLambdaなどAWSリソースへアクセスも行ってみたいです。
参考
https://github.com/aws-amplify/amplify-js/tree/master/packages/amazon-cognito-identity-js
https://dev.classmethod.jp/articles/sign-up-and-sign-in-by-cognito-with-awscli/
https://d1.awsstatic.com/webinars/jp/pdf/services/20200630_AWS_BlackBelt_Amazon Cognito.pdf
https://shamique.medium.com/aws-cognito-service-in-ionic-b234f21c27ef