この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、森田です。
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