NuxtJSと TypeScriptでAmplify認証ミドルウェアを作成!TypeScript環境のAmplify認証実装を解説します😎

NuxtJSと TypeScriptでAmplify認証ミドルウェアを作成!TypeScript環境のAmplify認証実装を解説します😎

こんにちは!

最近は AmplifySDK を使用して認証周りを実装するケースが増えてきました。 AmplifySDK を使用することで、従来の amazon-cognito-identity-jsSDK よりも、よりシンプル・エレガントに認証処理実装を実現できます。

本記事では、AmplifySDK と NuxtJS・TypeScript を使用した認証処理の実装を解説します! NextJS(ReactJS)でも応用できる内容となっておりますので、 Amplify による認証処理実装をされたい方には必見です!

想定する読者

  • Amplify を使用して認証処理を実装したいヒト
  • Amplify を VueJS・ReactJS で実装しているヒト

はじめに

認証基盤には Cognito を使用します

本記事は AmplifyCLI、または自前の Cloudformation などで構築されている Cognito を対象にした認証実装方法の紹介となります。

Amplify CLI は使用するべき?

結論、プロトタイピングや PoC 的な開発をされたい場合は AmplifySDK によるインフラ構築をぜひ採用してみてください!逆に、長期的に開発していくアプリケーション開発で AmplifyCLI を採用しインフラ構築を行うのは、制約に苦しめられる可能性が高いのでご注意ください。

私たちは、長期的にアプリケーションを開発・保守していくケースが多いため、通常 AmplifyCLI ではなく、Cloudformation を書いてインフラを構築することが多いです。

NuxtJS Amplify 認証ミドルウェアの実装解説

ディレクトリ構造

├── plugins
│   └── amplify.ts Amplifyの設定プラグイン(nuxt.config.jsで読み込み設定)
│
├──middleware
│   └── authenticated.ts 認証状態必須ミドルウェア
│   └── notAuthenticated.ts 非認証状態必須ミドルウェア
│
├──services
│   └── authService.ts 認証サービス

Amplify の設定プラグイン

Amplify の認証エンドポイント(Cognito)の設定を行います。nuxt.config.jspluginsに Amplify 設定用プラグインファイルを指定し、NuxtJS の Vue インスタンス生成前に読み込むようにします。尚、Amplify に設定する各種エンドポイントの設定値は、nuxt.config.jspublicRuntimeConfigから取得するようにします。(Nuxt2.13 以降ならプロジェクトルートディレクトリの.envpublicRuntimeConfigへバインドされます)

/nuxt.config.js

export default {
  ...
  publicRuntimeConfig: {
    REGION: process.env.REGION,
    COGNITO_USER_POOL_ID: process.env.COGNITO_USER_POOL_ID,
    COGNITO_USER_POOL_WEB_CLIENT_ID: process.env.COGNITO_USER_POOL_WEB_CLIENT_ID
  },
  plugins: [
    { src: '@/plugins/amplify.ts', mode: 'client' },
  ],
  ...
}

/.env

REGION={your_aws_region}
COGNITO_USER_POOL_ID={your_cognito_userpool_id}
COGNITO_USER_POOL_WEB_CLIENT_ID={your_cognito_client_id}

/plugins/amplify.ts

import Amplify from 'aws-amplify'
import { Plugin } from '@nuxt/types'

const myPlugin: Plugin = (context, inject) => {
  Amplify.configure({
    Auth: {
      region: context.nuxtState.config.REGION,
      userPoolId: context.nuxtState.config.COGNITO_USER_POOL_ID,
      userPoolWebClientId:
        context.nuxtState.config.COGNITO_USER_POOL_WEB_CLIENT_ID,
    }
  })
}

export default myPlugin

認証サービス

認証処理を扱うサービスファイルを作成します。本記事では触れませんが、サービス層には単体テストを実行し、動作を保証させておくことを推奨いたします。

import { Auth } from 'aws-amplify'

export const getUserId = async (): Promise<string> => {
  const user = await Auth.currentAuthenticatedUser()
  return user.attributes.sub
}

export const isAuthenticated = async (): Promise<boolean> => {
  return await new Promise((resolve, reject) => {
    Auth.currentAuthenticatedUser()
      .then(() => resolve(true))
      .catch(() => resolve(false))
  })
}

認証状態必須ミドルウェア

認証状態を要するページ(例えば会員マイページ)に設定するミドルウェアです。

import { Context, Middleware } from '@nuxt/types'
import { getUserId, isAuthenticated } from '~/services/authService'

const myMiddleware: Middleware = async (context: Context) => {
  const { store, redirect } = context
  const _isAuthenticated = await isAuthenticated()
  const promise: Promise<Function>[] = []
  // 非認証の場合はログインページへリダイレクト
  if (!_isAuthenticated) return redirect('/login')
  // 認証済みの場合はユーザー情報取得系のStoreをディスパッチ
  if (_isAuthenticated && store.getters['user/getUser'] === null)
    promise.push(
      store.dispatch('user/getUserById', {
        Id: await getUserId(),
      })
    )

  await Promise.all(promise)
}

export default myMiddleware

非認証状態必須ミドルウェア

ログインページをはじめとした、非認証状態時に表示させたくないページに設定するミドルウェアです。

import { Context, Middleware } from '@nuxt/types'
import { isAuthenticated } from '~/services/authService'

const myMiddleware: Middleware = async (context: Context) => {
  const { redirect } = context
  // 認証状態必須ミドルウェアでStoreの取得処理はされるのでここでは実行しない
  if (await isAuthenticated()) redirect('/home')
}

export default myMiddleware

まとめ

本記事では、NuxtJS&TypeScript でよく使用される認証系ミドルウェアの実装を紹介しましたが、ReactJS で実装しているケースでも、Amplify の処理部分などをきっと応用できるはずです!この機会に Amplify で一歩進んだ認証実装にチャレンジしてみてください。

TypeScript フロントエンド開発のご相談は、お気軽にお問い合わせください。