akanyan/app/Auth.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' => static::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' => static::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",
],
]))));
}
}