2023.09.28

AWS AmplifyとAmazon Cognitoを連携しユーザープールグループごとに異なる権限を与えよう

はじめに

アプリケーション開発において、ユーザーエクスペリエンスとデータセキュリティは不可欠な要素です。特に、利用するユーザープールごとにセキュアにアクセス制限をかける必要がある場合も多いでしょう。筆者自身もこの点がAWS Amplifyに関心を持ったきっかけになりました。今回の記事では、フロントエンド言語のVue.jsと、AWSのサービスであるAWS Amplify、AWS AppSync、GraphQL、そしてAmazon Cognitoを組み合わせ、ユーザープールごとにバックエンドから安全にアクセス制限をかける方法をデモ形式で説明します。

AWS Amplify とは

AWSが提供する包括的な開発プラットフォームで、ウェブやモバイルアプリケーションの構築を簡素化します。認証、API、ストレージ、アナリティクス、リアルタイム機能、ホスティング、CI/CDなど、様々な開発タスクに対するツールとサービスを提供し、バックエンドの複雑さに悩むことなく、優れたユーザーエクスペリエンスを重視でき、他のAWSサービスとシームレスに統合し、モダンなアプリケーションの迅速な開発、展開、管理を実現できます。

AWS Amplify、AWS AppSync、GraphQLとAmazon Cognitoの連携

AWS Amplify(以降、Amplify)はAmazon Cognito(以降、Cognito)と連携し、Cognitoユーザープールのセットアップをシンプルにし、ユーザー認証と認可を簡単に行えるようにサポートします。また、Cognitoの牢な認証とアクセス制御を提供するために、ユーザープールグループを利用することもできます。

AppSyncはGraphQLを利用してAPI開発をスムーズに行うことができます。GraphQLはREST APIの複数のエンドポイントを一つの柔軟なエンドポイントで置き換え、必要なデータだけを取得するアプローチを提供します。クライアントとサーバー間では、GraphQLのスキーマが定義され、ここでクライアントがバックエンドで行える操作の型が定義されます。このスキーマにCognitoに関連する属性を定義することで、データごとにアクセス権限を制御できます。

Amplify、AWS AppSync(以降、AppSync)、GraphQL、そしてCognitoの連携は、効率的な開発とデータ対話を融合させるものです。この統合により、開発者は、安全で効率的なモダンなアプリケーションを作ることができます。

構成と説明

試してみた構成は以下になります。
Vue.js + Amplifyで作ったFrontend クライアントアプリはAppSyncのGraphQL Resolverを利用し、Amazon DynamoDB(以降、DynamoDB)にあるデータをリクエストします。クエストの送信者やグループの権限に基づきCognitoで認証認可を行い、適切なレスポンスが返されます。

構成図

デモの実施

前提条件

以下1-3ステップが完了済みの前提です。

  • 1.
    Vue プロジェクトの作成(vue.js 3)
  • 2.
    必要な権限を持ったIAMクレデンシャルでAmplify環境を作成
  • 3.
    認証処理を追加(Emailで認証)

Cognitoユーザープールグループ作成

1. [amplify update auth]コマンドでmasterとcrew の2つのCognitoユーザープールグループを作成します。


amplify update auth
Please note that certain attributes may not be overwritten if you choose to use defaults settings.
Using service: Cognito, provided by: awscloudformation
 What do you want to do? Create or update Cognito user pool groups
#masterユーザープールグループの作成
? Provide a name for your user pool group: master
? Do you want to add another User Pool Group Yes
#crewユーザープールグループの作成
? Provide a name for your user pool group: crew
? Do you want to add another User Pool Group No
#ユーザープールグループの優先順を決める
√ Sort the user pool groups in order of preference · master, crew
✅ Successfully updated auth resource groupauthappe5886c81 locally

2. バックエンドに[amplify push]コマンドでプッシュをします。


amplify push
√ Successfully pulled backend environment dev from the cloud.

    Current Environment: dev
    
┌──────────┬──────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name        │ Operation │ Provider plugin   │
├──────────┼──────────────────────┼───────────┼───────────────────┤
│ Auth     │ userPoolGroups       │ Create    │ awscloudformation │
├──────────┼──────────────────────┼───────────┼───────────────────┤
│ Auth     │ groupauthappe5886c81 │ Update    │ awscloudformation │
└──────────┴──────────────────────┴───────────┴───────────────────┘
#userpoolはUpdateとuserPoolGroupsはCreate状態になっていることが分かります。
√ Are you sure you want to continue? (Y/n) · yes

Deployment completed.
Deployed root stack groupauthapp [ ======================================== ] 3/3
        amplify-groupauthapp-dev-1615... AWS::CloudFormation::Stack     UPDATE_COMPLETE                Thu Aug 24 2023 16:49:09...
        authgroupauthappe5886c81       AWS::CloudFormation::Stack     UPDATE_COMPLETE                Thu Aug 24 2023 16:48:19...
        authuserPoolGroups             AWS::CloudFormation::Stack     CREATE_COMPLETE                Thu Aug 24 2023 16:48:55...
Deployed auth groupauthappe5886c81 [ ======================================== ] 6/6
        IdentityPoolRoleMap            AWS::Cognito::IdentityPoolRol... UPDATE_IN_PROGRESS             Thu Aug 24 2023 16:48:13...
Deployed auth userPoolGroups [ ======================================== ] 4/4
        masterGroupRole                AWS::IAM::Role                 CREATE_COMPLETE                Thu Aug 24 2023 16:48:40...
        crewGroupRole                  AWS::IAM::Role                 CREATE_COMPLETE                Thu Aug 24 2023 16:48:41...
        masterGroup                    AWS::Cognito::UserPoolGroup    CREATE_COMPLETE                Thu Aug 24 2023 16:48:43...
        crewGroup                      AWS::Cognito::UserPoolGroup    CREATE_COMPLETE                Thu Aug 24 2023 16:48:43...

Deployment state saved successfully.

3. その後、Cognitoコンソールにて以下図のようにグループが作成されたことが確認できます。

GraphQL API作成

1. GraphQL API を作成します。[amplify add api] コマンドを実行し、認可タイプをAmazon Cognito User Poolにしてください。


amplify add api
? Select from one of the below mentioned services: GraphQL
? Here is the GraphQL API that we will create. Select a setting to edit or continue Authorization modes: API key (default, expiration time: 7 days from now)
? Choose the default authorization type for the API Amazon Cognito User Pool
Use a Cognito user pool configured as a part of this project.
? Configure additional auth types? No
? Here is the GraphQL API that we will create. Select a setting to edit or continue Continue
? Choose a schema template: Single object with fields (e.g., "Todo" with ID, name, description)

⚠️  WARNING: Some types do not have authorization rules configured. That means all create, read, update, and delete operations are denied on these types:
         - Todo
Learn more about "@auth" authorization rules here: https://docs.amplify.aws/cli/graphql/authorization-rules
✅ GraphQL schema compiled successfully.

2. 以下のSchemaファイルが作成されるので、中身を編集します。

/amplify/backend/api/groupauthapp/schema.graphql

ここでは「Task」というデータベースを作成します。
allow: groupsは、グループに入ったユーザーのみにデータアクセス許可を与える意味です。
masterグループに入ったユーザーは、CRUD(create、read、update、delete)すべてのリクエストができるようになり、crewグループに入ったユーザーに対しては、readだけをリクエストできます。


type Task @model @auth(
    rules: [
      { allow: groups,groups: ["master"],operations: [create, read, update, delete] },
      { allow: groups,groups: ["crew"],operations: [read] }
    ]
  ) {
  id: ID!
  taskName: String! 

3. バックエンドに[amplify push]コマンドでプッシュをします。


amplify push   
| Fetching updates to backend environment: dev from the cloud.✅ GraphQL schema compiled successfully.

Edit your schema at ***\group-auth-app\amplify\backend\api\groupauthapp\schema.graphql or place .graphql files in a directory at ***\group-auth-app\amplify\backend\api\groupauthapp\schema
√ Successfully pulled backend environment dev from the cloud.
/ Building resource api/groupauthapp✅ GraphQL schema compiled successfully.

Edit your schema at ***\group-auth-app\amplify\backend\api\groupauthapp\schema.graphql or place .graphql files in a directory at ***\group-auth-app\amplify\backend\api\groupauthapp\schema

    Current Environment: dev
    
┌──────────┬──────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name        │ Operation │ Provider plugin   │
├──────────┼──────────────────────┼───────────┼───────────────────┤
│ Api      │ groupauthapp         │ Create    │ awscloudformation │
├──────────┼──────────────────────┼───────────┼───────────────────┤
│ Auth     │ groupauthappe5886c81 │ No Change │ awscloudformation │
├──────────┼──────────────────────┼───────────┼───────────────────┤
│ Auth     │ userPoolGroups       │ No Change │ awscloudformation │
└──────────┴──────────────────────┴───────────┴───────────────────┘
#Api CategoryがCreate状態になっていることが分かります。
√ Are you sure you want to continue? (Y/n) · yes

⚠️  WARNING: Global Sandbox Mode has been enabled, which requires a valid API key. If
you'd like to disable, remove "input AMPLIFY { globalAuthRule: AuthRule = { allow: public } }"
from your GraphQL schema and run 'amplify push' again. If you'd like to proceed with
sandbox mode disabled, do not create an API Key.

√ Would you like to create an API Key? (y/N) · no
✅ GraphQL schema compiled successfully.

Edit your schema at ***\group-auth-app\amplify\backend\api\groupauthapp\schema.graphql or place .graphql files in a directory at ***\group-auth-app\amplify\backend\api\groupauthapp\schema
/ Building resource api/groupauthapp✅ GraphQL schema compiled successfully.

Edit your schema at ***\group-auth-app\amplify\backend\api\groupauthapp\schema.graphql or place .graphql files in a directory at ***\group-auth-app\amplify\backend\api\groupauthapp\schema
? Do you want to generate code for your newly created GraphQL API Yes
? Choose the code generation language target javascript
? Enter the file name pattern of graphql queries, mutations and subscriptions src\graphql\**\*.js
? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes
? Enter maximum statement depth [increase from default if your schema is deeply nested] 2

Deployment completed. 


ここまでの作業で、CLIでのリソース作成が完了しました。次にフロントエンドのソースコードを編集します。

ソースコード

/public/index.html


<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

/src/main.js


import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";

import "@aws-amplify/ui-vue/styles.css";
import Amplify from '@aws-amplify/core';
import awsconfig from "./aws-exports";
// 日本語のimport
import { I18n } from 'aws-amplify';
import { translations } from '@aws-amplify/ui-vue';
I18n.putVocabularies(translations);
I18n.setLanguage('ja');

Amplify.configure(awsconfig);

const app = createApp(App);

/src/App.vue







/views/HomeView.vue






動作確認

1. masterグループをテストします。

まずは、[npm run serve]コマンドでアプリを起動し、ユーザーアカウントを作成します。

  • 新規作成されたユーザーはまだユーザーグループに所属していないため、Webアプリにアクセスできず、以下のエラーが出ます。

その場合、右上の×マークをクリックしてエラー表示を閉じ、サインアウトをしてから次のステップに進んでください。

2. 次に、Cognitoコンソールにて、作成したユーザーをmasterグループに追加します。

アプリの画面に戻り、再度ログインして、タスクの作成や削除を試してみてください。
すると、問題なく操作ができることがわかります。

「データを入力し、作成または削除を試してみます。」

3. crewグループをテストします。

Cognitoコンソールにて、ユーザーをmasterグループから削除し、crewグループに追加します。

アプリの画面に戻し、再度ログインして、タスクの作成や削除を試してみてください。
すると、一覧だけを見ることができ、作成や削除処理は許可されていない為、Unauthorizedエラーが発生し、処理が失敗します。

データを入力し、作成または削除をしてみると、以下図のように、何も反応がないことが分かります。

開発ツールのコンソールにて、Unauthorizedエラーの確認ができます。

まとめ

Amplifyを使用して、Cognitoユーザープールグループごとにアクセス権限を制御できるVue.jsアプリを作成しました。異なるアクセス権限を持つグループごとにユーザーを追加しながら、動作確認を行いました。このような認証認可処理を、Amplifyを用いて簡単に実装でき、開発がスムーズに行えることが分かりました。

動作確認に関しては、今回はWebアプリ画面を操作してご紹介しましたが、フロントエンドのコードに手を加えることなく、API確認のみを行いたい場合は、AppSyncのクエリエディタを使用して確認することもできます。

最後に、本記事で記載した手順や内容はデモ用のものであるため、ご参考程度に留めておいてください。簡単なご紹介となりましたが、Amplifyやサーバレス開発にご興味のある方はぜひ当社までご相談 新規ウィンドウで開くください。

参考文献

Amplify Setup authorization rules 新規ウィンドウで開く

作者プロフィール

名前 AUNG
担当のAWS業務 営業支援、ソリューションアーキテクト
AWSの持っている資格 AWS Certified Developer - Associate
AWS Certified Solutions Architect - Associate
AWS Certified DevOps Engineer - Professional
AWS Certified Solutions Architect - Professional
AWS Certified Data Analytics - Specialty
AWS Certified Security - Specialty
AWS Certified Advanced Networking - Specialty
好きなAWSのサービス Amplify、CloudFormation
趣味 筋トレ
ひとこと 健康は大事

(寄稿:THU YEIN AUNG / 監修:高谷 英雄)

関連サービス

導入のお問い合わせはこちら

AWSやAmazon WorkSpacesの導入から接続回線、運用・保守まで何でもお任せください。

お問い合わせ

TOPへ戻る