接入 GitHub(第三方登录或调用 API)主要依赖 OAuth 2.0 授权协议。通过接入 GitHub,开发者可以实现“用 GitHub 账号一键登录平台”以及“获取用户公开信息、仓库数据”等功能。

1. 接入前的准备:创建 OAuth App

在开始写代码前,必须先在 GitHub 注册一个 OAuth Application。

  1. 登录 GitHub,点击右上角头像 -> Settings(设置)。

  2. 在左侧边栏最下方,点击 Developer settings(开发者设置)。

  3. 选择 OAuth Apps,点击 New OAuth App(或 Register a new application)。

  4. 填写应用信息:

    • Application name:应用名称(如 MyApp)。

    • Homepage URL:应用主页地址(本地测试可填 http://localhost:3000)。

    • Authorization callback URL:核心字段,授权成功后的回调地址(如 http://localhost:3000/api/v1/auth/callback/github)。

  5. 点击 Register application 完成注册。

  6. 注册完成后,系统会生成:

    • Client ID:应用的公开唯一标识。

    • Client Secret:密钥,点击 Generate a new client secret 生成(切记妥善保管,严禁暴露在前端)。

官方参考文档:Creating an OAuth app - GitHub Docs

2. GitHub OAuth 2.0 核心交互流程

GitHub OAuth 2.0 采用标准的授权码模式(Authorization Code Grant):


+----------+                               +-------------------------------+
|          |--(A)- 重定向至 GitHub 授权页 ->|                               |
|          |                               |  GitHub 授权服务器 (GitHub)    |
|          |<--(B)- 带授权 Code 回调应用 ---|                               |
|          |                               +-------------------------------+
|  客户端   |                               
| (应用)   |                               +-------------------------------+
|          |--(C)- 用 Code+Secret 换 Token->|                               |
|          |<--(D)- 返回 Access Token -----|  GitHub 令牌/API 服务器        |
|          |                               |                               |
|          |--(E)- 携带 Token 请求 API ---->|                               |
|          |<--(F)- 返回 用户数据/资源 -----|                               |
+----------+                               +-------------------------------+

3. 详细对接步骤与 API 接口规范

步骤一:引导用户前往 GitHub 授权页

前端点击“使用 GitHub 登录”按钮时,将用户浏览器重定向至 GitHub 授权地址:

  • 请求方式:GET

  • 请求 URL:[https://github.com/login/oauth/authorize](https://github.com/login/oauth/authorize)

  • 参数说明:

参数名类型是否必填说明
client_idString是注册应用时获得的 Client ID
redirect_uriString否授权后的回调地址(必须与配置的回调地址匹配)
scopeString否申请的权限范围,多个权限用空格隔开(如 read:user user:email)
stateString推荐随机生成的不可预测字符串,用于防御 CSRF 跨站请求伪造

拼接示例:


https://github.com/login/oauth/authorize?client_id=YOUR_CLIENT_ID&scope=read:user%20user:email&state=RANDOM_STATE_STRING

步骤二:接收临时 Code 并换取 Access Token

用户在 GitHub 页面点击“同意授权”后,GitHub 会重定向回你的 redirect_uri,并在 URL 中附带 code 与 state:


http://localhost:3000/api/v1/auth/callback/github?code=AUTH_CODE_HERE&state=RANDOM_STATE_STRING

后端接收到 code 后,向 GitHub 发起服务端 POST 请求换取 Access Token:

  • 请求方式:POST

  • 请求 URL:[https://github.com/login/oauth/access_token](https://github.com/login/oauth/access_token)

  • 请求头 Header:Accept: application/json(默认 GitHub 会返回 query 字符串,设置 Header 可直接获取 JSON 格式响应)

  • 请求 Body 参数:

{
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET",
  "code": "AUTH_CODE_HERE"
}
  • 响应示例:
{
  "access_token": "gho_16C7e42F292c6912E7710c838347Ae178B4a",
  "token_type": "bearer",
  "scope": "read:user,user:email"
}

步骤三:使用 Access Token 获取用户信息

拿到 access_token 后,就可以调用 GitHub REST API 获取用户的公开资料:

  • 请求方式:GET

  • 请求 URL:[https://api.github.com/user](https://api.github.com/user)

  • 请求头 Header:

    • Authorization: Bearer gho_16C7e42F292c6912E7710c838347Ae178B4a

    • User-Agent: Your-App-Name(必须配置,GitHub API 强制要求设置 User-Agent,否则返回 403)

  • 响应示例:

{
  "login": "octocat",
  "id": 583231,
  "avatar_url": "https://avatars.githubusercontent.com/u/583231?v=4",
  "name": "The Octocat",
  "email": "octocat@github.com"
}

官方参考文档:Authorizing OAuth apps - GitHub Docs

简单示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>GitHub OAuth 示例</title>
</head>
<body>
    <h2>GitHub 登录示例</h2>
    <button id="login-btn">使用 GitHub 登录</button>
    <div id="user-info"></div>

    <script>
        // 1. 配置你的 GitHub Client ID 和后端回调接口
        const CLIENT_ID = '你的_GITHUB_CLIENT_ID';
        const REDIRECT_URI = 'http://localhost:3000/callback.html'; // 授权后的回调页面

        const loginBtn = document.getElementById('login-btn');

        // 点击按钮,跳转到 GitHub 授权页
        loginBtn.addEventListener('click', () => {
            const authUrl = `https://github.com/login/oauth/authorize?client_id=${CLIENT_ID}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&scope=read:user%20user:email`;
            window.location.href = authUrl;
        });

        // 2. 判断当前页面是否处于授权回调状态(URL 中是否有 code)
        const urlParams = new URLSearchParams(window.location.search);
        const code = urlParams.get('code');

        if (code) {
            document.getElementById('user-info').innerText = '正在登录,换取 Token 中...';
            
            // 将 code 发送到你自己的 Node.js 后端换取 Token
            fetch('http://localhost:3000/api/github/token', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ code })
            })
            .then(res => res.json())
            .then(data => {
                if (data.access_token) {
                    document.getElementById('user-info').innerHTML = `
                        <h3>登录成功!</h3>
                        <p><b>Access Token:</b> ${data.access_token}</p>
                        <p><b>用户名:</b> ${data.user.login}</p>
                        <img src="${data.user.avatar_url}" width="100" />
                    `;
                } else {
                    document.getElementById('user-info').innerText = '登录失败:' + (data.error || '未获取到 Token');
                }
            })
            .catch(err => {
                console.error(err);
                document.getElementById('user-info').innerText = '请求后端服务出错';
            });
        }
    </script>
</body>
</html>

4. 常见权限范围(Scopes)

在步骤一请求授权时,可以通过 scope 参数控制请求的权限大小,遵循最小权限原则:

Scope 标识权限说明
(空)仅获取公开信息(公开仓库、公开 Profile 数据)
read:user读取用户的基本 Profile 数据
user:email读取用户的私有邮箱地址
repo获取用户私有仓库及公开仓库的完整读写权限
gist创建与管理用户的 Gist

官方参考文档:Scopes for OAuth apps - GitHub Docs

5. 安全与开发最佳实践

  1. 绝对保护 Client Secret:Client Secret 只能保存在后端服务器的环境变量中,换取 Access Token 的步骤必须在服务端发起。

  2. 校验 state 参数:前端或服务端发起授权时,生成随机 Token 存入 Session/Cookie,回调时核对是否一致,防止 CSRF 攻击。

  3. 响应式 User-Agent:发送 HTTP 请求访问 GitHub API 时,必须在 Request Header 中加上自定义 User-Agent,否则请求会被拒绝。

  4. Token 安全存储:服务端拿到用户 access_token 后,如果要持久化,应进行加密存储(如 AES-256)。

6. 官方关键文档汇总链接