For some time I've been using a hand-rolled solution for touchID over ssh which I previously blogged about. Up until recently it's been a somewhat loosely-compiled scattering of config that wasn't really in a releasable form but with a pending security talk on the horizon I thought it would be worth tidying it up and making it releasable so I could mention it in my talk. That code can be found here: https://github.com/m4rkw/touchid-remote However when I was compiling it I was under the impression that one of the tools it relies on - touch2sudo - was merely a standalone binary for authenticating sudo commands locally. I didn't realise that the author had also noted in the README that it's possible to use it over SSH. The solution presented there involves forwarding the local ssh agent over the SSH connection and then configuring touch2sudo as the askpass agent. This is cool and has some advantages over my solution - there are no static secrets that need to be configured and no local server daemon that needs to be running locally. It got me thinking though, for a while I've been using Secretive for ssh keys - https://github.com/maxgoedjen/secretive. This lets you create ssh keys in the mac's secure enclave so the private key cannot be extracted. When you create such a key you can optionally choose to require touchID authentication with it. I wondered if I could perhaps use this instead of touch2sudo for a simpler solution that required less config and no local server daemon. The pam_ssh_auth_agent PAM module is available for Debian distributions but the version that came with my machines was 0.10.3 which segfaults when used with keys from the secure enclave. 0.10.4 also seems to do this but the latest code on github works. Here's the setup process. 1) Compile and install pam_ssh_agent_auth on your target machines: $ git clone https://github.com/jbeverly/pam_ssh_agent_auth $ cd pam_ssh_agent_auth $ git submodule init $ git submodule update $ ./configure --without-openssl-header-check # this flag was necessary for me $ make $ sudo make install 2) Add this line to your sudoers file: Defaults env_keep += SSH_AUTH_SOCK 3) Enable the module in /etc/pam.d/sudo: auth sufficient /usr/local/libexec/pam_ssh_agent_auth.so file=/etc/ssh/sudo_authorized_keys/%u 4) Create the authorized_keys file with the public key from Secretive, this should be set to require touchID and the file should be root-owned and mode 0600. 5) Configure the local ssh connection in ~/.ssh/config: Host myserver Hostname myserver.mydomain.com IdentityAgent ~/Library/Containers/com.maxgoedjen.Secretive.SecretAgent/Data/socket.ssh ForwardAgent yes Now connect to the machine and execute sudo, you should get a touchID prompt from Secretive asking you to authenticate. This is very cool and doesn't require touch2sudo at all, everything is done by the Secretive agent. It's important to understand the security implications of forwarding your local agent to the remote server. An adversary that manages to gain access to the forwarded socket on the remote machine can attempt to make use of any keys that are held on the agent which could potentially be used to access other machines that accept those keys. To mitigate this it's worth making sure that all of your keys in Secretive are set to require touchID so they can't be silently used without your awareness. Another really cool thing you can do with this approach is to delegate a key on your iOS device as having sudo access as well. For example if you create a new ssh key in your SSH client on iOS, add it to the authorized_keys file specified above and enable agent forwarding on the connection you can then invoke sudo and it will use the key from the agent to authenticate sudo - passwordless and without any prompt. Because iOS devices are inherently very secure this is a reasonable tradeoff - my SSH client (Shelly) requires faceID when it loads. Prevously I was using the Duo PAM module to authenticate sudo over SSH when connecting from my iOS device but this new method is much quicker and easier as there's no confirmation step.