Fusic Tech Blog

Fusicエンジニアによる技術ブログ

React + AppSyncの認証をCognitoに任せる
2024/03/29

React + AppSyncの認証をCognitoに任せる

どうも、こんにちは。Fusicの小原です。
Fusicには複数チームが存在しており、自分が所属しているチームでは毎朝その日の体調と仕事(コンディションと呼んでる)を共有しています。その共有するシステムをReactで作りバックグランドではAWSのサービスを使っています。勉強っという意味で作ったのでまだ修正する箇所はありますが、今までやった技術的なことを書いていこうと思います。

AWS構成

フロントはReactでS3の静的ホスティングで運用しています。
ユーザの認証はCognito(今回のメイン)を利用しています。
コンディション情報はDynamoDBに保存し、インターフェイスはAppSyncというGraphQLのインターフェイスで実装しています。
CDの仕組みも作り、CodePipelineとCodeBuildを使ってデプロイさせています。
インフラ構成としては以下のようになっています。

Cognitoで認証する

では実際にReact + Cognitoを使ってどうやって認証を行ったかを見て行きたいと思います。
フロント側のライブラリはAmplifyを使いました。Amplifyはアプリケーションの解析や認証、APIなどを提供してくれる強力なライブラリです。これを使ってCognitoで認証を行って行きます。

インフラ側の準備

CognitoでユーザープールとIDプールの作成

まずはCognitoでUser Poolを作ります。

「デフォルトを確認する」でとりあえず作ります。設定は後ででも編集することができるのでこれでいいかと。
次はアプリクライアントを作成します。

そうするとアプリクライアントIDが発行されます。このアプリクライアントIDとユーザープールIDを利用してCognitoで認証を行います。

次に、ID プールを作成します。

ここで認証プロバイダーをCognitoにし先ほど作成した、ユーザープールIDとアプリクライアントIDを入力します。

あとはIAM Roleの追加画面になるので、既存のIAMロールにするか新規でIAMロールを作るか選択できます。
ここは新規追加で問題ないでしょう。

これでIDプールのIDが取得できました。
ユーザープールID、アプリクライアントID、IDプールIDこれらを使ってCognitoでの認証を行わせます。
とりあえず、使いやすいように一つのファイルにまとめておきます。

export default {
  Auth: {
    IdentityPoolId: process.env.REACT_APP_AWS_IDENTITY_POOL_ID ? process.env.REACT_APP_AWS_IDENTITY_POOL_ID : '',
    region: process.env.REACT_APP_REGIN ? process.env.REACT_APP_REGIN : 'ap-northeast-1',
    userPoolId: process.env.REACT_APP_AWS_USER_POOL_ID ? process.env.REACT_APP_AWS_USER_POOL_ID : '',
    userPoolWebClientId: process.env.REACT_APP_AWS_USER_POOL_WEB_CLIENT_ID ? process.env.REACT_APP_AWS_USER_POOL_WEB_CLIENT_ID : '',
  }
};

(これを、aws-cognito.jsファイルとして保存しておきます。)
環境変数にこれらの値を入れています。あとCognitoのリージョンを指定する必要があります(今回はap-northeast-1で作っています)

Amplify

Cognitoの情報をAmplifyに読み込ませる

では、上記で作った設定をAmplifyに読み込ませます。

・・・
 import cognito from './aws-cognito';
 ・・・
 
 import Amplify, { Auth } from 'aws-amplify';
 
 Amplify.configure(cognito);

これでAmplifyの認証情報として設定することができました。

Amplifyの認証のコンポーネント

次にAmplifyの認証を使うコンポーネントを指定します。
withAuthenticator関数の第一引数にAmplifyの認証範囲のコンポーネントをセットします。
第三引数にAmplifyでそれぞれデフォルトで提供されてるサインイン画面、サインアップ画面、パスワード再発行画面(パスワードを忘れた時)などをセットします。今回はサインイン画面は自分で独自でカスタマイズした画面になるようにしてます(SingContainer)。

import React, { Component } from 'react';
import SignInContainer from '../containers/signInContainer.jsx';
 
import {
  withAuthenticator,
  ConfirmSignIn,
  ConfirmSignUp,
  ForgotPassword,
  SignUp,
  VerifyContact
} from 'aws-amplify-react';
 
・・・
 
class MainContainer extends Component {
  render() {
    return (
      <Router>
        <Switch>
          ・・・
        </Switch>
      </Router>
    );
  }
}
 
export default withAuthenticator(MainContainer, false, [
  <SignInContainer />,
  <ConfirmSignIn />,
  <VerifyContact />,
  <SignUp />,
  <ConfirmSignUp />,
  <ForgotPassword />,
]);

AppSync

次はAppSyncの作成を行って行きます。AppSyncを利用する時にいくつか認証タイプがあります。もちろん認証にCognitoもサポートしています。

AppSyncの作成

では、早速AppSyncの作成を行って行きたいと思います。
まずは、コンソールからAppSyncの画面へ行き「Create API」から作成画面へ行きます。

ここでは無駄なものを省くため、「Build from scratch」で作ります。
次の画面でAPIの名前を入力する画面があるので、API名を入力し「Create」を押すことで作成完了です。

認証方式を設定

AppSyncで使う認証タイプを設定します。

認証タイプを「Amazon Cognito User Pool」に設定し、先ほどCognitoのユーザープールを作ったリージョンを指定。
ユーザープールを選択し、Default actionをALLOWで作成しておきます。

設定ファイルのダウンロード

次に設定ファイルをダウンロードします。

「Download Config」ボタンですぐに設定ファイルがダウンロードできます。
中身はこんな感じです。

const awsmobile = {
 "aws_appsync_graphqlEndpoint": "https://xxxxxxxxxxxxxxxx.appsync-api.ap-northeast-1.amazonaws.com/graphq",
 "aws_appsync_region": "ap-northeast-1",
 "aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS",
 "aws_appsync_apiKey": "null",
 };
 
 export default awsmobile;

これをAppSyncのクライアントに読み込ませれば、一通り完了になります。

import awsmobile from './app-exports';
import { ApolloProvider } from 'react-apollo';
import AWSAppSyncClient from 'aws-appsync';
import cognito from './aws-cognito';

import Amplify, { Auth } from 'aws-amplify';

Amplify.configure(cognito);

const client = new AWSAppSyncClient({
  disableOffline: true,
  url : awsmobile.aws_appsync_graphqlEndpoint,
  region: awsmobile.aws_appsync_region,
  auth: {
    type: awsmobile.aws_appsync_authenticationTypes,
    jwtToken: async () => (await Auth.currentSession()
      .then(data => {
        return data
  })
  .catch(err => {
    return err
    })).getIdToken().getJwtToken(), },
});

まとめ

以上でReact + AppSyncの認証をCognitoで行うことができます。
Amplify自体が強力で色々と機能があるのでAWSを使ってアプリケーションを作るなら利用できる場面が多いんではないでしょうか。
AppSyncのバックグランド側はDynamoDBなので、そこの利用方法についても今後載せていきたいと思います。

kobaru

kobaru

インフラ好きっ子