PHP Discord OAuth2認証
PHP Laravel環境でDiscord OAuth2認証を行ったので備忘録
環境
・Larave 5.7
・PHP 7.2.15
前提
・Discord Developerで「OAUTH2_CLIENT_ID」「OAUTH2_CLIENT_SECRET」を取得
・Discord DeveloperでCallback URLの設定
ログイン時
public function login(Request $request)
{
define('OAUTH2_CLIENT_ID', '<OAUTH2_CLIENT_ID>');
define('OAUTH2_CLIENT_SECRET', '<OAUTH2_CLIENT_SECRET>');
$authorizeURL = 'https://discord.com/api/oauth2/authorize';
$tokenURL = 'https://discord.com/api/oauth2/token';
$apiURLBase = 'https://discord.com/api/users/@me';
$params = array(
'client_id' => OAUTH2_CLIENT_ID,
'redirect_uri' => '<Callback URL>',
'response_type' => 'code',
'scope' => 'identify guilds'
);
// Redirect the user to Discord's authorization page
header('Location: https://discord.com/api/oauth2/authorize' . '?' . http_build_query($params));
die();
}
Callbackで呼び出す関数
public function message_login_callback_discord(Request $request)
{
define('OAUTH2_CLIENT_ID', '<OAUTH2_CLIENT_ID>');
define('OAUTH2_CLIENT_SECRET', '<OAUTH2_CLIENT_SECRET>');
$authorizeURL = 'https://discord.com/api/oauth2/authorize';
$tokenURL = 'https://discord.com/api/oauth2/token';
$apiURLBase = 'https://discord.com/api/users/@me';
$apiURLGuild = 'https://discord.com/api/users/@me/guilds';
if($request->input('code')) {
// 初回のCallback
$token = $this->apiRequest($tokenURL, array(
"grant_type" => "authorization_code",
'client_id' => OAUTH2_CLIENT_ID,
'client_secret' => OAUTH2_CLIENT_SECRET,
'redirect_uri' => '<Callback URL>',
'code' => $request->input('code')
));
// sessionにaccess_tokenを格納
session(['access_token' => $token->access_token]);
return redirect('/message_login_callback_discord');
}
//上記処理後のCallback
if(session('access_token')) {
$user = $this->apiRequest($apiURLBase);
$guilds = $this->apiRequest($apiURLGuild);
return $user;
}
return redirect('/login');
}
その他「API Request 関数」
public function apiRequest($url, $post=FALSE, $headers=array()) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$response = curl_exec($ch);
if($post)
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$headers[] = 'Accept: application/json';
if(session('access_token'))
$headers[] = 'Authorization: Bearer ' . session('access_token');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
return json_decode($response);
}
おまけ「特定のDiscordサーバーに参加しているか確認」
$user = $this->apiRequest($apiURLBase);
$guilds = $this->apiRequest($apiURLGuild);
$check_suiseicord_join = false;
foreach ($guilds as $guild) {
if ($guild->id=="<確認したいサーバー(guild)のID>") {
$check_suiseicord_join = true;
}
}