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

AWS AmplifyとAWS×フロントエンド #AWSAmplifyJPAdvent Calendar 2024

Day 14

【AWS Amplify】Next.js Middleware で Cognito グループの認可処理を行う

Last updated at Posted at 2024-12-23

はじめに

こんにちは、梅雨です。

今回は、Next.js Middleware で Cognito ユーザの所属するグループによって認可処理を行う方法について解説していこうと思います。

AWS Amplify とは?

AWS Amplify は、フロントエンドとクラウドバックエンドを効率に構築・デプロイするためのフレームワークです。

Amplify を使うことで、認証、DB、API などのバックエンド機能を簡単にセットアップでき、フロントエンドとシームレスに統合することができます。

認証機能に関しては、Amazon Cognito と統合することでユーザのサインインやサインアップを短時間で実装できます。

実装

早速実装に移っていきましょう。

ランナーの準備

まずは createServerRunner 関数でサーバランナーを用意します。

この関数は @aws-amplify/adapter-nextjs パッケージから提供されています。

npm i @aws-amplify/adapter-nextjs
import config from "src/aws-exports";
import { createServerRunner } from "@aws-amplify/adapter-nextjs";

const { runWithAmplifyServerContext } = createServerRunner({
  config,
});

通常の認証

続いて、Cognito ユーザの通常の認証を行なっていきます。

さきほど作成したランナー内で fetchAuthSession 関数を用いてユーザセッションを取得し、セッションが存在しないまたはセッショントークンが存在しないときは強制的に /login に飛ばすようにしています。

src/middleware.ts
const middleware = async (request: NextRequest) => {
  const authenticated = await runWithAmplifyServerContext({
    nextServerContext: { cookies },
    operation: async (contextSpec) => {
      try {
        const authSession = await fetchAuthSession(contextSpec, {});
        return authSession.tokens !== undefined;
      } catch (error) {
        console.log(error);
        return false;
      }
    },
  });

  if (authenticated) {
    if (request.nextUrl.pathname !== "/login") return;
    request.nextUrl.pathname = "/";
    return NextResponse.redirect(request.nextUrl);
  } else {
    if (request.nextUrl.pathname === "/login") return;
    request.nextUrl.pathname = "/login";
    return NextResponse.redirect(request.nextUrl);
  }
};

export default middleware;

Cognito グループによる認可処理

最後に、本題となるCognito グループによる認可処理を記述していきます。

先ほど取得したユーザセッションには Amplify によって検証が行われた JWT 形式のアクセストークンが含まれています。

JWT のペイロードは cognito:groups という名前で認証ユーザの所属するグループを所持しています。このグループはグループ名の配列形式をとります。

["admin", "maintainer"]
const authSession = await fetchAuthSession(contextSpec, {});
+ const groups = authSession.tokens?.accessToken.payload[
+     "cognito:groups"
+ ] as string[] | undefined;

続いて、この配列を用いて認可を行います。

今回の例では、admin グループと maintainer グループに所属するユーザのみがアクセスできるようにします。

const authSession = await fetchAuthSession(contextSpec, {});
const groups = authSession.tokens?.accessToken.payload[
    "cognito:groups"
] as string[] | undefined;
+ return !!(groups?.includes("admin") || groups?.includes("maintainer"));

これによって、groups?.includes("admin")groups?.includes("maintainer")) が両方とも false (または undefined)のとき、全体として false を返すようになりました。

最終的なコード

最終的なコードは以下のようになっています。

src/middleware.ts
const middleware = async (request: NextRequest) => {
  const authenticated = await runWithAmplifyServerContext({
    nextServerContext: { cookies },
    operation: async (contextSpec) => {
      try {
        const authSession = await fetchAuthSession(contextSpec, {});
        const groups = authSession.tokens?.accessToken.payload[
          "cognito:groups"
        ] as string[] | undefined;
        return !!(groups?.includes("admin") || groups?.includes("maintainer"));
      } catch (error) {
        console.log(error);
        return false;
      }
    },
  });

  if (authenticated) {
    if (request.nextUrl.pathname !== "/login") return;
    request.nextUrl.pathname = "/";
    return NextResponse.redirect(request.nextUrl);
  } else {
    if (request.nextUrl.pathname === "/login") return;
    request.nextUrl.pathname = "/login";
    return NextResponse.redirect(request.nextUrl);
  }
};

export default middleware;

おわりに

今回の記事では、Next.js の Middleware で Cognito グループによる認可処理を行う方法について解説しました。

Amplify では現状複数の Cognito プールと接続することはできないため、異なる属性を持つユーザを扱うためにはグループによる制御が欠かせません。

Next.js でグループによる認可制御を行う際は是非参考にしてみてください。

最後までお読みいただきありがとうございました。

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