【NextAuth.js】cognitoで複数のサードパーティのIDプロバイダーを使った時に直接ソーシャルログインの画面に遷移する
はじめに
cognitoで複数のサードパーティのIDプロバイダーを利用している状態で、
NextAuth.jsのCognitoProvider
を使ってsignIn
関数を以下のように実行すると、
cognitoが用意しているログイン画面に遷移してしまいます。
import { signIn } from "next-auth/react";
(...省略)
<Button
onClick={() => signIn("cognito")}
>
Google
</Button>
cognitoが用意しているログイン画面
普通のアプリケーションでは、このcognitoの画面が見えるとよくないのでサードパーティのログイン画面に直接遷移する方法を紹介します。
解決方法(1)
前提: Cognitoの単一のアプリケーションクライアントに、複数のサードパーティのIDプロバイダーを登録している場合。
以下のように、signIn
の第三引数に以下のように設定すればいけます。
import { signIn } from "next-auth/react";
(...省略)
<Button
onClick={() => signIn("cognito", {}, { identity_provider: "Google" })}
>
Google
</Button>
ここで"Google"
のところに指定する値は、Cognitoのサインインエクスペリエンス項目にある
アイデンティティプロバイダーの名前を指定すればOKです。
cognitoのコンソール画面(サインインエクスペリエンス項目)
解決方法(2)
前提: Cognitoの単一のアプリケーションクライアントに、単一のサードパーティのIDプロバイダーを登録して、複数のアプリケーションクライアントを運用している場合。
以下のように[...nextauth].ts
ファイルに複数のCognitoProvider
を登録し、
引数のid
の部分がそれぞれユニークになるように設定します。
import CognitoProvider from "next-auth/providers/cognito";
const defaultCognitoProvider = CognitoProvider({
id: "cognito",
clientId: process.env.COGNITO_CLIENT_ID,
clientSecret: process.env.COGNITO_CLIENT_SECRET,
issuer: process.env.COGNITO_ISSUER,
checks: "nonce",
});
const googleCcognitoProvider = CognitoProvider({
id: "cognito-google",
clientId: process.env.COGNITO_GOOGLE_CLIENT_ID,
clientSecret: process.env.COGNITO_GOOGLE_CLIENT_SECRET,
issuer: process.env.COGNITO_ISSUER,
checks: "nonce",
});
その上で、signIn
関数の引数に上で設定したid
を指定すると対応するクライアントが実行されます。
import { signIn } from "next-auth/react";
(...省略)
<Button
onClick={() => signIn("cognito")}
>
default
</Button>
(...中略)
<Button
onClick={() => signIn("cognito-google")}
>
default
</Button>
(1)と(2)とでおすすめの方法
どちらでも同じことが実現できるのですが、おすすめなのは(1)の方法です。理由は、アプリケーションクライアントが1つになるためです。
本題とは関係ないですが、アクセストークンの更新やサインアウトを実装することも考えると(1)の方がおすすめです。それぞれ以下の記事が参考になります。
- アクセストークンの更新
- サインアウトの挙動
加えてIDトークンの検証をする時にも同じアプリケーションクライアントである必要があります。そういった点からも(1)の方法がおすすめです。
おわりに
複数のアプリケーションクライアントを指定した時の
CognitoProvider周りのドキュメントが存在せず(調べた限りですが…)結構苦労しました。
最初は(2)の方法でアプリケーションを作成していたのですが、調べて行くうちに
(1)の方法で作成した方が構成やプログラムもシンプルでいいなと思い採用しました。
誰かのお役に立てれば幸いです。
結局うまくいかなかったけれど試したこと
cognitoのClientへのURLを直接実行する。
以下のようなURLをボタンに設定して遷移するなど試したのですが、NextAuth側のトークンをうまく取得できないため断念しました(あまりガッツリ試していないので、URLの設定とかが間違っているかもです…)。
const googleLoginUrl = `${process.env.NEXT_PUBLIC_COGNITO_ENDPOINT}/oauth2/authorize?identity_provider=Google&redirect_uri=${host}/api/auth/callback/cognito&response_type=CODE&client_id=${clientId}&scope=${scope}`;
Discussion