📘
NextAuth.jsを使ってDrupalのOAuthを利用する
概要
NextAuth.jsを使ってDrupalのOAuthを利用する方法に関する備忘録です。
挙動
Next.jsで作成したアプリにアクセスして、「Sign in」ボタンを押します。
Drupalにログインしていない場合には、ログイン画面に遷移します。
ログイン済みの場合、「許可」するかのボタンが表示されるので、許可します。
ログイン情報が表示されます。
Drupal側の準備
モジュールのインストール
以下のモジュールをインストールします。
本記事執筆時点の最新の以下をインストールしました。
composer require 'drupal/simple_oauth:^6.0@beta'
トークンを暗号化するための鍵の生成
鍵のペアを生成し、セキュリティのためにドキュメントルートの外に保存します。
openssl genrsa -out private.key 2048
openssl rsa -in private.key -pubout > public.key
鍵のパスを設定
鍵のパスを管理画面で設定します:
/admin/config/people/simple_oauth
Amazon LightsailでDrupalを動作させている場合、以下のように、ユーザを変更する必要がありました。
sudo chown daemon:daemon private.key
Clients
/admin/config/services/consumer
にアクセスします。
default_consumer
がすでに作成されているため、こちらを編集します。
-
New Secret
に値を入力します。 -
Grant types
でAuthorization Code
を選択します。 -
Redirect URIs
に以下を入力します。 -
Access token expiration time
に値を入力します。
Postmanでの動作確認
以下のように入力します。Drupalがhttps://drupal.example.org
にセットアップされていると過程します。
- 認可 URL: https://drupal.example.org/oauth/authorize
- アクセストークン URL: https://drupal.example.org/oauth/token
- クライアント ID: Drupalで設定した値
- クライアントシークレット: Drupalで設定した値
「新しいアクセストークンを取得」を押すと、冒頭の挙動で示した通り、Drupalの画面に遷移し、許可したのち、以下に遷移しました。
https://oauth.pstmn.io/v1/callback?code=...
Next.jsからの利用
ソースコードを以下でご確認いただけます。
完全の余地があるかと思いますが、以下のような設定により、動作確認ができました。
/src/app/api/auth/[...nextauth]/authOptions.js
export const authOptions = {
// debug: true, // next-auth のデバッグモードを有効化
providers: [
{
id: "drupal",
name: "Drupal",
type: "oauth",
clientId: process.env.DRUPAL_CLIENT_ID,
clientSecret: process.env.DRUPAL_CLIENT_SECRET,
authorization: {
url: process.env.DRUPAL_AUTH_URL,
params: {
scope: process.env.DRUPAL_SCOPE,
response_type: "code",
redirect_uri: `${process.env.NEXTAUTH_URL}/api/auth/callback/drupal`, // 環境変数からリダイレクトURIを構築
},
},
token: {
async request(context) {
const body = new URLSearchParams({
client_id: process.env.DRUPAL_CLIENT_ID, // 明示的に client_id を追加
client_secret: process.env.DRUPAL_CLIENT_SECRET,
code: context.params.code, // 認可コード
grant_type: "authorization_code",
redirect_uri: `${process.env.NEXTAUTH_URL}/api/auth/callback/drupal`,
});
const res = await fetch(process.env.DRUPAL_TOKEN_URL, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body,
});
const json = await res.json(); // Parse the response body once
if (!res.ok) {
throw new Error(`Token request failed: ${res.statusText}`);
}
return {
tokens: json
}
}
},
profile(profile) {
return {
id: profile.sub, // "sub" をユーザーの一意のIDとして利用
name: profile.name || profile.preferred_username || "Unknown User", // 名前の優先順位を設定
email: profile.email || "No Email Provided", // メールがない場合のフォールバック
image: profile.profile || null, // プロファイルURLを画像として使用(必要に応じて調整)
}
},
},
],
callbacks: {
async session({ session, token }) {
// トークンからセッションに必要な情報を追加
session.accessToken = token.accessToken;
session.user.id = token.id;
return session;
},
async jwt({ token, account, user }) {
if (account) {
token.accessToken = account.access_token;
}
if (user) {
token.id = user.id; // プロファイルからユーザーIDをトークンに保存
}
return token;
},
},
};
まとめ
DrupalのOAuthの利用にあたり、参考になりましたら幸いです。
Discussion