I've been building a OAuth2 (and IndieAuth)-based single-sign on system, with the intention of using it as the auth layer for a few things I plan to build for my own use. Along the way, I've been contemplating how I could use the same system for... well... everything. This morning I wondered if I could use it for my own git repositories.

Currently, my git repositories are in GitHub (I oscillate back and forth between self-hosting various things or using other services). I use a ssh key hidden away in a hardware key (Yubikey) for authentication. One downsides of my current setup is that I need somewhat finicky setup (GPG SSH Agent) on any machine that I want to use the key. Another is that that only the most expensive Yubikeys have the ability to run the GPG Applet, I only have the one, and it's not always next to me when I want it. I have a handful of u2f-only security keys, so there's always one nearby.

GitHub's solution appears to be something like Gmail's app passwords. Basically a special password that you use for git operations, presumably each password is only used on a single machine. However, it's still a long-lived credential (floating around a disk in plain text even). Can I do better?

I dig a bit of reading on how Git works over HTTP and came across a config option to pass extra HTTP headers. That would allow me to send an OAuth2 bearer token. So I could put a Git behind an reverse proxy, which could be responsible for checking the access token. Now I just need to make getting and refreshing the access token somewhat convenient.

I recently built a command line tool for getting access tokens from the SSO service. It has two sub-commands: login, which will request or refresh an access token using the OAuth2 device flow, and curl, which will passes the rest of the arguments to curl and adds an authorization header with the current token. I'm thinking of adding a new git-setup command, which would modify my git config with a new block for the git server, with the authorization header in the extraHeaders option. This would be a short-lived credential that would last for a day. Future login commands would update the access token in the config. In a pinch, if I was in an environment where I couldn't use the CLI tool, I could get an access token from the website and pass the token into git.

So the initial setup would look something like this:

  $ sso git-setup https://git.jesterpm.net
Go to https://... and enter code ABCD-EFGH to authorize access.

$ cat ~/.gitconfig
[http "https://git.jesterpm.net"]
    extraHeader = Authorization: Bearer xxxxxx

Then the day-to-day flow would look like:

  $ sso login    # Assuming it hasn't already been done for some other reason
Go to https://... and enter code JKMNP-QRST to authenticate yourself.

$ git push

I think I could arrive at a solution that was even more portable (that didn't need the sso tool to be installed). For example, I could have a hosted shell script so that I run curl https://git.jesterpm.net/login.sh | sh to set everything up, but I really don't find myself trying to access code on random machines much anymore.