80 lines
2.7 KiB
PHP
80 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace MingTsay\Akanyan;
|
|
|
|
use Exception;
|
|
use MingTsay\Akanyan\Discord\Me;
|
|
use MingTsay\Akanyan\Discord\Token;
|
|
|
|
require_once __DIR__ . '/../env.php';
|
|
|
|
class Auth
|
|
{
|
|
private const DISCORD_REDIRECT_URI = 'https://akanyan.oho.tw/auth.php?source=discord';
|
|
|
|
public static function encrypt(Token $payload): ?string
|
|
{
|
|
$key = file_get_contents(__DIR__ . '/../sodium_key');
|
|
try {
|
|
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);
|
|
$cipher = sodium_crypto_aead_xchacha20poly1305_ietf_encrypt(json_encode($payload), '', $nonce, $key);
|
|
|
|
return implode(';', array_map('base64_encode', [$nonce, $cipher]));
|
|
} catch (Exception) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static function decrypt(string $u): ?Token
|
|
{
|
|
$key = file_get_contents(__DIR__ . '/../sodium_key');
|
|
try {
|
|
list($nonce, $cipher) = array_map('base64_decode', explode(';', $u));
|
|
$payload = json_decode(sodium_crypto_aead_xchacha20poly1305_ietf_decrypt($cipher, '', $nonce, $key));
|
|
if ($payload === null) return null;
|
|
return new Token($payload);
|
|
} catch (Exception) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static function authorize(): string
|
|
{
|
|
$query_string = http_build_query([
|
|
'client_id' => $_ENV['DISCORD_CLIENT_ID'],
|
|
'redirect_uri' => self::DISCORD_REDIRECT_URI,
|
|
'response_type' => 'code',
|
|
'scope' => 'identify',
|
|
]);
|
|
return "https://discord.com/api/oauth2/authorize?$query_string";
|
|
}
|
|
|
|
public static function getTokenByCode(string $code): ?Token
|
|
{
|
|
$payload = json_decode(file_get_contents('https://discord.com/api/oauth2/token', false, stream_context_create([
|
|
'http' => [
|
|
'method' => 'POST',
|
|
'header' => 'Content-Type: application/x-www-form-urlencoded',
|
|
'content' => http_build_query([
|
|
'client_id' => $_ENV['DISCORD_CLIENT_ID'],
|
|
'client_secret' => $_ENV['DISCORD_CLIENT_SECRET'],
|
|
'grant_type' => 'authorization_code',
|
|
'code' => $code,
|
|
'redirect_uri' => self::DISCORD_REDIRECT_URI,
|
|
]),
|
|
],
|
|
])));
|
|
if ($payload === null) return null;
|
|
return new Token($payload);
|
|
}
|
|
|
|
public static function getMe(Token $getU): ?Me
|
|
{
|
|
return new Me(json_decode(file_get_contents('https://discord.com/api/oauth2/@me', false, stream_context_create([
|
|
'http' => [
|
|
'method' => 'GET',
|
|
'header' => "Authorization: Bearer $getU->access_token",
|
|
],
|
|
]))));
|
|
}
|
|
}
|