0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Amplify CLIで作ったGraphQL APIクエリするテンプレ + Authenticator コンポーネントのまとめ

Posted at

何をするか

Amplify CLIで以下を作成する。

  • Cognitoで認証されたユーザーだけがクエリを実行できるGraphQL API
  • React.jsのコード
    • Authenticatorコンポーネントによる認証
    • Cognitoで認証されてAPIへクエリする (認証とUIのテンプレなのでクエリ内容は固定、しかも結果もコンソールに表示するのみ)
    • 認証状態が変わるとボタンの表示非表示が変わる
    • material-ui入れる (今回のコードではボタンしか使っていないため、@aws-amplify/ui-reactだけでもいい)

Amplifyのドキュメントは必要情報自体はあるけれど、情報が散在しているためシンプルな構成をガガッと試したい時に結構時間かかる。今回一番苦労したのはAuthenticatorコンポーネントが何者なのかというところ(複数のバージョンがあり紛らわしい)。

ログイン前の画面
スクリーンショット 2022-01-23 22.30.19.png

ログイン後の画面
スクリーンショット 2022-01-23 22.30.00.png

CALLボタンは同じコンポーネントの表示位置を変えているだけだが、ログインするとAPIリクエストにユーザー情報が勝手に付与されるようになる。

環境とパッケージ

今回はこれがメモりたいために書いたようなもの。新たに作成しようとするとバージョンの問題なのかエラーが発生してしんどいので、動くバージョン群をメモしておく。

Amazon Linux 2
node -v -> v16.4.0
npm -v -> 7.18.1
amplify -v -> 7.6.5

package.json (のdependencies)
  "dependencies": {
    "@aws-amplify/ui-react": "^2.1.0",
    "@emotion/react": "^11.7.1",
    "@emotion/styled": "^11.6.0",
    "@material-ui/core": "^5.0.0-beta.5",
    "aws-amplify": "^4.3.11",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "5.0.0",
    "web-vitals": "^2.1.3"
  }

作成手順

こんな感じ。細かい手順は成り行きで。

npx create-react-app testapp
cd testapp
amplify init
amplify add api # Cognito選択
amplify push
touch src/APICall.js

コード

APICall.js
import React from "react";
import { Auth, API, graphqlOperation } from 'aws-amplify';
import { testQuery } from './graphql/queries'

import { Button } from '@material-ui/core'

const APICall = () => {
    const call = async () => {
        try{
            const userInfo = await Auth.currentAuthenticatedUser();
            console.log(userInfo);
        } catch (e) {
            console.log('not authorized dayo')
        }
        try{
            // 認証されていてもいなくてもリクエストは送る
            const res = await API.graphql(graphqlOperation(testQuery))
            console.log(res)
        } catch (e) {
            console.log(e);
        }
    }

    return(
        <>
        <Button variant="contained" onClick={call}>call button</Button>
        </>
    )
}

export default APICall;
App.js
import React, { useEffect, useState } from 'react';

import { Amplify, Auth, Hub } from 'aws-amplify';
import { Authenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';

import APICall from './APICall'

import awsExports from './aws-exports';
Amplify.configure(awsExports);

const App = () => {
  const [loginState, setLoginState] = useState(null);

  useEffect(() => {
    // ログイン状態を loginState にセット
    const authenticationStateCheck = async () => {
      try{
        const userInfo = await Auth.currentAuthenticatedUser();
        setLoginState(userInfo);
      }catch(e){
        setLoginState(null);
      }
    }
    // ページロード時にログイン状態をチェック
    authenticationStateCheck();

    // 認証状態変更時にログイン状態をチェック
    Hub.listen('auth', (data) => {
      authenticationStateCheck();
    })
  }, []);
 
  return (
    <>
    <Authenticator >
    {({ signOut, user }) => (
        <main>
          <h1>Hello {user.username}</h1>
          ログインしている時はここにボタンが現れる↓
          <br/>
          <APICall />
          <button onClick={signOut}>Sign out</button>
        </main>
      )}
    </Authenticator>
    ログインしてない時はここにボタンが現れる↓
    <br/>
    {loginState ? "no button" : <APICall />}
    </>
  );
}

export default App;
schema.graphql
## どんなものを投げてもLambdaが何かしら結果を返してくれるというようなおサボりをしている
type Query {
  testQuery (id: ID): String
  @function(name: "<Lambda関数名>-${env}")
  @auth(rules: [{allow: private, provider: userPools},])
}

困っていたこと (Authenticatorコンポーネントの使い方)

AuthenticatorにはLatestとLegacyの情報が散在しており紛らわしい。
例えば、このdocumentではAuthenticatorからonStateChangepropsとして子コンポーネントに渡せるというふうに書いてあったが、importしているのがaws-amplify-reactなのでこれはLegacy. @aws-amplify/ui-react v2.1.0のAuthenticator(document)では動かなかった。
後はAmplifyAuthenticatorというコンポーネントの存在も紛らわしく、AmplifyAuthenticator => Legacy, Authenticator => Latestと対応するものと思ってしまっていた。しかしレガシーとされているパッケージを見ると、reactだけでも二つ記載されていた。正しくは多分以下。

コンポーネント パッケージ 関連リンク Legacy or Latest
AmplifyAuthenticator @aws-amplify/ui-react@v1 Github Legacy
Authenticator aws-amplify-react Github Legacy
Authenticator @aws-amplify/ui-react@v2 documentGithub Latest

知ったこと

  • AuthenticatorのLegacyとLatestの見分け方。
  • 今はLatestで認証状態の変化を取得するにはHubを使うしかない?(そこまでしっかり調べてないです...)
  • API.graphql()でリクエストするとログイン状態に応じて認証情報を付与してくれる。GraphQL APIがIAM認証の場合は勝手に認証ロールor未認証ロールでのリクエストになってくれる。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?