cli/cli

Allow multiple account credentials

ncmans opened this issue · 75 comments

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.

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.

@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.

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.

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).

fdm1 commented

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
}

@fdm1 Which config file did you fill that in?

fdm1 commented

@fdm1 Which config file did you fill that in?

Just in my bash dotfiles

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 = example@example.com

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?

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

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.

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

{
  "git@enterprise.com": {
    "host": "enterprise.com",
    "token": ""
  },
  "git@enterprise1.com": {
    "host": "enterprise1.com",
    "token": ""
  }
}

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.

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

¡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).

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

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.

Similar to @lucatpa I use a tool to manage my GH_CONFIG_DIR but I use OnDir instead. The advantage of this is that I don't have to setup multiple .envrc files in each repo

So I have this setup in my .config/gh folder

├── config.yml
├── org1
│   └── hosts.yml
└── org2
    └── hosts.yml

and I have this setup in my ~/.ondirrc config file

enter ~/source/org1/([^/]+)
  export GH_CONFIG_DIR="/Users/username/.config/gh/org1"

leave ~/source/org1/([^/]+)
  unset GH_CONFIG_DIR

enter ~/source/org2/([^/]+)
  export GH_CONFIG_DIR="/Users/username/.config/gh/org2"

leave ~/source/org2/([^/]+)
  unset GH_CONFIG_DIR

HTH

(Just to make it super clear, all my code is in /Users/username/source/)

Shingle.org.com

camh- commented

What about using git credential fill to get the creds and delegate it all to git-credential-helpers? If gh did this, it would work perfectly for my use case (two GitHub accounts with git already set up to use the right creds for various repos depending on repo org/user). It also means that gh does not need to store tokens in plaintext on the filesystem.

ezzra commented

I want to share my little approach that I build after reading this issue here some time ago, it does just link the hosts.yml config to user-specific hosts-username.yml files (which you need to create first), depending on a git repo setting (that you have to config).

However, it makes it possible to use use specific gh for specific Github users that you setup per local repo.

https://gist.github.com/ezzra/ec5a575a6cab368179bbd6a95e6f7fe6

(using git credential fill might be worth to use here, I didn't know about this when I created my workaround)

seriously? 2 years and github still won't listen to such an obvious feature?

camh- commented

@tr4g please be kind. i know it's frustrating, but there's so much work that can be done, not everything will get done. I personally want to take a crack at this, using git credential, but time keeps ticking.

For what it's worth, I have a switchhub script that symlinks a -<username> file to the main config file for hub and gh. It's a little manual, but eases the pain a bit for now. Attached.
switchhub.txt (renamed to .txt to be able to attach)

@camh- What does caller do here?

camh- commented

@eabase the last line of the script is the same as

# Only run main if executed as a script and not "sourced".
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then main "$@"; fi

I've been doing this a long time before ${BASH_SOURCE} worked for this and caller was the only way I found to do it. It is just inspecting the function call stack. I should update my script template.

This is a terrible Dev experience. Someone please fix this.

Too bad this did not work something like Kubectx. Just run a Kubectx command (which is pointed at all the Kube certs you have), and select which Kube cluster you want to work with. Made my life soo much easier!

https://github.com/ahmetb/kubectx

Not hating on the devs, just though I would chime in, Keep up the good work devs!

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

I have never head of direnv...you have started a new rabbithole and have saved me so much work...Thank you!

I have never head of direnv...you have started a new rabbithole and have saved me so much work...Thank you!

@j33pguy if you are down a rabbithole, you might as well try ondir 😁

Similar to @lucatpa I use a tool to manage my GH_CONFIG_DIR but I use OnDir instead. The advantage of this is that I don't have to setup multiple .envrc files in each repo

Until multiple accounts are not implemented in gh, I've ended up with such aliases to switch between regular GitHub and Company's GitHub (thank God gh supports aliases 😝): https://gist.github.com/yermulnik/017837c01879ed3c7489cc7cf749ae47

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.

[includeIf` "gitdir:~/work/"]

path = ~/work/.gitconfig

@thinkstack

I haven't used any of those, but seems like direnv supports exactly the same thing (print from their docs below), by searching parent folders for a .envrc (or .env) file.

So I guess you don't really need to put one file per directory if you organize your directories appropriately.

Direnv docs:

image


@yermulnik

Thanks! That's a very lightweight alternative if we don't want to install anything else.

How do you folks manage your credentials with those solutions?

1618365730

@marcelocra

How do you folks manage your credentials with those solutions?

Not sure this is what you're asking but I use 1password and chezmoi.

  • direnv sets GH_CONFIG_DIR, for example to ~/.config/gh/work
  • credentials are stored in 1password
  • chezmoi does dotfiles management and supports returning data from 1password using the cli. The template file for ~/.config/gh/work/hosts.yml looks like this:
github.com:
    user: leon-work
    oauth_token: {{ (onepasswordItemFields "2qaegfeuivaudgbx5zmdjtcjeu").credential.v }}
    git_protocol: ssh

Somewhat related: today I attempted to use gh pr create and was rebuffed because the GITHUB_TOKEN in my env was a token with very limited permissions. I'm using said token to authenticate with a GH package registry, so it has read-only permissions. It's loaded into my env by direnv. gh preferred the GITHUB_TOKEN env var over its other auth method. It would be useful to have a mechanism to ignore the environment variables. Or specify preferred ordering of auth method, i.e. first: try token negotiated with gh auth; then: try GITHUB_TOKEN etc.

Until this is officially supported, I have created a simple gh extension to manage multiple profiles. Check it out at gabe565/gh-profile.

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.

Duplicate of #

@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.

nmnduy commented

Since we can use GH_CONFIG_DIR to specify different gh config dir, I use direnv to set that env var for different projects.

After logging in with gh auth login, I copy .config/gh to my project dir, then use direnv to set GH_CONFIG_DIR to that location.

Since we can use GH_CONFIG_DIR to specify different gh config dir, I use direnv to set that env var for different projects.

After logging in with gh auth login, I copy .config/gh to my project dir, then use direnv to set GH_CONFIG_DIR to that location.

I did this too for a while! My gh extension actually takes advantage of direnv, but it sets up the .envrc file for you 😊

Here to add that this is a much desired feature please. constant nightmare switching accounts

Would also love to see a purpose-built solution added to the CLI please 🙏

@leonhfr was playing around with this today along with the 1Password CLI op. This seems to have worked for me:

  1. Run gh auth setup-git to get the helpers structure written to ~/.gitconfig
  2. Edit ~/.gitconfig so the helpers point instead at op as follows: helper = !op plugin run -- gh auth git-credential
  3. After that when you want to run the git CLI, it passes you directly through to 1Password - no templating in the gh hosts.yaml needed and multiple accounts stored in 1Password.

The current gh CLI command in item 1 above writes absolute paths to the gh binary without considering aliases that op adds.

Not sure what all the fuss is about. I got this to work fairly easily after purchasing a new computer for each Github account I have. Never had a problem since...

The issue is opened for a long time and still there is no native resolution. Maybe gh cli extension could be handy, here is one that I found https://github.com/gabe565/gh-profile.

Probably a gh cli extension that updates symlinks for the configuration files is easy to achieve. E.g.

There are many ways to solve it, but I would love to see a native support without any wrappers.

Since no one has brought it up, I would like to bring up the approach Gitlab's cli, glab, took to allow multiple accounts. I don't know if their approach was designed for this, but I found that it works very nicely with way I have already configured ssh.

glab allows you to define an api_host for each host you use. The api_host is simply the hostname of the Gitlab instance glab communicates with. The hostname is only used to for git communication. So if you set the git_protocol as ssh, ssh is what resolves the specified hostname to the correct hostname. The following configuration might clarify what I mean.

glab-cli/config.yml:

hosts:
    work.gitlab.com:
        api_host: gitlab.com
        user: <work user>
        token: <work_token>
        git_protocol: ssh

    personal.gitlab.com:
        api_host: gitlab.com
        user: <personal user>
        token: <personal_token>
        git_protocol: ssh

.ssh/config:

Host personal.gitlab*
	IdentityFile ~/.ssh/ed25519_personal

Host work.gitlab*
	IdentityFile ~/.ssh/ed25519_work

Host *gitlab*
	Hostname gitlab.com
	User git
	IdentitiesOnly yes

In your work projects you would set the remote url as:

git@work.gitlab.com:Work/work_project.git

And in your personal projects you would set the remote url as:

git@personal.gitlab.com:Persnoal/personal_project.git

If you want to define a default user for gitlab, you would then simply have to add gitlab.com as a host into both
.ssh/config and hosts.yml.

As you can see, when glab and ssh see the domain name personal.gitlab.com, they communicate with gitlab.com, but they have correctly setup the authentication for the personal user. I think gh would benefit from implementing such a separation between the api hostname and the specified hostname.

As a bonus, if you don't want to type git@personal.gitlab.com everytime you set a remote url and instead prefer persnoal@github.com, add the following lines to your git/config

[url "git@personal.gitlab.com"]
	insteadOf = personal@gitlab.com

This way git auto expands the url personal@gitlab.com to git@personal.github.com.

I have written a simple wrapper script to handle my github cli commands.
It uses fzf to dispatch on the username.

Usage

I use a keyring (gnome-keyring) with libsecret and set the git credential helper to that:

$ git config credential.helper=libsecret

I never have to enter passphrases with it (neither for ssh commit signing).

You add the token to the keyring:

$ username='exprpapi'
$ token="TOKEN_GH_${username}"
$ secret-tool store --label="${token}" "${token}" token

You can retrieve it like this:

$ username='exprpapi'
$ token="TOKEN_GH_${username}"
$ secret-tool lookup "${token}" token

I added the following to my shell config:

get_gh_name() {
  local names=('exprpapi' 'other_username1' 'other_username2')
  local name="$(printf '%s\n' "${names[@]}" | fzf)"
  echo "${name}"
}

get_gh_token() {
  local name="${1:-$(get_gh_name)}"
  local token="TOKEN_GH_${name}"
  local attribute="${token}"
  local value='token'
  local gh_token="$(secret-tool lookup "${attribute}" "${value})"
  echo "${gh_token}"
}

gh() {
  GH_TOKEN="$(get_gh_token)" /usr/bin/gh "$@"
}

I can now run cli commands and it will prompt me with fzf asking which identity to run it with:

demo

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 it's more likely than ever that we'll be able to do this but don't have it prioritized, yet.

GitHub's terms of service around multiple account support

@vilmibm What is the issue here? What if one is an external individual contributor for many GitHub enterprises that utilize managed users?

For what it's worth, I use git-credential (with git config --global credential.useHttpPath true) to manage different credentials for different repositories, and a wrapper function in my ~/.bashrc sets environment variables for each execution of gh.

gh() (
    : ${GH_HOST:=github.com}
    if [[ -z ${GH_REPO:-} ]]; then
        local URL=$(git config remote.origin.url)
        case $URL in
            https://${GH_HOST}/*) GH_REPO=${URL#https://${GH_HOST}/};;
            *@${GH_HOST}:*) GH_REPO=${URL#*@${GH_HOST}:};;
        esac
        GH_REPO=${GH_REPO%.git}
    fi
    if [[ -n ${GH_REPO:-} && -z ${GH_TOKEN:-} && -z ${GITHUB_TOKEN:-} ]]; then
        exec {fd}< <(git credential fill <<<url="https://${GH_HOST}/${GH_REPO}.git")
        while read -r -u $fd; do
            case $REPLY in
                password=*) GITHUB_TOKEN=${REPLY#*=};;
            esac
        done
        exec {fd}<&-
    fi
    export GH_HOST GH_REPO GH_TOKEN GITHUB_TOKEN
    command gh "$@"
)

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.

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.

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.

It is worth mentioning that:

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

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

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.

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 ✌

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 🤞

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.

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!

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!

@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 ❤

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.

@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.

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.

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.

@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!