跳至主要内容

为 GitHub 应用程序生成用户访问令牌

你可以为你的 GitHub 应用程序生成用户访问令牌,以便将应用程序活动归因于用户。

关于用户访问令牌

注意:目前,到期用户访问令牌是一项可选功能,并且可能会发生变化。若要选择加入或退出令牌到期功能,请参阅“激活 GitHub 应用的可选功能”。有关更多信息,请参阅“GitHub 应用的用户到服务器访问令牌到期”。

用户访问令牌是一种 OAuth 令牌。与传统 OAuth 令牌不同,用户访问令牌不使用范围。相反,它使用细粒度权限。用户访问令牌仅具有用户和应用都拥有的权限。例如,如果应用被授予写入存储库内容的权限,但用户只能读取内容,那么用户访问令牌只能读取内容。

类似地,用户访问令牌只能访问用户和应用都可以访问的资源。例如,如果应用被授予对存储库 AB 的访问权限,并且用户可以访问存储库 BC,那么用户访问令牌可以访问存储库 B,但不能访问 AC。你可以使用 REST API 来检查用户访问令牌可以访问哪些安装以及安装中的哪些存储库。有关更多信息,请参阅“GitHub 应用安装的 REST API 端点”中的 GET /user/installationsGET /user/installations/{installation_id}/repositories

当你使用用户访问令牌进行 API 请求时,将应用用户访问令牌的速率限制。有关更多信息,请参阅“GitHub 应用的速率限制”。

默认情况下,用户访问令牌在 8 小时后到期。你可以使用刷新令牌重新生成用户访问令牌。有关更多信息,请参阅“刷新用户访问令牌”。

用户可以撤销其对 GitHub 应用的授权。有关详细信息,请参阅“令牌过期和撤销”。如果用户撤销其对 GitHub 应用的授权,该应用将收到 github_app_authorization webhook。GitHub 应用无法取消订阅此事件。如果你的应用收到此 webhook,则应停止以撤销令牌的用户的名义调用 API。如果你的应用继续使用已撤销的访问令牌,它将收到 401 错误的凭据 错误。有关此 webhook 的详细信息,请参阅“Webhook 事件和有效负载”。

你应保护用户访问令牌和刷新令牌的安全。有关详细信息,请参阅“创建 GitHub 应用的最佳实践”。

注意:如果用户报告称在授权你的 GitHub 应用后,他们无法查看其组织拥有的资源,并且该组织使用 SAML SSO,请指示用户在重新授权之前为其组织启动一个活动的 SAML 会话。有关详细信息,请参阅 GitHub Enterprise Cloud 文档中的“SAML 和 GitHub 应用”。

使用 Web 应用程序流程生成用户访问令牌

如果你的应用在浏览器中运行,则应使用 Web 应用程序流程生成用户访问令牌。有关使用 Web 应用程序流程的教程,请参阅“使用 GitHub 应用构建“使用 GitHub 登录”按钮”。

  1. 将用户定向到此 URL,并从以下参数列表中添加任何必要的查询参数:https://github.com/login/oauth/authorize。例如,此 URL 指定了 client_idstate 参数:https://github.com/login/oauth/authorize?client_id=12345&state=abcdefg

    查询参数类型是否必需?说明
    client_id字符串必需你的 GitHub 应用的客户端 ID。客户端 ID 不同于应用 ID。你可以在应用的设置页面中找到客户端 ID。有关导航到 GitHub 应用的设置页面的详细信息,请参阅“修改 GitHub 应用注册”。
    redirect_uri字符串强烈建议用户在授权后将被发送到的应用程序中的 URL。这必须与你在应用程序设置中提供的“回调 URL”之一完全匹配,并且不能包含任何其他参数。
    state字符串强烈建议指定时,该值应包含一个随机字符串以防止伪造攻击,并且它还可以包含任何其他任意数据。
    login字符串可选指定时,Web 应用程序流程将提示用户使用特定帐户登录并授权你的应用程序。
    allow_signup布尔值可选在 OAuth 流程中,未经身份验证的用户是否可以选择注册 GitHub。默认值为 true。当政策禁止注册时,使用 false
    prompt字符串可选如果设置为 select_account,则强制显示帐户选择器。如果应用程序具有非 HTTP 重定向 URI 或用户有多个已登录帐户,帐户选择器也会显示。
  2. 如果用户接受你的授权请求,GitHub 将把用户重定向到应用程序设置中的回调 URL 之一,并提供一个 code 查询参数,你可以在下一步中使用它来创建用户访问令牌。如果你在上一步中指定了 redirect_uri,将使用该回调 URL。否则,将使用应用程序设置页面上的第一个回调 URL。

    如果你在上一步中指定了 state 参数,GitHub 还会包含一个 state 参数。如果 state 参数与你在上一步中发送的 state 参数不匹配,则无法信任该请求,并且应中止 Web 应用程序流程。

  3. 通过向此 URL 发出 POST 请求,以及以下查询参数来交换上一步中的 code 以获取用户访问令牌:https://github.com/login/oauth/access_token

    查询参数类型说明
    client_id字符串必需。GitHub 应用程序的客户端 ID。客户端 ID 不同于应用程序 ID。你可以在应用程序的设置页面上找到客户端 ID。有关导航到 GitHub 应用程序的设置页面的详细信息,请参阅“修改 GitHub 应用程序注册”。
    client_secret字符串必需。GitHub 应用的客户端密钥。您可以在应用的设置页面中生成客户端密钥。
    code字符串必需。您在上一步骤中收到的代码。
    redirect_uri字符串用户在授权后会被发送到的应用程序中的 URL。这必须与您在设置 GitHub 应用时提供的“回调 URL”之一完全匹配,并且不能包含任何其他参数。
    repository_id字符串用户访问令牌可以访问的单个存储库的 ID。如果 GitHub 应用或用户无法访问该存储库,这将被忽略。使用此参数进一步限制用户访问令牌的访问权限。
  4. GitHub 将提供一个包含以下参数的响应

    响应参数类型说明
    access_token字符串用户访问令牌。令牌以ghu_开头。
    expires_in整数access_token到期前的秒数。如果您禁用了用户访问令牌的过期,将省略此参数。该值始终为28800(8 小时)。
    refresh_token字符串刷新令牌。如果您禁用了用户访问令牌的过期,将省略此参数。令牌以ghr_开头。
    refresh_token_expires_in整数refresh_token到期前的秒数。如果您禁用了用户访问令牌的过期,将省略此参数。该值始终为15897600(6 个月)。
    scope字符串令牌具有的范围。此值始终为空字符串。与传统 OAuth 令牌不同,用户访问令牌仅限于您的应用和用户都具有的权限。
    token_type字符串令牌的类型。该值始终为bearer
  5. 使用上一步骤中的用户访问令牌代表用户进行 API 请求。将用户访问令牌包含在 API 请求的Authorization标头中。例如

    curl --request GET \
    --url "https://api.github.com/user" \
    --header "Accept: application/vnd.github+json" \
    --header "Authorization: Bearer USER_ACCESS_TOKEN" \
    --header "X-GitHub-Api-Version: 2022-11-28"
    

使用设备流生成用户访问令牌

注意:设备流处于公开测试阶段,可能会发生变化。

如果您的应用是无头应用或无法访问浏览器,您应该使用设备流来生成用户访问令牌。例如,CLI 工具、简单的 Raspberry Pi 和桌面应用程序应使用设备流。有关使用设备流的教程,请参阅“使用 GitHub 应用构建 CLI”。

在使用设备流之前,您必须先在应用设置中启用它。有关启用设备流的更多信息,请参阅“修改 GitHub 应用注册”。

设备流使用 OAuth 2.0 设备授权授予。

  1. https://github.com/login/device/code 发送 POST 请求,同时附带 client_id 查询参数。客户端 ID 与应用 ID 不同。你可以在应用的设置页面中找到客户端 ID。有关导航到 GitHub 应用设置页面的详细信息,请参阅“修改 GitHub 应用注册”。

  2. GitHub 将提供一个响应,其中包括以下查询参数

    响应参数类型说明
    device_code字符串用于验证设备的验证码。此代码长 40 个字符。
    user_code字符串你的应用程序应显示的验证码,以便用户可以在浏览器中输入该代码。此代码为 8 个字符,中间带连字符。例如,WDJB-MJHT
    verification_uri字符串用户需要输入其 user_code 的 URL。该 URL 为:https://github.com/login/device
    expires_in整数device_codeuser_code 过期前的时间(以秒为单位)。默认值为 900 秒(15 分钟)。
    interval整数在你可以发出新的访问令牌请求(POST https://github.com/login/oauth/access_token)以完成设备授权之前必须经过的最小秒数。如果你在该时间间隔过去之前发出请求,则会达到速率限制并收到 slow_down 错误。默认值为 5 秒。
  3. 提示用户在 https://github.com/login/device 中输入上一步中的 user_code

    如果用户在 expires_in 时间过去之前未输入代码,则该代码将失效。在这种情况下,你应重新启动设备流。

  4. 轮询 POST https://github.com/login/oauth/access_token,同时附带 client_iddevice_codegrant_type 查询参数(如下所述),直至设备和用户代码过期或用户通过输入 user_code 成功授权该应用。

    查询参数类型说明
    client_id字符串必需。你的 GitHub 应用的客户端 ID。
    device_code字符串必需。你在上一步中收到的设备验证码。
    grant_type字符串必需。授予类型必须为 urn:ietf:params:oauth:grant-type:device_code
    repository_id字符串用户访问令牌可以访问的单个存储库的 ID。如果 GitHub 应用或用户无法访问该存储库,这将被忽略。使用此参数进一步限制用户访问令牌的访问权限。

    不要以高于 interval 指示的频率轮询此端点。如果你这样做,则会达到速率限制并收到 slow_down 错误。slow_down 错误响应将 5 秒添加到最后一个 interval

    在用户输入代码之前,GitHub 将以 200 状态和 error 响应查询参数进行响应。

    错误名称说明
    authorization_pending当授权请求处于待定状态且用户尚未输入用户代码时,会发生此错误。应用程序应以不高于 interval 指定的频率持续轮询 POST https://github.com/login/oauth/access_token
    slow_down当您收到 slow_down 错误时,将在使用 POST https://github.com/login/oauth/access_token 的请求之间所需的最小 interval 或时间范围内添加 5 秒。例如,如果起始间隔要求请求之间至少间隔 5 秒,并且您收到 slow_down 错误响应,则现在必须至少等待 10 秒才能对令牌提出新请求。错误响应包括您必须使用的新的 interval
    expired_token如果设备代码已过期,则您将看到 token_expired 错误。您必须对设备代码提出新请求。
    unsupported_grant_type授予类型必须为 urn:ietf:params:oauth:grant-type:device_code,并且在轮询 OAuth 令牌请求 POST https://github.com/login/oauth/access_token 时作为输入参数包含在内。
    incorrect_client_credentials对于设备流,您必须传递应用程序的客户端 ID,您可以在应用程序设置页面中找到它。客户端 ID 不同于应用程序 ID 和客户端密钥。
    incorrect_device_code提供的 device_code 无效。
    access_denied当用户在授权过程中单击取消时,您将收到 access_denied 错误,并且用户将无法再次使用验证代码。
    device_flow_disabled设备流尚未在应用程序设置中启用。有关启用设备流的详细信息,请参阅“修改 GitHub 应用程序注册”。
  5. 一旦用户输入了 user_code,GitHub 将提供一个包含以下查询参数的响应

    响应参数类型说明
    access_token字符串用户访问令牌。令牌以ghu_开头。
    expires_in整数access_token到期前的秒数。如果您禁用了用户访问令牌的过期,将省略此参数。该值始终为28800(8 小时)。
    refresh_token字符串刷新令牌。如果您禁用了用户访问令牌的过期,将省略此参数。令牌以ghr_开头。
    refresh_token_expires_in整数refresh_token到期前的秒数。如果您禁用了用户访问令牌的过期,将省略此参数。该值始终为15897600(6 个月)。
    scope字符串令牌具有的范围。此值始终为空字符串。与传统 OAuth 令牌不同,用户访问令牌仅限于您的应用和用户都具有的权限。
    token_type字符串令牌的类型。该值始终为bearer
  6. 使用上一步骤中的用户访问令牌代表用户进行 API 请求。将用户访问令牌包含在 API 请求的Authorization标头中。例如

    curl --request GET \
    --url "https://api.github.com/user" \
    --header "Accept: application/vnd.github+json" \
    --header "Authorization: Bearer USER_ACCESS_TOKEN" \
    --header "X-GitHub-Api-Version: 2022-11-28"
    

在用户安装您的应用程序时生成用户访问令牌

如果您在应用程序设置中选择 在安装期间请求用户授权 (OAuth),则 GitHub 将在用户安装您的应用程序后立即启动 Web 应用程序流。

无论应用程序安装在用户帐户还是组织帐户上,您都可以使用此方法生成用户访问令牌。但是,如果应用程序安装在组织帐户上,您将需要使用 Web 应用程序流程或设备流程为组织中的其他用户生成用户访问令牌。

  1. 当用户安装您的应用程序时,GitHub 会将用户重定向到 https://github.com/login/oauth/authorize?client_id=CLIENT_ID,其中 CLIENT_ID 是您应用程序的客户端 ID。

  2. 如果用户接受您的授权请求,GitHub 会将用户重定向到您应用程序设置中的第一个回调 URL,并提供一个 code 查询参数。

    如果您想控制使用哪个回调 URL,请不要选择在安装期间请求用户授权 (OAuth)。相反,引导用户完成完整的 Web 应用程序流程并指定 redirect_uri 参数。

  3. 通过向此 URL 发出 POST 请求,以及以下查询参数来交换上一步中的 code 以获取用户访问令牌:https://github.com/login/oauth/access_token

    查询参数类型说明
    client_id字符串必需。GitHub 应用程序的客户端 ID。客户端 ID 不同于应用程序 ID。你可以在应用程序的设置页面上找到客户端 ID。有关导航到 GitHub 应用程序的设置页面的详细信息,请参阅“修改 GitHub 应用程序注册”。
    client_secret字符串必需。GitHub 应用的客户端密钥。您可以在应用的设置页面中生成客户端密钥。
    code字符串必需。您在上一步骤中收到的代码。
    redirect_uri字符串用户在授权后会被发送到的应用程序中的 URL。这必须与您在设置 GitHub 应用时提供的“回调 URL”之一完全匹配,并且不能包含任何其他参数。
    repository_id字符串用户访问令牌可以访问的单个存储库的 ID。如果 GitHub 应用或用户无法访问该存储库,这将被忽略。使用此参数进一步限制用户访问令牌的访问权限。
  4. GitHub 将提供一个包含以下参数的响应

    响应参数类型说明
    access_token字符串用户访问令牌。令牌以ghu_开头。
    expires_in整数access_token到期前的秒数。如果您禁用了用户访问令牌的过期,将省略此参数。该值始终为28800(8 小时)。
    refresh_token字符串刷新令牌。如果您禁用了用户访问令牌的过期,将省略此参数。令牌以ghr_开头。
    refresh_token_expires_in整数refresh_token到期前的秒数。如果您禁用了用户访问令牌的过期,将省略此参数。该值始终为15897600(6 个月)。
    scope字符串令牌具有的范围。此值始终为空字符串。与传统 OAuth 令牌不同,用户访问令牌仅限于您的应用和用户都具有的权限。
    token_type字符串令牌的类型。该值始终为bearer
  5. 使用上一步骤中的用户访问令牌代表用户进行 API 请求。将用户访问令牌包含在 API 请求的Authorization标头中。例如

    curl --request GET \
    --url "https://api.github.com/user" \
    --header "Accept: application/vnd.github+json" \
    --header "Authorization: Bearer USER_ACCESS_TOKEN" \
    --header "X-GitHub-Api-Version: 2022-11-28"
    

使用刷新令牌生成用户访问令牌

默认情况下,用户访问令牌在 8 小时后过期。如果您收到带有到期时间的用户访问令牌,您还将收到一个刷新令牌。刷新令牌在 6 个月后过期。您可以使用此刷新令牌重新生成用户访问令牌。有关更多信息,请参阅“刷新用户访问令牌”。

GitHub 强烈建议您使用会过期的用户访问令牌。如果您之前选择不使用会过期的用户访问令牌,但又想重新启用此功能,请参阅“激活 GitHub 应用程序的可选功能”。

故障排除

以下部分概述了在生成用户访问令牌时您可能会收到的部分错误。

客户端凭据不正确

如果您指定的 client_idclient_secret 不正确,您将收到 incorrect_client_credentials 错误。

要解决此错误,请务必为您的 GitHub 应用程序使用正确的凭据。您可以在 GitHub 应用程序的设置页面上找到客户端 ID 和客户端密钥。有关导航到 GitHub 应用程序设置页面的更多信息,请参阅“修改 GitHub 应用程序注册”。

重定向 URI 不匹配

如果您指定的 `redirect_uri` 与 GitHub 应用程序注册中的回调 URL 之一不匹配,您将收到 `redirect_uri_mismatch` 错误。

要解决此错误,请提供与 GitHub 应用程序注册中的回调 URL 之一匹配的 `redirect_uri`,或省略此参数以默认为 GitHub 应用程序注册中列出的第一个回调 URL。有关更多信息,请参阅“关于用户授权回调 URL”。

错误的验证代码

如果您正在使用设备流,并且您指定的验证代码 (device_code) 不正确、已过期或与您从对 https://github.com/login/device/code 的初始请求中收到的值不匹配,您将收到 `bad_verification_code` 错误。

要解决此错误,您应该重新启动设备流以获取新代码。有关更多信息,请参阅“使用设备流生成用户访问令牌”。

错误的刷新令牌

如果您指定的刷新令牌无效或已过期,您将收到 `bad_refresh_token` 错误。

要解决此错误,您必须重新启动 Web 应用程序流或设备流以获取新的用户访问令牌和刷新令牌。只有当您的 GitHub 应用程序选择让用户访问令牌过期时,您才会收到刷新令牌。有关更多信息,请参阅“刷新用户访问令牌”。

不受支持的授权类型

当您通过设备流请求用户访问令牌时,`grant_type` 参数必须为 `urn:ietf:params:oauth:grant-type:device_code`。当您使用刷新令牌刷新用户访问令牌时,`grant_type` 参数必须为 `refresh_token`。如果您没有使用正确的授权类型,您将收到 `unsupported_grant_type` 错误。

未验证的用户电子邮件

如果您尝试为其生成用户访问令牌的用户尚未使用 GitHub 验证其主要电子邮件地址,您将收到 `unverified_user_email` 错误。

要解决此错误,请提示用户验证其 GitHub 帐户上的主要电子邮件地址。有关更多信息,请参阅“验证您的电子邮件地址”。