Isomorphic Git (which we use) doesn’t, for example. Not sure I particularly want it to, either—such a feature would probably bring in a host of dependencies but not much to the table compared to a scoped PAT.
The core SecSH (ie SSH 2) protocol design assumes you have SSH keys, offering password authentication only as an optional extra feature.
Now of course the IETF does not have an enforcement arm, and I have seen implementations that don't work like that, but to me this is an obvious red flag, like a stub plugged in to stop the seat belt alarm going off, "I know that what I'm doing is very stupid, so I worked harder to do it anyway". OK then.
I see about two possible cases:
1) One uses Git CLI and wants to get rid of incessant password prompts this way.
2) One has a setup in which multiple servers access a private Git repo, and wants each server to use different credentials.
This doesn’t seem worth the trouble in simpler scenarios when the user accesses Git from one or two personal machines and is entirely fine just changing their password/revoking PAT if it is compromised.
In HTTPS the model is, you and the server both know a secret, your "password" and then you... just tell them your secret each time to authenticate.
That's a pretty good model if you're a ten year old playing forts out in the woods, but it's far below what we ought to be achieving for a service like this.
It's true that this plaintext password authentication is normal for the web, which is basically Tim (Berners-Lee)'s fault but that doesn't magically make it a good idea, and it makes sense that GitHub doesn't want "Yes it's crap but it's no worse than the web" to be all they're delivering.
The relying party (GitHub in this case) learn nothing secret. Your authentication credentials literally can't be stolen from GitHub because they don't have them, so you don't need to care about how well they try to protect them.
A MITM learns nothing secret. If things go wrong and you somehow allow a MITM attack to occur, the MITM doesn't get durable credentials from you, once you are talking to GitHub not the MITM they're locked out, even though they watched you authenticate successfully, perhaps many times, they do not learn how to forge working credentials.
> If things go wrong and you somehow allow a MITM attack to occur
I get the point, though perhaps the phrasing could do with a little less victim-shaming. How many of the times you were MITMed did you allow that to happen? Now count cases about which you still don’t know.
> Your authentication credentials literally can't be stolen from GitHub because they don't have them, so you don't need to care about how well they try to protect them.
To me, secret management on the side of an unsophisticated user is arguably of more worry than someone breaking into GitHub and stealing PATs.
Consider if a user is casually contributing to documentation on GitHub using some Git client which forces them to supply an SSH key for authentication. Now there is more than one way things could go wrong, for example:
1) They use a key without a passphrase, and it is stored somewhere on their filesystem (perhaps under ~/.ssh, where ssh-keygen wants to place it by default) where any app with disk access can read it. Voila, a third party gets full access to their GitHub repositories.
2) They use a weak passphrase, reuse an old password for passphrase, or store the passphrase in plain text. Similar liability.
Meanwhile, PAT is: long, auto-generated by GitHub (so one can’t reuse a password), shown only once, doesn’t make sense for the user to save, and the client can make sure to store it using a sound mechanism (e.g., Keychain on macOS).
That said, a well-behaved user-friendly Git client could neutralize some of the downsides by taking care of generating a completely new, passphrase-protected SSH keypair under the hood, storing the passphrase and the private part reliably, and asking the user to add the public part to their GitHub account, each time it is set up on a new machine. I wonder how many clients go to such lengths.
Right, so, with a lot of extra hoop jumping GitHub have been able to special case HTTPS authentication for their site so that if you use these tokens it's only somewhat worse than what you get out of the box with SSH.
>What you need to do today: For developers, if you are using a password to authenticate Git operations with GitHub.com today, you must begin using a personal access token over HTTPS (recommended) or SSH key by August 13, 2021, to avoid disruption.
What you describe is a problem the organization has created for themselves. If they can't also come up with a solution for themselves, well, that's their problem, I guess. Stupid hurts.
As long as they're only shooting themselves with the nailgun and no one else, I'm fine with 'em doing it. Hell, I'd probably show 'em how to load it.
--
Pro-tip:
$ ssh -T -p 443 git@ssh.github.com#! /usr/bin/env sh
ssh-add ~/.ssh/id_github
ssh-add ~/.ssh/id_github2
or something like that and then just name it sshadd on the path
or create an alias in your login script
alias sshadd="ssh-add ~/.ssh/id_github && ssh-add ~/.ssh/id_github2"
I haven't actually tried it yet myself, but I think my preference would be to set the "IdentityFile" option to an environment variable (i.e., "${SSH_IDENTITYFILE}") in my ~/.ssh/config file, within an explicit "Host" definition for "github.com").
In my shell initialization files, I'd set $SSH_IDENTITYFILE to either "%d/.ssh/id_ed25519_github_personal" or "%d/.ssh/id_ed25519_github_work" (for example), depending on which I wanted to be the default.
When I wanted to use the other account, all I would need to do would be change which of the keys $SSH_IDENTITYFILE pointed to.
--
Pro-tip: you'll also want to set "ControlPath none" and "IdentitiesOnly yes" for "Host github.com".
You can't create an SSH key with select role permissions like you can with a Personal Access Token. But you do need a PAT to use the API. So you can either have one PAT + one SSH key, or just use one PAT and no SSH key. (Or multiple PATs, for fine-grained access control)
If you use multiple SSH keys in GitHub (which you should be, to access different things) then you have to manually juggle which SSH key you're passing when you pull each repo, because GitHub will just take the first SSH key you have in your ssh-agent that has an account in GitHub. You won't know from looking at a Git URI ("ssh://git@github.com") which one is needed. OTOH, with PAT, you can either make a URL like ("https://user@github.com") to pre-specify which user to use, or use "https://github.com" and specify user and PAT at auth time.
Authentication using SSH requires first accepting the host keys of Github.com, which can rotate, so you have to decide if you're going to bake the host keys into a container, or require a user to accept them (and know when they change if it's a real GitHub key change or a hacker). Or ignore host keys and lose all the security of SSH encryption. The alternative, HTTPS + PAT, requires no such operations, carries less risk, and is less work to implement.
And of course some networks block port 22.
A mistake lots of people make in this case though is they don't set IdentitiesOnly (in OpenSSH). IdentitiesOnly tells SSH that even if it knows how to authenticate as, say, 'me', if you've told it to authenticate as 'employee' in a particular configuration it should insist on only authenticating as 'employee' never 'me'. If you don't do that you can get confusing behaviour (and of course a privacy hole) on GitHub if your SSH agent knows your 'me' credentials and you try to use an account set to 'employee' credentials, as it uses the wrong ones.
The ssh-keygen manpage has a section under the heading CERTIFICATES that describes the permissions that are configurable when generating the certificate (though those permissions are ssh specific as opposed to the permissions for API access).
1. your private key requires a passphrase to decrypt
or
2. Github could be configured to require both the private ssh key as well as a username and password to authenticate