LoginSignup
0
1

More than 1 year has passed since last update.

AWS AmplifyUI+Vueでユーザー認証してみる(後編)。

Posted at

前説

AWS AmplifyUI+Vueでユーザー認証してみる(前編)。の続き記事になります。
前編では、Amplifyのプロジェクトを新規作成し、ユーザー認証のUIコンポーネントを追加してみる所まで行いました。
今回の記事では、その情報を参考に、既存のVueプロジェクトにユーザー認証用のAmplifyUIコンポーネントを適用する所まで行います。

AmplifyUIコンポーネント導入に必要な内容確認

まず、前編の記事で、AmplifyUIを追加した事で発生した変化を確認します。

増えたファイルは以下の2つです。こちらはAmplifyプロジェクトとしての情報を保持している様です。

  • amplify/backend/auth/myamplifyproject*********/cli-inputs.json
  • amplify/backend/backend-config.json

認証関係の情報が追加されたのは以下のファイルです。

  • amplify/backend/types/amplify-dependent-resources-ref.d.ts
  • amplify/team-provider-info.json

App.vueに以下の部分が追加されました。

<script setup>
  import { Authenticator } from '@aws-amplify/ui-vue';
  import '@aws-amplify/ui-vue/styles.css';
</script>

既存プロジェクトはAmplifyのプロジェクトではないので、4ファイルに関してはそのまま追加は出来なさそうです。情報としては認証に使われるcognitoのIDなどが記載されています。まとめると以下の対応になりそうです。

  • モジュールのインポート
  • 認証用に使われるcognitoの情報設定

これらのキーワードで検索していると、オフィシャルのページにそのままの情報がありました。

実対応

実際に適用していきます。

Vue3へ移行

上記ページには下記メッセージがあります。Vue2ではGoogleアカウントなどのソーシャルログインとの連携があまり考慮されてない過去のコンポーネントしか使えなさそうです。
image.png
これはこれで大きな話題ですが、今回の件と本質的には関係無いのでまたの機会にします。
簡単に言うと、Vue3の新規プロジェクトを作成し、使っていたrouterやelement-uiなどモジュールをVue3用に替え、既存ソースを順次移植する方法を採用しています。記事を書いている時点では、初期表示するページだけ移行している状況です。

モジュールのインポート

公式ページ通りです。

yarn add @aws-amplify/ui-vue aws-amplify

認証用に使われるcognitoの情報設定

Login部分に使用するVueファイルでは以下の記載が必要です。ここが設定する部分です。

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

前編の記事ではaws-exports.jsというファイルがあり、それはAmplifyが自動的に更新する設定ファイルという事が解っています。それをもとに、Amplify.configureを実行して情報をセットする必要があります。

公式ページや、それを実際に使用している記事がありました。実際に使用されている記事からすると、公式ページのScoped configurationを行っておけば大丈夫そうです。前編の記事で生成されていたのはTop level configurationの様です。

今回使用したパラメーター
export default {
  Auth: {
    // (required) only for Federated Authentication - Amazon Cognito Identity Pool ID
    identityPoolId: 'XX-XXXX-X:XXXXXXXX-XXXX-1234-abcd-1234567890ab',

    // (required)- Amazon Cognito Region
    region: 'XX-XXXX-X',

    // (optional) - Amazon Cognito User Pool ID
    userPoolId: 'XX-XXXX-X_abcd1234',

    // (optional) - Amazon Cognito Web Client ID (26-char alphanumeric string, App client secret needs to be disabled)
    userPoolWebClientId: 'a1b2c3d4e5f6g7h8i9j0k1l2m3',
  }
} 

実際のアプリで使用

CognitoとAmplifyUIの導入が済んだ状態です。実際にアプリで使用していきます。大きく分けて2種類の仕様部分があります。

  • ログイン処理
  • トークンを使ってAPIアクセス

基本情報の取得

実際には、ログイン後に各コンポーネントでログイン情報を使用する必要があります。基本情報は公式ページにありました。

まず、useAuthenticatorを使ってauthオブジェクトを生成しています。

公式ページ引用
import { Authenticator, useAuthenticator } from '@aws-amplify/ui-vue';
const auth = useAuthenticator();

その後、auth.userでユーザー情報を参照したり、auth.routeでログイン状況を取得できます。

公式ページ引用
  <template v-if="auth.route === 'authenticated'">
    <h1>Hello {{ auth.user?.username }}!</h1>
    <button @click="auth.signOut">Sign out</button>
  </template>

ログイン処理

サンプルを真似て、ログイン成功まではログイン画面のみを表示し、成功したらrouterを表示する形にします。

App.vue
<template>
  <authenticator>
    <template v-slot="{ signOut }">
      <button @click="signOut">Sign Out</button>
    </template>
  </authenticator>
  <div id="app">
    <div v-if="auth.route === 'authenticated'">
      <router-view/>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { Authenticator, useAuthenticator } from "@aws-amplify/ui-vue";
import { Amplify } from 'aws-amplify';
import "@aws-amplify/ui-vue/styles.css";
import awsconfig from '@/aws-exports';
Amplify.configure(awsconfig);

export default defineComponent({
  setup() {
    const auth = ref(useAuthenticator());
    return {
      auth
    }
  },
  components: {
    Authenticator
  },
});
</script>

トークンを使ってAPIアクセス

今回AmplifyUI導入のアプリでは、APIアクセスで、APIGatewayでCognitoオーサライザーを使用しています。IDトークン内のjwtトークンをHeaderで渡す必要があります。

ログイン情報の取得

ユーザー情報はCognitoUserAmplifyクラスで取得出来そうです。

元ソースを見るとCognitoUserの継承オブジェクトの様です。amazon-cognito-identity-jsからimportされています。

必要なプロパティは上記amazon-cognito-identity-jsがあるリポジトリを探せばよさそうです。サンプルで使っているusernameもあります。

トークンの取得

APIアクセスの時に、ヘッダーにjwtトークンを埋める必要があります。今までは、session.getIdToken().getJwtToken()という関数を使っていました。

前述のCognitoUser.jsのリポジトリを見ると、getSessionにcallback関数をセットする様です。
そして、そのcallbackは最終的に(error,session)というパラメーターが渡されるようです。
そこからは同様にgetIdToken().getJwtToken()を使えそうです。この部分でthis.signInUserSessionを使っていますが、リフレッシュ処理などを考慮したsessionをgetSession関数で取得するべきかと思います。

今回は、以下の様なモジュールを作成しました。

api.ts
import axios from 'axios';
import { BalanceView } from '@/common/interfaces';
import masterdata from '@/const/masterdata';
import { useAuthenticator } from '@aws-amplify/ui-vue';
const API_BASE_URL = (process.env.VUE_APP_API_BASE_URL as string);

export default class ApiCalls {
  // 共通して使用する関数
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  callGetApi = async (url: string, config: {[key:string]: any}, callback: any): Promise<any> => {
    const auth = useAuthenticator();
    auth.user.getSession(async (error: Error, session: CognitoUserSession) => {
      if (error != null) {
        throw error;
      }
      const addHeaders = {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${session.getIdToken().getJwtToken()}`
      };
      const newHeaders = config['headers'] ? {
        ...config['headers'],
        ...addHeaders
      } : addHeaders;
  
      const newConfig = {
        ...config,
        'headers': newHeaders
      }
      const response = await axios.get(url, newConfig);
      return callback(response);
    });
  };

  // ビジネスロジック用関数での使用例
  getBalanceList = async (tgtDate: string): Promise<BalanceView[]> => {
    return new Promise(resolve => {
      const url = `${API_BASE_URL}/balance?tgt_date=${tgtDate}`;
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      this.callGetApi(url, { data: {}}, (response: any) => {
        const wkBalanceList: BalanceView[] = [];
        for (const resdata of response.data) {
          const wkBalance: BalanceView = {
            method_nm: masterdata.getMethodNm(resdata['method_cd']),
            value_fmt: Number(resdata['value']).toLocaleString()
          }
          wkBalanceList.push(wkBalance);
        }
        resolve(wkBalanceList);
      });
    });
  };
}

使用する側は以下の様な感じです。

const api = new ApiCalls();
// 中略
const balanceList = await api.getBalanceList(tgtToDateStr);

感想

通常、ログイン画面だけなら結構シンプルですが、ユーザー登録、パスワード変更画面など思いのほか実装が必要な画面があります。そこをパッケージングしてくれるこのAmplifyUIはすごく便利だと思いました。

今回はそのAmplifyUIをAmplifyプロジェクトでない通常のVueプロジェクトで使用してみました。Cognitoオーサライザーに対応しているAPIアクセスも出来ました。

Vue3への移行途中です。今回で技術的課題が無くなりました。これで安心して残りのVue3移行を進める事が出来ます。

0
1
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
1