Skip to main content

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

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

关于用户访问令牌

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

用户访问令牌是一种 OAuth 标记。 不同于传统 OAuth 标记,用户访问令牌不使用范围。 而是使用细粒度的权限。 用户访问令牌仅具有用户和应用都拥有的权限。 例如,如果向应用授予了写入存储库内容的权限,但用户只能读取内容,则用户访问令牌也只能读取内容。

同样,用户访问令牌只能访问用户和应用都可访问的资源。 例如,如果向应用授予了对存储库 AB 的访问权限,并且用户可以访问存储库 BC,那么用户访问令牌可以访问存储库 B,但不能访问 AC。 可以使用 REST API 检查用户访问令牌可以访问哪些安装以及安装中的哪些存储库。 有关详细信息,请参阅“GitHub App 安装的 REST API 终结点”中的 GET /user/installationsGET /user/installations/{installation_id}/repositories

使用用户访问令牌发出 API 请求时,用户访问令牌的速率限制适用。 有关详细信息,请参阅“GitHub 应用的速率限制”。

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

用户可以撤销其对 GitHub App 的授权。 有关详细信息,请参阅“令牌过期和吊销”。 如果用户撤销其对 GitHub App 的授权,应用会收到 github_app_authorization Webhook。 GitHub Apps 无法取消订阅此事件。 如果应用收到此 Webhook,应停止代表已撤销令牌的用户调用 API。 如果应用继续使用已撤销的访问令牌,它将收到 401 Bad Credentials 错误。 有关此 Webhook 的详细信息,请参阅“Webhook 事件和有效负载”。

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

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

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

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

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

    查询参数类型说明
    client_idstring必填。 GitHub App 的客户端 ID。 客户端 ID 不同于应用 ID。 可以在应用的设置页上找到客户端 ID。 若要详细了解如何导航到 GitHub App 的设置页,请参阅“修改 GitHub 应用注册”。
    redirect_uristring用户获得授权后被发送到的应用程序中的 URL。 此 URL 必须与在应用设置中作为“回叫 URL”提供的 URL 之一完全匹配,并且不能包含任何附加参数。
    statestring指定后,该值应该包含一个随机字符串,以防止伪造攻击,并且可以包含任何其他任意数据。
    loginstring指定后,Web 应用程序流会显示特定帐户,提示用户可使用该帐户登录和授权应用。
    allow_signupboolean在 OAuth 流程中,是否向未经身份验证的用户提供注册 GitHub 的选项。 默认为 true。 在策略禁止注册时使用 false
  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_idstring必填。 GitHub App 的客户端 ID。 客户端 ID 不同于应用 ID。 可以在应用的设置页上找到客户端 ID。 若要详细了解如何导航到 GitHub App 的设置页,请参阅“修改 GitHub 应用注册”。
    client_secretstring必填。 GitHub App的客户端密码。 可以在应用的设置页上生成客户端密码。
    codestring必填。 在上一步中收到的代码。
    redirect_uristring用户获得授权后被发送到的应用程序中的 URL。 此 URL 必须与在设置 GitHub App 时作为“回叫 URL”提供的 URL 之一完全匹配,并且不能包含任何附加参数。
    repository_idstring用户访问令牌可以访问的单个存储库的 ID。 如果 GitHub App 或用户无法访问存储库,将忽略此项。 使用此参数可进一步限制用户访问令牌的访问权限。
  4. GitHub 将做出包含以下参数的响应:

    响应参数类型说明
    access_tokenstring用户访问令牌。 令牌以 ghu_ 开头。
    expires_inintegeraccess_token 过期前需经历的秒数。 如果禁用了用户访问令牌的有效期限,将省略此参数。 值将始终为 28800(8 小时)。
    refresh_tokenstring刷新令牌。 如果禁用了用户访问令牌的有效期限,将省略此参数。 令牌以 ghr_ 开头。
    refresh_token_expires_inintegerrefresh_token 过期前需经历的秒数。 如果禁用了用户访问令牌的有效期限,将省略此参数。 值将始终为 15897600(6 个月)。
    scopestring令牌具有的范围。 此值将始终为空字符串。 不同于传统的 OAuth 标记,用户访问令牌仅限于应用和用户拥有的权限。
    token_typestring令牌类型。 值将始终为 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 Apps 生成 CLI”。

必须先在应用的设置中启用设备流,才能使用设备流。 有关启用设备流的详细信息,请参阅“修改 GitHub 应用注册”。

设备流使用 OAuth 2.0 设备授权模式。

  1. https://github.com/login/device/code 发送 POST 请求和 client_id 查询参数。 客户端 ID 不同于应用 ID。 可以在应用的设置页上找到客户端 ID。 若要详细了解如何导航到 GitHub App 的设置页,请参阅“修改 GitHub 应用注册”。

  2. GitHub 将做出包含以下查询参数的响应:

    响应参数类型说明
    device_codestring用于验证设备的验证码。 该验证码长度为 40 个字符。
    user_codestring应用程序应该显示的验证码,以便用户可以在浏览器中输入该验证码。 此代码为 8 个字符,中间有连字符。 例如,WDJB-MJHT
    verification_uristring用户需要在其中输入其 user_code 的 URL。 该 URL 为: https://github.com/login/device
    expires_inintegerdevice_codeuser_code 过期之前的秒数。 默认值为 900 秒(15 分钟)。
    intervalinteger在能够发出新的访问令牌请求 (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_idstring必填。 GitHub App 的客户端 ID。
    device_codestring必填。 在上一步中收到的设备验证码。
    grant_typestring必填。 授权类型必须是 urn:ietf:params:oauth:grant-type:device_code
    repository_idstring用户访问令牌可以访问的单个存储库的 ID。 如果 GitHub App 或用户无法访问存储库,将忽略此项。 使用此参数可进一步限制用户访问令牌的访问权限。

    轮询此终结点的频率不要高于 interval 指示的频率。 如果这样做,会达到速率限制并出现 slow_down 错误。 slow_down 错误响应向上一个 interval 添加 5 秒钟的时间。

    在用户输入代码之前,GitHub 将做出响应,其中包含一个 200 状态和一个 error 响应查询参数。

    错误名称说明
    authorization_pending授权请求待处理并且用户尚未输入用户代码时,将发生此错误。 应用应持续轮询 POST https://github.com/login/oauth/access_token,且轮询频率低于 interval 指定的频率。
    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轮询 OAuth 令牌请求 POST https://github.com/login/oauth/access_token 时,授权类型必须为 urn:ietf:params:oauth:grant-type:device_code 并且必须作为输入参数包含在内。
    incorrect_client_credentials对于设备流程,您必须传递应用程序的客户端 ID,您可以在应用程序设置页面上找到该 ID。 客户端 ID 不同于应用程序 ID 和客户端密码。
    incorrect_device_code提供的 device_code 无效。
    access_denied当用户在授权过程中单击取消时,你将收到 access_denied 错误,该用户将无法再次使用验证码。
    device_flow_disabled尚未在应用的设置中启用设备流。 有关启用设备流的详细信息,请参阅“修改 GitHub 应用注册”。
  5. 用户输入 user_code 后,GitHub 将做出包含以下查询参数的响应:

    响应参数类型说明
    access_tokenstring用户访问令牌。 令牌以 ghu_ 开头。
    expires_inintegeraccess_token 过期前需经历的秒数。 如果禁用了用户访问令牌的有效期限,将省略此参数。 值将始终为 28800(8 小时)。
    refresh_tokenstring刷新令牌。 如果禁用了用户访问令牌的有效期限,将省略此参数。 令牌以 ghr_ 开头。
    refresh_token_expires_inintegerrefresh_token 过期前需经历的秒数。 如果禁用了用户访问令牌的有效期限,将省略此参数。 值将始终为 15897600(6 个月)。
    scopestring令牌具有的范围。 此值将始终为空字符串。 不同于传统的 OAuth 标记,用户访问令牌仅限于应用和用户拥有的权限。
    token_typestring令牌类型。 值将始终为 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_idstring必填。 GitHub App 的客户端 ID。 客户端 ID 不同于应用 ID。 可以在应用的设置页上找到客户端 ID。 若要详细了解如何导航到 GitHub App 的设置页,请参阅“修改 GitHub 应用注册”。
    client_secretstring必填。 GitHub App的客户端密码。 可以在应用的设置页上生成客户端密码。
    codestring必填。 在上一步中收到的代码。
    redirect_uristring用户获得授权后被发送到的应用程序中的 URL。 此 URL 必须与在设置 GitHub App 时作为“回叫 URL”提供的 URL 之一完全匹配,并且不能包含任何附加参数。
    repository_idstring用户访问令牌可以访问的单个存储库的 ID。 如果 GitHub App 或用户无法访问存储库,将忽略此项。 使用此参数可进一步限制用户访问令牌的访问权限。
  4. GitHub 将做出包含以下参数的响应:

    响应参数类型说明
    access_tokenstring用户访问令牌。 令牌以 ghu_ 开头。
    expires_inintegeraccess_token 过期前需经历的秒数。 如果禁用了用户访问令牌的有效期限,将省略此参数。 值将始终为 28800(8 小时)。
    refresh_tokenstring刷新令牌。 如果禁用了用户访问令牌的有效期限,将省略此参数。 令牌以 ghr_ 开头。
    refresh_token_expires_inintegerrefresh_token 过期前需经历的秒数。 如果禁用了用户访问令牌的有效期限,将省略此参数。 值将始终为 15897600(6 个月)。
    scopestring令牌具有的范围。 此值将始终为空字符串。 不同于传统的 OAuth 标记,用户访问令牌仅限于应用和用户拥有的权限。
    token_typestring令牌类型。 值将始终为 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 App 使用正确的凭据。 可以在 GitHub App 的设置页面上找到客户端 ID 和客户端密码。 若要详细了解如何导航到 GitHub App 设置页面,请参阅“修改 GitHub 应用注册”。

重定向 URI 不匹配

如果指定的 redirect_uri 与 GitHub App 注册中的其中一个回调 URL 不匹配,将收到 redirect_uri_mismatch 错误。

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

验证码错误

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

若要解决此错误,应再次启动设备流以获取新代码。 有关详细信息,请参阅“使用设备流生成用户访问令牌”。

不好的刷新令牌

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

若要解决此错误,必须重启 Web 应用程序流或设备流,以获取新的用户访问令牌和刷新令牌。 仅当 GitHub App 已选择使用即将过期的用户访问令牌时,你才会收到刷新令牌。 有关详细信息,请参阅“刷新用户访问令牌”。

不支持的授权类型

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

未经验证的用户电子邮件

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

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