You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PHP环境下OAuth2访问令牌存储与Discord授权相关技术问题咨询

Hey there! Let's walk through each of your Discord OAuth integration questions with practical, secure solutions—this stuff is crucial for keeping your app safe and user-friendly.

1. When Should I Refresh the Access Token?

First off, when you exchange the authorization code for an access token, Discord also sends you a refresh_token (this is the key to avoiding repeated logins you’re worried about). Here’s the plan:

  • Store the right data: Save the access_token, its expires_in value (7 days = 604800 seconds), the timestamp when you obtained it, and the refresh_token in your database tied to the user’s account.
  • Two reliable refresh strategies:
    • Proactive check: Every time you need to call the Discord API, calculate if the token is about to expire (e.g., within the next 15-30 minutes). If yes, use the refresh_token to fetch a new access_token (note: Discord may invalidate the old refresh_token after use, so be sure to update your database with the new one).
    • Reactive refresh: If you get a 401 Unauthorized response from Discord, trigger the refresh flow then, then retry the API call. This is simpler but adds a tiny bit of overhead on that first failed request.
      Either way, you won’t need to prompt users to re-login every 7 days as long as their refresh_token remains valid (it stays active until the user revokes your app’s access).

2. Where Should I Store the Access Token? Client or Database?

Never store the access token on the client side—not in localStorage, not in regular cookies. Client-side storage is vulnerable to XSS attacks, which would let attackers steal the token and act on the user’s behalf.

The correct approach is to store the access token (and refresh token) in your server-side database, tied to each user’s account. The client only needs a session ID (stored in an HttpOnly, Secure cookie) that your server uses to look up the user’s token data when needed. This keeps sensitive tokens out of reach of client-side threats.

3. Should I Hash the Access Token in the Database? How to Handle This in PHP?

Wait a second—hashes are one-way functions, meaning you can’t reverse them to get the original token back. And you need the original token to call Discord’s API, so hashing won’t work here. Instead, you should encrypt the token before storing it in the database, so you can decrypt it when you need to use it.

Here’s a secure implementation using PHP’s OpenSSL extension (AES-256-GCM is a strong, authenticated encryption algorithm):

First, generate a 32-byte encryption key (run this once, save the output somewhere safe—don’t hardcode it!):

// Generate a secure key (run this once, store the result securely)
echo base64_encode(random_bytes(32));

Then use these encrypt/decrypt functions:

function encryptDiscordToken(string $token, string $key): string {
    $key = base64_decode($key);
    $iv = random_bytes(openssl_cipher_iv_length('aes-256-gcm'));
    $tag = '';
    
    $encryptedToken = openssl_encrypt(
        $token,
        'aes-256-gcm',
        $key,
        OPENSSL_RAW_DATA,
        $iv,
        $tag
    );
    
    // Combine IV, tag, and encrypted token for storage
    return base64_encode($iv . $tag . $encryptedToken);
}

function decryptDiscordToken(string $encryptedToken, string $key): string {
    $key = base64_decode($key);
    $data = base64_decode($encryptedToken);
    
    $ivLength = openssl_cipher_iv_length('aes-256-gcm');
    $iv = substr($data, 0, $ivLength);
    $tag = substr($data, $ivLength, 16); // GCM tags are 16 bytes
    $encrypted = substr($data, $ivLength + 16);
    
    return openssl_decrypt(
        $encrypted,
        'aes-256-gcm',
        $key,
        OPENSSL_RAW_DATA,
        $iv,
        $tag
    );
}

When storing the token, pass it through encryptDiscordToken first. When you need to call Discord’s API, decrypt it with decryptDiscordToken.

4. Where to Store CLIENT_ID and CLIENT_SECRET? Is Hardcoding in PHP Files Safe?

Hardcoding these values in your PHP files is a big no-no. If your code gets leaked (e.g., accidentally pushed to GitHub, or your server is compromised), attackers can steal these credentials and impersonate your app.

Instead, store them in environment variables:

  • Use a .env file (with the vlucas/phpdotenv Composer package to load it) to define your secrets:
    DISCORD_CLIENT_ID=your-client-id-here
    DISCORD_CLIENT_SECRET=your-client-secret-here
    
  • Add .env to your .gitignore so it never gets committed to version control.
  • In your PHP code, retrieve them with getenv():
    $clientId = getenv('DISCORD_CLIENT_ID');
    $clientSecret = getenv('DISCORD_CLIENT_SECRET');
    

If you’re using a server like Apache or Nginx, you can also set environment variables directly in your server config instead of using a .env file—either way, keep these values out of your codebase.


内容的提问来源于stack exchange,提问作者Elyas Behroozizade

火山引擎 最新活动