> ## Content Index
> Fetch the complete content index at: https://blog.anthea.day/llms.txt
> Use this file to discover other available public pages before exploring further.

# Discord OAuth 串接
- URL: https://blog.anthea.day/discord-oauth-integration/
- Published: 2025-08-28T17:27:24.000Z
- Updated: 2026-11-07T20:07:42.000Z
- Author: Anthea / 芫荽
- Tags: #Migrated-1792241843742, #Import 2026-10-17 12:57, Coding

最近在做 side project 的時後在煩惱登入應該怎麼處理比較方便，剛好 side project 是和遊戲相關的，於是決定來研究一下 Discord OAuth 的 API 要怎麼用。

#### 創立 Discord Application

首先進入到 [Discord Developer Portal](https://discord.com/developers/applications?ref=blog.anthea.day) 的畫面，點擊 `New Application` 並輸入名字。

![](https://blog.anthea.day/content/images/2026/10/1-ejsxgt7nduflzitc_4dyda.png)

接著點選剛剛建立好的 application 後會進入下面的畫面，從左邊的選單列點擊 `OAuth 2` 的選項後，找到 `Client Information` 的內容：

![](https://blog.anthea.day/content/images/2026/10/1-bx_icqt3sdv_z5ktt4kixa.png)

`Client ID` 和 `Client Secret` 都是等等我們的程式碼會需要用到的值，可以的話先記下來。之後再回到這個頁面的話會看到和圖片上一樣，`Client Secret` 會被 Discord 貼心的藏起來。

如果真的忘記的話按下 `Reset Secret` 就可以取得一組新的 secret 了。

#### 呼叫 Discord API

登入的流程主要是這樣的：

1. 呼叫 `https://discord.com/api/oauth2/authorize` 打開 Discord 取得授權的頁面（攜帶 redirect 的網址）
2. User 按下授權後根據剛剛的 redirect 網址由 Discord 做轉導，並且在網址上會攜帶一個參數 `code`
3. 帶著 code 在轉導的頁面中呼叫 [https://discord.com/api/oauth2/token](https://discord.com/api/oauth2/token?ref=blog.anthea.day) 取得 Bearer token
4. 拿到 Bearer token 之後就可以使用 Discord API 的其他服務了

具體的步驟如下：

首先，先建立一個 `index.html` 並放入下面的程式碼：

```xml
<div class="section" id="loginSection"> 
    <h2>Discord OAuth 登入</h2> 
    <p>設定完成後，點擊下方按鈕開始 Discord OAuth 流程：</p> 
    <button id="loginBtn" onclick="startDiscordLogin()">使用 Discord 登入</button> 
    <div id="loginStatus"></div> 
</div> 
 
<script> 
    startLogin() { 
        // 建立 Discord 授權 URL 
        const discordAuthUrl = new URL("https://discord.com/api/oauth2/authorize"); 
        discordAuthUrl.searchParams.set("client_id", this.config.clientId); 
        discordAuthUrl.searchParams.set("redirect_uri", this.config.redirectUri); 
        discordAuthUrl.searchParams.set("response_type", "code"); 
        discordAuthUrl.searchParams.set("scope", "identify email"); 
 
        // 重定向到 Discord 
        window.location.href = discordAuthUrl.toString(); 
    } 
</script>
```

![](https://blog.anthea.day/content/images/2026/10/1-v0sot1gq2tspvetjb5ag5g.png)

接著準備好轉導頁面 `redirect.html` 的內容：

```xml
<!-- 授權結果區域 --> 
<div class="section" id="authResult"> 
    <h2>授權結果</h2> 
    <div id="loginStatus"></div> 
</div> 
 
<!-- 取得用戶資訊 --> 
<div class="section" id="tokenSection"> 
    <button id="tokenBtn" onclick="getTokenAndUserInfo()">取得 token</button> 
    <div id="tokenResult"></div> 
</div> 
 
<!-- 用戶資訊區域 --> 
<div class="section" id="userSection"> 
    <h2>用戶資訊</h2> 
    <div id="userInfo"></div> 
    <button onclick="logout()">登出</button> 
</div> 
 
<script> 
    init() { 
        // 檢查 URL 中是否有授權碼 
        const urlParams = new URLSearchParams(window.location.search); 
        const code = urlParams.get("code"); 
        const error = urlParams.get("error"); 
 
        if (error) { 
            this.showError("授權被拒絕：" + error); 
        } else if (code) { 
            this.showAuthCode(code); 
        } 
    } 
 
    showAuthCode(code) { 
        const statusDiv = document.getElementById("loginStatus"); 
        statusDiv.innerHTML = ` 
            <div class="success"> 
                <p><strong>授權成功！</strong></p> 
                <p>授權碼：<code>${code}</code></p> 
                <p><strong>注意：</strong> 由於純前端無法安全處理 Client Secret，需要後端 API 來完成 Token 交換。</p> 
                <p>實作時請將此授權碼傳送給後端 <code>/api/auth/discord/callback</code> API。</p> 
            </div> 
        `; 
         
        // 清理 URL 
        window.history.replaceState({}, document.title, window.location.pathname); 
    } 
 
    async handleDiscordCallback() { 
        const config = { 
            clientId: localStorage.getItem("discord_client_id") || "", 
            clientSecret: localStorage.getItem("discord_client_secret") || "", 
            redirectUri: localStorage.getItem("discord_redirect_uri"), 
        }; 
 
        const urlParams = new URLSearchParams(window.location.search); 
        const code = urlParams.get("code"); 
 
        // 用授權碼交換 access token 
        const tokenResponse = await fetch("https://discord.com/api/oauth2/token", { 
            method: "POST", 
            headers: { 
                "Content-Type": "application/x-www-form-urlencoded", 
            }, 
            body: new URLSearchParams({ 
                client_id: config.clientId, 
                client_secret: config.clientSecret, 
                grant_type: "authorization_code", 
                code: code, 
                redirect_uri: config.redirectUri, 
                scope: "identify email", 
            }), 
        }); 
 
        const tokenData = await tokenResponse.json(); 
 
        // 取得用戶資訊 
        const userResponse = await fetch("https://discord.com/api/users/@me", { 
            headers: { 
                Authorization: `Bearer ${tokenData.access_token}`, 
            }, 
        }); 
 
        const userData = await userResponse.json(); 
 
        const userSectionDiv = document.getElementById("userInfo"); 
        userSectionDiv.innerHTML = ` 
            <div class="success"> 
                <p><strong>取得資訊成功！</strong></p> 
                <p>User ID <code>${userData.id}</code></p> 
                <p>User Display Name is ${userData.global_name}</p> 
                <p>User Account is ${userData.username}</p> 
            </div> 
        `; 
    } 
 
    init(); 
</script>
```

接著到 [Discord Developer Portal](https://discord.com/developers/applications?ref=blog.anthea.day) 裡面的 OAuth2 中 `Redirects` 的地方新增我們要轉導的頁面：

![](https://blog.anthea.day/content/images/2026/10/1-6gvikufl67rd84ssnxr3sw.png)

設定完成後透過 `index.html` 點擊登入，按下授權後就可以看到下面的畫面囉！

![](https://blog.anthea.day/content/images/2026/10/1--uh1iy8uphrw3izvbn0ysg.png)

完整的程式碼我會放在我的 [GitHub](https://github.com/anthea-wu/medium-demo?ref=blog.anthea.day) 中，以上就是今天的分享，我們下次見 👋