Auth0でDiscordログインの実装+特定サーバーでロールを持っている時だけ認証が通るようにする設定
Auth0でDiscordのソーシャルログインを使って、特定のサーバーで特定のロールを持っている人だけ認証が通るようにする方法。
先人の人が実装していた方法は、今のDisocrdAPIの仕様を満たしていなくて動かなかったです。
認証用のDiscordアプリケーションの用意
Developersページでアプリケーションを新規作成する。
OAuth2設定を開いて、OAuth2 URL GeneratorからBotにチェックを入れる。
チェックを入れると出てくるBot Permissionsで、とりあえずManage RolesとView Channelsにチェックを入れて権限をつけておく。
生成されたURLにアクセスして、Botを認証に使うDiscordサーバーに招待しておく。
ソーシャルログインのセットアップ
Auth0の認証=>ソーシャルから、Discordへの接続を作成する。
Client IDとClient Secretには作っておいたDiscordアプリケーションのClient IDとClient Secretを設定。
Discord Developersページのアプリケーション設定内のOAuth2設定で、Redirectsに以下のURLを設定しておく。
https://<Auth0のドメイン>/login/callback
-設定例----
https://<テナント名>.jp.auth0.com/login/callback
トリガーの設定
トリガーはログイン後にnodejsのスクリプトを実行して、追加の認証処理を実装するやつです。
Auth0のアクション=>トリガー=>post-loginからログイン後のトリガーを設定します。
アクションを新規作成して、以下のコードを設定します。
const axios = require('axios');
exports.onExecutePostLogin = async (event, api) => {
// ---------------------------------------------------
// 1. ログイン方法の判定
// ---------------------------------------------------
// 今回のログインに使われたConnectionが "discord" でないなら
// チェックを行わずにログインを許可して終了
if (event.connection.name !== 'discord') {
return;
}
// ---------------------------------------------------
// 2. Identityの取得と検証
// ---------------------------------------------------
const identity = event.user.identities.find((v) => v.connection === "discord");
// Discord経由で来ているはずなのにIdentityがない(通常ありえないが念のため)
if (!identity) {
api.access.deny("Discord identity not found.");
return;
}
const userIdMatch = identity.user_id?.match(/discord\|(.+)/);
const discordUserId = userIdMatch ? userIdMatch[1] : identity.user_id;
if (!discordUserId) {
api.access.deny("Invalid Discord User ID format");
return;
}
// ---------------------------------------------------
// 3. Secretsの取得
// ---------------------------------------------------
const botToken = event.secrets.DISCORD_BOT_TOKEN;
const guildId = event.secrets.DISCORD_GUILD_ID;
const requiredRoleId = event.secrets.DISCORD_ROLE_ID;
if (!botToken || !guildId || !requiredRoleId) {
console.error("Missing secrets configuration.");
api.access.deny("Server configuration error.");
return;
}
// ---------------------------------------------------
// 4. APIによるメンバー・ロール確認
// ---------------------------------------------------
try {
const response = await axios.get(`https://discord.com/api/v10/guilds/${guildId}/members/${discordUserId}`, {
headers: { Authorization: `Bot ${botToken}` }
});
const memberRoles = response.data.roles || [];
// 指定ロールを持っていない場合
if (!memberRoles.includes(requiredRoleId)) {
api.access.deny("You do not have the required role to access this application.");
return;
}
// 問題なければログイン成功
return;
} catch (error) {
if (error.response && error.response.status === 404) {
// サーバーに参加していない
api.access.deny("You are not a member of the required Discord server.");
} else {
console.error("Discord API Error:", error.message);
// APIエラー時は安全のため拒否
api.access.deny("An error occurred while validating Discord membership.");
}
}
};
シークレットの設定
コードエディターのサイドバーで以下のシークレットを設定します。
-
DISCORD_BOT_TOKEN- Discord Developersのアプリケーション設定で、Bot設定から確認できるトークンを設定します。
-
DISCORD_GUILD_ID- DisocrdサーバーのIDを設定。このサーバーに入っているユーザーのみのログインを許可。
-
DISCORD_ROLE_ID- ロールのIDを設定。このロールを持っているユーザーのみのログインを許可します。
依存関係の設定
コードの中でaxiosを使用しているので、コードエディターのサイドバーから依存関係タブを開き、axiosのlatestバージョンを設定します。
動作チェック
Auth0の認証=>ソーシャルから、Discordを開いて接続を試すを実行します。
Discordで認証して、認証が通ればOK。

Discussion