Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow multiple account credentials #326

Open
ncmans opened this issue Feb 7, 2020 · 76 comments
Open

Allow multiple account credentials #326

ncmans opened this issue Feb 7, 2020 · 76 comments
Labels
auth related to tokens, authentication state, or oauth core This issue is not accepting PRs from outside contributors enhancement a request to improve CLI

Comments

@ncmans
Copy link

ncmans commented Feb 7, 2020

Describe the feature or problem you’d like to solve

I have two accounts on github each with access to a different set of private repositories. Currently I use a combination of git's [IncludeIf ...] config and a custom config which overrides the SSH private key I use for certain repositories. E.g.:

In ~/.gitconfig:

[includeIf "gitdir:~/work/"]
  path = ~/work/.gitconfig

and in ~/work/.gitconfig:

[core]
  sshCommand = "ssh -i ~/.ssh/work"

It will be great if the credentials for gh can also be configured per repository as well.

Proposed solution

There are a bunch of options I can think of:

  • Allow overriding gh config by a file in a local clone's .git directory
  • Allow defining rules in the gh config which defines which repos/orgs should use which credential. E.g.
github.com/google:
  - user: gemployee
    oauth_token: ...

github.com/microsoft:
  - user: msemployee
    oauth_token: ...

github.com:
  - user: personal
    oauth_token: ...

How will it benefit CLI and its users?

It will allow Github users with multiple accounts of varying access to seamlessly work on different repositories.

@mislav mislav added the enhancement a request to improve CLI label Apr 14, 2020
@eXamadeus
Copy link

Is there currently a way to work around this by removing the current authentication? I can't seem to find it.

Reinstalling seems to work, but it's very cumbersome.

@mislav
Copy link
Contributor

mislav commented May 4, 2020

@eXamadeus GitHub CLI currently has no mechanism for switching between multiple GitHub accounts and I don't really have a workaround to suggest for you at this moment, sorry.

The only approach I could imagine, but would not recommend to anyone, would be to authenticate with 1st account, save a copy of ~/.config/gh/hosts.yml somewhere & delete the original file, authenticate again with the 2nd account, and now you can swap the ~/.config/gh/hosts.yml file with the backup file when you need to switch accounts.

Since this solution involves using SSH for git protocol, make sure both configuration files include the git_protocol: ssh line.

@aitchkhan
Copy link

aitchkhan commented Sep 18, 2020

If we can add two entries or as many entries on every gh auth login. It might become easier with something like this:

github.com:
    user: aitchkhan
    oauth_token: xxx
    user: haroonKhan-10p
    oauth_token: xxx
    git_protocol: ssh

If the cli can somehow sense which username the current repository is associated to. It would be easy to find the user in the hosts.yml and rest would be magic.

PS: I have not gone through the codebase. These are my assumptions.

@seed-of-apricot
Copy link

seed-of-apricot commented Sep 30, 2020

Searched and landed here. This feature would help people with two or more accounts (personal/business/others) and use both of them every day (swapping the config file would be too much for them).

@vilmibm vilmibm added the core This issue is not accepting PRs from outside contributors label Sep 30, 2020
@fdm1
Copy link

fdm1 commented Sep 30, 2020

It's a bit hacky, but I solved this so that I could evaluate if I want to actually use this cli by using the token auth capabilities, putting this into my dotfiles.

alias gh_cli=$(which gh)
function gh() {
  if [[ $(pwd) =~ {PATH_TO_PERSONAL_CODE} ]]; then
    GITHUB_TOKEN=$PERSONAL_GH_CLI_TOKEN
  else
    GITHUB_TOKEN=$WORK_GH_CLI_TOKEN
  fi

  GITHUB_TOKEN=$GITHUB_TOKEN gh_cli $@
  unset GITHUB_TOKEN
}

@seed-of-apricot
Copy link

@fdm1 Which config file did you fill that in?

@fdm1
Copy link

fdm1 commented Oct 1, 2020

@fdm1 Which config file did you fill that in?

Just in my bash dotfiles

@tomholford
Copy link

tomholford commented Dec 15, 2020

Now that #2179 has been merged, perhaps it will be less effort to implement this feature?

Would be nice to have something like how git handles it:
~/.gitconfig

[includeIf "gitdir:~/dev/"]
  path = ~/.gitconfig.personal
[includeIf "gitdir:~/workspace/"]
  path = ~/.gitconfig.work

~/.gitconfig.work

[user]
  name = example-work-user
  email = [email protected]

edit

Now that I think about it some more, can gh infer which authed account to use from the current git config user.name or email?

@yangby-cryptape
Copy link

Since #2444 has been merged, as an alternative solution, set the environment variable GH_CONFIG_DIR to different directories could allow multiple accounts.

@dantonyuk
Copy link

dantonyuk commented Mar 22, 2021

I just implemented simple multi-account support based on the remote.origin.url config property (of course GH_HOST is on board as well): #3278

So having hosts.yml as

github.com:
    user: personal-account
    oauth_token: personal-token
github.com/acme:
    user: work-account
    oauth_token: work-token

we use work credentials for all acme repositories and personal credentials for everything else.

Unfortunately, gh cli uses global settings for "default" host, so I postponed the implementation of gh auth status which uses several credentials at the same time. Implemented.

@jeremy-ww
Copy link

Maybe this is a workaround if u wanna use multi credentials for a specific command. such as pr view

/usr/local/pr2

#!/usr/bin/python3

import subprocess
import json
import os
import re

with open(os.path.expanduser('~/.pr-config.json')) as f:
  configs = json.load(f)

command = 'gh pr view --web'
remote_url = subprocess.check_output(['git', 'config', '--get', 'remote.origin.url']).strip().decode()

for pattern, config in configs.items():
  is_match = re.match(pattern, remote_url)
  if is_match:
    os.system(
      f'GH_HOST={config["host"]} GH_ENTERPRISE_TOKEN={config["token"]} {command}'
    )
    break

~/.pr-config.json

{
  "[email protected]": {
    "host": "enterprise.com",
    "token": ""
  },
  "[email protected]": {
    "host": "enterprise1.com",
    "token": ""
  }
}

@thecharlesjenkins
Copy link

I am able to have multiple accounts signed in and that is nice, but one thing that I am trying to do is when I am creating a repository I would like to select my account. Doing something like gh repo create my_name/repo_name doesn't seem to work because one of my accounts is enterprise and one is public. Passing in my enterprise name like this causes HTTP 404: Not Found (https://api.github.com/users/my_enterprise_username) when I am logged into both my personal and enterprise GitHub but trying to create a repo for my private Github. This is not like a first-logged into account gets priority, no matter the order in which I log into my GitHub accounts I will receive this error when trying to create a repo for my enterprise account. Is there a way to force gh repo create to use the enterprise API instead of the public one? Right now I must log out of my personal account to create an enterprise repo unless I am doing something wrong.

@matthew-cline
Copy link

I've created a bash wrapper script for gh which makes it easier to do multiple accounts. Uses personal access tokens.

@camillesf
Copy link
Contributor

camillesf commented May 23, 2021

¡Hello!

After having read everything, I believe it'd be more robust not to second-guess anything, and mark the user to use via Git's own configuration mechanism.

From the original submission, the work config would be expanded to specify the username to use for the server in question:

# ~/work/gitconfig
[core]
    sshCommand = "ssh -i ~/.ssh/work"

[gh "github.com"]
    user = workuser

That way, we'd leverage the includeIf mechanism that everybody is already using to customize Git to their needs; hosts.yml could just have an array of stanzas for the same (or different) servers.

$  git config --get gh.github.com.user
workuser

(The hosts.yml format would have to be adjusted to be able to take multiple user stanzas, of course. A bit, but not quite, like #326 (comment).)

Edited to add: sadly, it would not work for things like gh repo clone, because all includeIf directives only when already in a repo.


Replying now to #326 (comment):

Now that I think about it some more, can gh infer which authed account to use from the current git config user.name or email?

I'm not sure that's a viable approach, since some users may not alter user.* variables (see the original submission where only sshCommand is changed).

@lucatpa
Copy link

lucatpa commented May 25, 2021

I strongly recommend using direnv in conjunction with GH_CONFIG_DIR to use multiple accounts.

@trkoch
Copy link

trkoch commented May 27, 2021

This is by far the easiest solution. If you don't like/cannot use direnv, you can still manually prefix GH_CONFIG_DIR. Shell wrappers above are clever, but this gets the job done just fine. @lucatpa Thanks for sharing!

I strongly recommend using direnv in conjunction with GH_CONFIG_DIR to use multiple accounts.

@kmaehashi
Copy link

We are under migration from GHES to GHEC (Enterprise Managed Users) and facing the same problem. Our employees are often required to use both GHEC EMU and the public GitHub.com to work with external collaborators or contribute to open-source projects, and needing the option to switch between EMU and public GitHub accounts.

To add some internal context here: we want this feature and have wanted it for a long time but have run into issues regarding respecting GitHub's terms of service around multiple account support.

I think there is documentation specific to this topic: https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-your-personal-account/managing-multiple-accounts
However, the method the doc suggests (use SSH for one account and HTTPS for the other) is too tricky, so we're expecting the GitHub CLI to solve this problem.

aravezskinteeth added a commit to aravezskinteeth/.dotfiles that referenced this issue Jul 7, 2023
- TODO : Search a workaround so I can have both accounts, see cli/cli#326
@Chrisjames7744

This comment was marked as spam.

iainelder added a commit to iainelder/dotfiles that referenced this issue Jul 14, 2023
I need to be able to set GH_CONFIG_DIR to use GH CLI features in non-personal
accounts.

When the [GH CLI](cli/cli#326) supports multiple profiles I may disable direnv again.
@freizl
Copy link

freizl commented Jul 19, 2023

gh-profile is cool but it softly broken due to 2.26.0 release.
Work around is go back to insecure storage (gh auth login --insecure-storage). gh-profile readme has the details.

@kmaehashi
Copy link

It is worth mentioning that:

I think the last part missing is the multi-account support in the gh command.

@firasdlke

This comment was marked as spam.

@firasdlke

This comment was marked as spam.

@firasdlke

This comment was marked as spam.

@electriquo
Copy link

following Multi-account support on GitHub.com accouterments. is gh going to add support for multi-account?

@andyfeller
Copy link
Contributor

following Multi-account support on GitHub.com accouterments. is gh going to add support for multi-account?

@electriquo : To give an explicit answer: yes

As you might see on this issue in the timeline, @williammartin and @samcoe have been working through the implications of multiple account and how this affects the authentication schema and the product experience.

@williammartin
Copy link
Member

williammartin commented Nov 15, 2023

To give a more nuanced answer: mostly, but it depends exactly what you mean

As @andyfeller mentioned above we are very actively exploring native support for being able to log into multiple accounts on a single host, and switch between them manually. In #8281 we are laying the ground work for the configuration schema and keyring migrations that need to occur to support this whilst providing backwards and a reasonable amount of forwards compatibility. After we feel comfortable with this, we will look to ship a UX focused around something like gh auth switch, providing the ability to change the currently active user on a host.

Explicitly out of scope for this tranche of work is automatic account switching based on some criteria (be that cwd, remote.origin.url, git config gh.github.com.user or anything else). We aren't ruling this out for the future but the myriad creative approaches outlined in this issue demonstrate that there are quite a few competing ideas and hopes and it needs some attention separate from the obvious use case outlined above.

Cheers ✌

@ConnorIngold
Copy link

To give a more nuanced answer: mostly, but it depends exactly what you mean

As @andyfeller mentioned above we are very actively exploring native support for being able to log into multiple accounts on a single host, and switch between them manually. In #8281 we are laying the ground work for the configuration schema and keyring migrations that need to occur to support this whilst providing backwards and a reasonable amount of forwards compatibility. After we feel comfortable with this, we will look to ship a UX focused around something like gh auth switch, providing the ability to change the currently active user on a host.

Explicitly out of scope for this tranche of work is automatic account switching based on some criteria (be that cwd, remote.origin.url, git config gh.github.com.user or anything else). We aren't ruling this out for the future but the myriad creative approaches outlined in this issue demonstrate that there are quite a few competing ideas and hopes and it needs some attention separate from the obvious use case outlined above.

Cheers ✌

For Christmas, I'm asking Santa for gh auth switch 🤞

@keikoro
Copy link

keikoro commented Nov 29, 2023

Having read through many issues on the topic now, I'm wondering if a proposal like this: #7081 (separating out the protocol + not hardcoding it into the host URL) couldn't be extended to also include ssh and solve the problem much more easily for people who already have different ssh configs set up for switching between accounts, e.g. when using git, than reworking the auth system.

Having to repeatedly (re)set and look up environment variables like GH_CONFIG_DIR also seems redundant/convoluted when existing tools are already configured to differentiate between users/scenarios, like, as said, via ssh config files or Git config settings which were pointed out up-thread.

I haven't really dug into the code (not a Go person) but considering --hostname is an option available for so many commands, I'm wondering if it couldn't be adapted for more flexibility.

@williammartin
Copy link
Member

Hi @keikoro, I'm not really following your comment sorry. Can you outline a bit more how you would expect this to work? In particular, how you would expect this to impact a scenario like: "I want to trigger workflow runs in private repositories that I only have access to in different accounts".

Cheers!

@williammartin
Copy link
Member

williammartin commented Dec 2, 2023

Hey folks, especially @ConnorIngold 🎅 ,

As we're heading towards releasing the first piece of multi-account functionality, I just wanted to share the multi-account-beta-20231202 branch which contains most of the changes we'd like to ship. Specifically, the UX changes are in:

  • gh auth login which now will add a new account under a host rather than replacing the old one
  • gh auth switch which is a new command that allows for switching between the active user for a host (if there are 2 it will automatically switch, 3 or more, will prompt for selection)
  • gh auth logout now prompts for logout if there is more than 1 account on the host, and switches to another on logout if there is one
  • gh auth status now shows all known accounts for hosts, and highlights the active one

The consequence of this is that you should be able to get tokens for multiple accounts and switch between those tokens easily with auth switch. Specifically, this will switch the token used for GitHub API requests and the token returned by gh when it is set up to manage git credentials.

We know there are many more features requested throughout this issue (e.g. automatic switching, automatic user and email git configuration), and there are plenty of other quality of life (get token with gh auth token --user, user specific configuration) and docs improvements we already know would be useful on top of this work. However, we're interested in releasing what we have before the Christmas break, assuming it already provides value, and then iterating on that with any feedback we receive.

If you're interested in playing around with this branch, read on...

Testing out multi account

The multi-account-beta-20231202 branch can be built from source and can be used at outlined above.

Note that there is not yet an account switching interstitial page in the authentication flow with GitHub, so at the point you open your browser, you'll want to have used the browser based account switcher to be logged in as the user you intend to authenticate with in the CLI.

The main challenge in this work was that the gh hosts.yml file (where hosts, their config, their user, and in --insecure-storage cases, their token live) schema only supported a single user per host, and having persistent data on disk presented a compatibility challenge. Be aware that this branch performs a migration on the data in this file (updating to a one-to-many mapping), and also adds a version to the config.yml file. We've attempted to retain forward compatibility so you should be able to use the current and older releases of gh with the new schema but given these are plain text files that could have been modified in any way, that's not something we can guarantee. If you are concerned about the data in these files, we advise you to take a backup but in the worst case, if something goes awry, you should be able to delete them, and use the release version again without any further burden other than logging in.

If you do run into issues with any of this, particularly around the schema migration, we'd love to know. Please leave feedback relating to this test branch in #8403, to avoid adding more noise to this issue.

Cheers!

@andyfeller
Copy link
Contributor

@gabe565 : wanted to make an intentional effort to invite you to test this beta feature and share your insights given https://github.com/gabe565/gh-profile 🙇 thank you again for supporting our community's needs for so long ❤

@williammartin
Copy link
Member

We've shipped the initial work described above in v2.40.0. Please read the release notes and the linked technical document for more details about what is in and out of scope and what the sharp edges might be.

Please leave any feedback on the release discussion.

As described in the technical document, we know there are plenty of things discussed in this issue that were not in scope for this release, so I will be leaving this issue open.

@iainelder
Copy link

@williammartin , I was reviewing my GitHub CLI configuration and you've just delighted me with the support for multiple logins. I'm pleased to see that you are working on the extra features to make this complete. I'm now subscribed to the issue to stay up to date.

@Jp3us
Copy link

Jp3us commented Mar 9, 2024 via email

torgeir added a commit to torgeir/nix-darwin that referenced this issue Mar 14, 2024
@Dramaga11

This comment was marked as spam.

@cornfeedhobo
Copy link

It's great to read that there is progress being made on this request.

Addressing one consistent comment:

Explicitly out of scope for this tranche of work is automatic account switching based on some criteria

I agree that there shouldn't be complex logic that determines which account to use, but if there is support for gh auth switch, could we add an --account flag for cloning?

Similarly, is the current scope to only support controlling the globally authenticated user (or "context", if using k8s parlance)? It would be really nice to not do that, and instead run with a UX that matches the other Github apps, where most users are assumed to have a "default" username that they use for most things, and N other usernames used for work/private uses.

@williammartin
Copy link
Member

@cornfeedhobo thanks for the feedback. It would be great if you could create an enhancement request for both of these so that we can discuss them specifically. We could then get a better understanding of your use cases and blend it into any larger designs (e.g. offering the ability to act as a particular authenticated user for any command). It also gives the community an opportunity to chime in without trudging through this horrendously long thread.

Cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auth related to tokens, authentication state, or oauth core This issue is not accepting PRs from outside contributors enhancement a request to improve CLI
Projects
No open projects
Status: No status
Development

No branches or pull requests