next-auth-saml - Next-Auth.jsを使用したNextJSSAML認証。

(NextJS SAML authentication with Next-Auth.js.)

Created at: 2021-04-06 15:53:35
Language: JavaScript

次へ-Auth.jsSAMLの例

DockerCompose DockerCompose

Next-Auth.jsを使用し、SAMLIdPで

saml2-js
認証するサンプルアプリケーション。

このサンプルに含まれるもの

リポジトリには、

kristophjunge/test-saml-idp
イメージを使用するモックIdPとともに、開発モードでNext.jsアプリを起動するDocker-Composeファイルが含まれています。

模擬IdPはhttp:// localhost:8080 / simplesamlで公開され、Next.jsアプリケーションはhttp:// localhost:3000で公開されます。

前提条件

設定

GitHubリポジトリのクローンを作成する

まず、このリポジトリをローカルマシンに複製します。

git clone https://github.com/Jenyus-Org/next-auth-saml.git

依存関係のインストール

次に、を使用

yarn
して依存関係をインストールします。

yarn

OpenSSLを使用した証明書の生成

サービスプロバイダーをセットアップするには、いくつかのSPキーを生成する必要があります。これは、OpenSSLを使用して行うことができます。

openssl req -x509 -newkey rsa:4096 -keyout certs\key.pem
-out certs\cert.pem -nodes -days 900

Dockerコンテナの実行

Docker-Composeのおかげで、1つのコマンドを使用してアプリ全体を起動できます。

docker-compose up --build

今すぐに頭// localhostを::HTTP 3000とのログインを試してみてくださいザ・SAML資格情報がある。

user1
user1pass

カスタマイズ

このショーケースの機能はかなりシンプルです。Next-Auth.jsは認証コールバックでCSRFトークンを必要とするため、SAML本体を認証エンドポイントに渡す前にSAMLアサーションをインターセプトする必要があります。私たちは

pages/api/auth/login/saml.js
ファイルでそうします:

export default async (req, res) => {
  if (req.method === "POST") {
    const { data, headers } = await axios.get("/api/auth/csrf", {
      baseURL: "http://localhost:3000",
    });
    const { csrfToken } = data;

    const encodedSAMLBody = encodeURIComponent(JSON.stringify(req.body));

    res.setHeader("set-cookie", headers["set-cookie"] ?? "");
    return res.send(
      `<html>
        <body>
          <form action="/api/auth/callback/saml" method="POST">
            <input type="hidden" name="csrfToken" value="${csrfToken}"/>
            <input type="hidden" name="samlBody" value="${encodedSAMLBody}"/>
          </form>
          <script>
            document.forms[0].submit();
          </script>
        </body>
      </html>`
    );
  }
};

これにより、ファイルが返されるとすぐに自分自身を

POST
送信し、
/api/auth/callback/:provider
ルートにリクエストを返すようにマップされるHTMLフォームが生成されます。ここでは、Next-Auth.js構成のプロバイダー
:provider
のIDと一致することが重要です
Credentials

注: Next-Auth.jsのREST APIについて詳しくは、こちらをご覧ください

サインインフローを開始するため

GET
に、同じAPIルートハンドラーでリクエストを受け入れ、コールバックURLを含むログインリクエストURLを生成します。

export default async (req, res) => {
  const createLoginRequestUrl = (identityProvider, options = {}) =>
    new Promise((resolve, reject) => {
      serviceProvider.create_login_request_url(
        identityProvider,
        options,
        (error, loginUrl) => {
          if (error) {
            reject(error);
          }
          resolve(loginUrl);
        }
      );
    });

  try {
    const loginUrl = await createLoginRequestUrl(identityProvider);
    return res.redirect(loginUrl);
  } catch (error) {
    console.error(error);
    return res.sendStatus(500);
  }
};

注:のために

saml2-js
コールバック・ベースであることは、我々は、使用
Promise
URLを生成した後、当社のルートハンドラにリダイレクトまたは500のステータスコードを返すように。

Next-Auth.js構成には

Credentials
、SAML本体を取得し
saml2-js
て解析に使用するカスタムプロバイダーを含め、ユーザーを返してセッションに追加します。

export default NextAuth({
  providers: [
    Providers.Credentials({
      id: "saml",
      name: "SAML",
      authorize: async ({ samlBody }) => {
        samlBody = JSON.parse(decodeURIComponent(samlBody));

        const postAssert = (identityProvider, samlBody) =>
          new Promise((resolve, reject) => {
            serviceProvider.post_assert(
              identityProvider,
              {
                request_body: samlBody,
              },
              (error, response) => {
                if (error) {
                  reject(error);
                }

                resolve(response);
              }
            );
          });

        try {
          const { user } = await postAssert(identityProvider, samlBody);
          return user;
        } catch (error) {
          console.error(error);
          return null;
        }
      },
    }),
  ],
  callbacks: {
    jwt: (token, user) => {
      if (user) {
        return {
          user,
        };
      }

      return token;
    },
    session: (session, { user }) => {
      return {
        ...session,
        user,
      };
    },
  },
});

注: Next-Auth.jsが提供するコールバック

jwt
session
コールバックについて詳しくは、こちらをご覧ください

さらに詳しい情報

動機

このサンプルは、Next-Auth.jsでのSAMLのサポートをテストおよび紹介するために作成されました。ご覧のとおり、

/api/auth/signin/:provider
ルートにはCSRFトークンが必要なため、手動でトークンを取得して自己送信を生成する必要があります
<form>
。このソリューションには、独自のNext-Auth.jsプロバイダーを持つOssoのようなサードパーティプロバイダーを使用する場合と比較して、独自のトレードオフがあります

貢献

このリポジトリは、フローを強化できるプルリクエストを受け付けています。つまり、複数のIdPのサポートを追加するか

POST
、HTMLの自己送信を介してCSRFトークンを追加せずにSAMLリクエストをサポートするためのより良い方法を見つけます
<form>