Making your (Android) phone remind you when you've forgotten your YubiKey
I use my YubiKey multiple times every day to authenticate to various web sites, so I tend to leave it plugged in. When I use it with a desktop computer I don't carry with me, I run the risk of forgetting it's plugged in and leaving it behind. If I forget it at work and then need it later at home, it's a pain, and vice versa. This project prevents that from happening by warning me if I walk away from my computer with the YubiKey still plugged into it.
The goal is not to prevent me from leaving my YubiKey plugged into some random computer that's not mind that I happen to be using. On computers like that, I only plug in my YubiKey for long enough to authenticate, then put it away. The solution here is for computers you use regularly that you can install software on, since you need to install the software that generates the notifications that make this work.
A different approach to be considered is one of the products, such as this one, that would let you attach a tag to your YubiKey and then detect and warn you when you walk away from it. Personally, I didn't like that option, for a few reasons: the tags are bigger and bulkier than the YubiKey; they use batteries which need to be periodically replaced; and I experimented with using Bluetooth for this purpose and found it to be unreliable. Also, to be honest, this seemed like the kind of problem I could solve myself, so I wanted to try that before paying somebody else to solve it for me.
The computers I use regularly send push notifications to my phone whenever I plug in or unplug my YubiKey.
My phone uses the push notifications to keep track of whether my YubiKey is plugged in.
My phone notices if I start walking around when my YubiKey is plugged in, and warns me quietly.
If I miss the quiet notification and walk a little farther, my phone generates a more urgent warning that's much harder to miss.
The moving parts
A shell script deployed to my computers sends the push notifications.
The shell script is triggered by a udev rule that fires when the YubiKey is plugged in or unplugged, and also by a systemd timer that runs a systemd service every 60 seconds as a backstop in the unlikely event the udev rule doesn't work.
IFTTT vs. Pushover
IFTTT is free, whereas Pushover will cost you $4.99 for the Android app after a 7-day free trial.
Pushover is slightly easier to set up than IFTTT, but both are equally easy to use once they're set up.
Pushover is much more reliable than IFTTT. Pushover almost always delivers notifications in just a few seconds, whereas IFTTT notifications can take several minutes to arrive (For the curious: this is because Pushover uses Google's FCM to reliably push notifications, whereas the IFTTT app uses periodic polling to check for notifications, and the polling is especially unreliable when Android decides to doze your phone.)
I started out using IFTTT, but I eventually decided that the frequent notification delays were intolerable, so I've switched to using Pushover. The code here supports either.
You can use both IFTTT and Pushover for notifications if you want redundancy to protect against one of the services being in the midst of an outage when you plug in or unplug your YubiKey.
Setting up IFTTT
Register for an IFTTT account if you don't already have one.
Install the IFTTT app on your phone and log in.
On the IFTTT web site, set up a new applet as follows:
- For "this", select "Webhooks" and then "Receive a web request".
- Enter "yubikey_plugged_in" as the event name.
- For "that", select "Notifications" and then "Send a notification from the IFTTT app".
- For the message, enter "YubiKey is plugged in".
Set up another applet as described above, but this time use "yubikey_unplugged" as the event name and "YubiKey is not plugged in" as the message.
Go to your Webhooks settings and copy your maker key (the random string at the end of your Webhooks URL); you'll need it later.
Setting up Pushover
Register for a Pushover account if you don't already have one.
Install the Pushover app on your phone and log in.
Save your user key, which is prominently displayed on the Pushover home page after you log in, for later.
Create a new Pushover Application and save its API token for later.
How to deploy on your computer
yubikey-monitor.shand set the
both. The default is
pushoversince that's what I use.
Copy the script to
/usr/local/binand make sure it's executable.
If you're using IFTTT, then create the file
/root/.ifttt_maker_keyand put the maker key which you saved above into it.
If you're using Pushover, then create the file
/root/.pushover_keysand put your API token and user key (in that order) on the first two lines of the file.
Plug in your YubiKey and then run
/usr/local/bin/yubikey-monitor.sh(as root). You should get two "YubiKey is plugged in" notifications on your phone if you're using just IFTTT or just Pushover, or four notification if you're using both. The notifications should come within ten seconds or so if you're using Pushover; they could take several minutes with IFTTt.
Unplug your YubiKey and run the script again and you should get either two or four "YubiKey is not plugged in" notifications.
udevadm control --reload.
Plug in your YubiKey and you should get the notifications without running the script by hand, since the udev rule should run it automatically.
Ditto when you unplug the YubiKey.
You can deploy the tool as described above on as many computers as you would like. You won't get notified about walking away from a computer with your YubiKey plugged into it unless you've deployed the tool on that computer!
How to deploy on your phone
Install AutoNotification. You'll have to pay a couple of bucks for it after the 7-day free trial, but you can try it out first to make sure it's doing what you want and expect.
Copy YubiKey_Plugged_In.prf.xml, YubiKey_Unplugged.prf.xml, YubiKey_Soft_Reminder.prf.xml, and YubiKey_Loud_Reminder.prf.xml to your phone and import them into Tasker by tapping "Profiles" and selecting "Import Profile" for each one.
Enable the four profiles and tap the checkmark at the top to put the changes into effect.
Plug in your YubiKey and confirm that either you don't see the notification on your phone, or it disappears shortly after it appears, indicating that AutoNotification intercepted and removed it.
In Tasker, tap "Vars" and confirm that the
YUBIKEYvariable is set to
Get up and walk around, and within 10-20 steps you should get a notification on your phone telling you not to forget your YubiKey.
Keep walking, and within 10-20 more steps your phone should vibrate and beep loudly.
Unplug your YubiKey, and confirm that the "Don't Forget Your YubiKey" notification is dismissed automatically.
At this point you can tweak the Tasker profiles and tasks as desired to behave differently, if you wish.
Can I use this for something other than a YubiKey?
With minimal modifications, you should be able to use this code for
any removable device, USB or otherwise, that generates
when it is connected to and disconnected from your computer. You could
even get away without the
udev events and rely exclusively on the
systemd timer if you can figure out code to put in the shell script
in place of
usb-devices | grep -q -s -i -w yubikey to determine
whether the device is currently plugged in.
The things you would need to modify to generalize this to another device are:
as noted above, the code in the shell script that determines whether the device is plugged in;
in the shell script and in your IFTTT applet, the names of the plug and unplug events used in IFTTT;
in the shell script and in your IFTTT applet, the text of the notification that gets sent when the device is plugged in or unplugged;
the `systemd service and timer names and descriptions;
the name of the shell script, though it doesn't have any functional relevance so if you don't want to bother you can just leave it; and
if you're going to still use
udev, the vendor ID in the rules file, and you may want to add additional attributes to the rule to make it more selective.
I am happy to accept pull requests to make the code more generalized and extensible.
Copyright 2019 Jonathan Kamens
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.