Skip to content

Invalidate previous OAuth token when a new one is generated with gh auth #9233

Description

@danielfn

Describe the feature or problem you’d like to solve

Whenever an already logged-in user runs a gh auth login or gh auth refresh, a new OAuth app token is generated and replaces the previous token in the credentials store. The problem is that the old token is not revoked during this process, presenting a security risk for the user and any organization where that token has been authorized.

Proposed solution

Every time a user authenticates with the CLI, the previous OAuth app token should be removed from the local credentials store AND deleted from the user's GitHub account. IMHO, this should be the default and expected behavior.

Additional context

We discovered this issue while checking the list of SAML SSO authorizations for an organization. For a large organization,this list can easily become bloated with OAuth app tokens since they are not revoked unless explicitly done so by an organization owner or if the user removes the GitHub CLI integration from their settings.

This issue is further amplified because these tokens can't be configured with an expiry date. Related request:

Activity

  1. williammartin commented on Jun 20, 2024

    @williammartin
    Member

    Hey @danielfn, thanks for the write up.

    AND deleted from the user's GitHub account.

    I'm afraid this isn't possible, the platform has no support for the CLI to reasonably support this. It's something that we've talked about quite a few times internally. I'm certainly happy to bring this up again but I wouldn't expect to get very far with it.

    If revocation is important for you, you probably want to bring your own token.

  2. added
    gh-authrelating to the gh auth command
    and removed on Jun 20, 2024
  3. danielfn commented on Jun 21, 2024

    @danielfn
    Author

    Hi @williammartin, thanks for your quick reply!

    If revocation is important for you, you probably want to bring your own token.

    Of course, as a user I can use my own token, but as an organization owner I haven't found a way to enforce it.

    Correct me if I'm wrong, but this is because the GitHub CLI app is automatically authorized for use in any organization the user has access to. I tried limiting OAuth app and GitHub app access requests but this setting doesn't seem to apply to this app.

    Still, I find the gh auth login device flow really convenient for day-to-day use, but the long-lived Oauth app tokens (#5924) plus not automatically deauthorizing the previous one is what concerns me.

    EDIT: About:

    I tried limiting OAuth app and GitHub app access requests but this setting doesn't seem to apply to this app.

    It looks like this setting is only for external collaborators, not organization members, so it didn't apply in this case to begin with.

  4. sds commented on Sep 7, 2026

    @sds

    Moving the conversation from #14362 to this issue as requested by @williammartin. Goal is to understand what blockers there may be, and unless there are hard blockers find a path forward to resolve this issue.

    While that PR implements a proposed fix, concerns were raised. Repeating the concerns with my responses inline from the original PR.

    1. backwards compatibility (whether there are people who use gh auth token and put their token elsewhere)

    Fair point. I don't have data on how the CLI is used by others, I can only speak for how I've seen it used myself and by others at my org, and I've not seen this. That said, I would say principle of least surprise still applies—when I log out, I expect my token to be revoked if the very tool I'm using generated it, regardless of where else I've decided to inject the token.

    2. handling error cases (e.g. if people now expect tokens to be revoked, but revocation fails, I believe this PR will leave them stranded because the token has been removed from the keyring)

    Yes, this was missed in my own review and I appreciated the automated review pointing it out. It of course should be addressed.

    3. communicating how this relates to oauth tokens that may not be owned by the GitHub CLI OAuth app

    Relating to the prior point, this case will silently fail. Agree we should at least output some kind of warning that the token was not owned by the GitHub CLI app—this was an oversight. Relevant code

    4. communicating how this relates to other forms of token that might have been provided with --with-token

    Yes, I realize I left this out in the PR description even though I had intentionally (attempted to) address it. The implementation specifically only does this with OAuth tokens—it does not attempt to revoke other kinds of tokens (relevant code). However, I did not manually verify this particular case.

    • Concern 2 is a simple matter of handling those error cases. Happy to do this in any follow up PR.
    • Concerns 3—let me know if I'm missing something.
    • Concern 4 is partially answered—If you use --with-token to inject an OAuth token, then that will still be revoked with the current PR. Any other type of token is not revoked. Could address by tracking whether the token was imported via --with-token or not.

    I can't speak to concern 1 since I'm not clear on who uses that particular workflow (it seems niche?). It seems—at least to me—that we should apply the principle of least surprise and that logging out revokes a token, regardless of where that token was copied to or exfiltrated. Exfiltration is a primary concern with the CLI's current implementation—we'd like a way to quickly revoke a token if we suspect a compromise, as that would be the most secure approach.

    What can I do to move this forward?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    blockedenhancementa request to improve CLIgh-authrelating to the gh auth command

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions