Skip to main content

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

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

关于用户访问令牌

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

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

同样,用户访问令牌只能访问用户和应用都可访问的资源。 例如,如果向应用授予了对存储库 AB 的访问权限,并且用户可以访问存储库 BC,那么用户访问令牌可以访问存储库 B,但不能访问 AC。 可以使用 REST API 检查用户访问令牌可以访问哪些安装以及安装中的哪些存储库。 有关详细信息,请参阅“GitHub 应用安装”中的 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 过期前需经历的秒数。 如果禁用了用户访问令牌的有效期限,将省略此参数。 值将始终为 15811200(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 过期前需经历的秒数。 如果禁用了用户访问令牌的有效期限,将省略此参数。 值将始终为 15811200(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 过期前需经历的秒数。 如果禁用了用户访问令牌的有效期限,将省略此参数。 值将始终为 15811200(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 帐户上验证其主要电子邮件地址。 有关详细信息,请参阅 “验证电子邮件地址”。