How to cache Yubikey/U2F credentials when authenticating over SSH (specifically Git)

gitgithubsshtwo-factor-authentication

I've set up my GitHub account to use U2F using Yubikey (all over SSH) but as I also use a Git bash prompt, so every time I use my terminal, I'm prompted to touch my security key.

I don't quite understand the relationship between SSH credentials, the key and the FIDO U2F standard, so I'm unsure how to set up my environment to stop prompting me every time I use my terminal.

Can I configure it to only ask, say once a day, or once per session or something?

Best Answer

  • First of all, U2F is uncacheable by design. It's not simply a password; it's a challenge/response protocol, in which the token receives a different 'challenge' every time, and issues digital signatures without ever revealing its secret keys to the PC (basically like a smartcard). That's where its main strength lies.

    The same applies to Yubikey's classic one-time passwords. As the name says, they're one-time, and the server will never accept the same password more than once, nor any password older than an already accepted one.

    That being said, there's two things you can do:

    • First, figure out what is asking you for the credentials, because it's definitely not SSH. The U2F support patches haven't been merged into OpenSSH yet, and ssh git@github.com has never asked for any interactive input – it only ever uses SSH keypairs, not password+2fa.

      Similarly, if you're actually pushing over HTTPS and not SSH, there's still no U2F integration in the HTTP authentication as far as I know, so at most you'd be asked for the 6-digit code.

      If you have a full-sized Yubikey, check whether its light is blinking when prompted. It only blinks when waiting for U2F confirmation – if it's steady, it'll send a classic one-time-password instead. And if you can see the Yubikey typing in a long password, that's not U2F.

    • Second, for SSH in general, you can enable OpenSSH's connection caching / multiplexing feature. After you log in to a server, OpenSSH will keep that connection alive for several minutes even after you close the remote shell (i.e. even after Git finishes its transfers).

      To do that, put the following in your ~/.ssh/config:

      Host *
          ControlMaster auto
          ControlPath ~/.ssh/S.%r@%h:%p
          ControlPersist 5m
      

      (Older OpenSSH versions don't support ControlPersist, so you can keep the other two options but you'll need to start the connection manually with ssh -fNM git@github.com.)