How I remember my YubiKey

By | August 15, 2018

I’ve recently started using a YubiKey NEO for two-factor authentication for sites that support it.1

Because I am using my YubiKey for more and more sites, I tend to leave it plugged in whenever I am in front of a computer for an extended period of time. The first day I was using the key it became clear that this was going to be a problem, when I left it plugged into my computer at work and didn’t realize it until I’d gotten home. Yes, new technology leads to new problems, but problems that are created by technology can be solved by technology too. Here’s how I solved the “Don’t forget your YubiKey at work” problem.2

The Android Tasker app allows you to create automated workflows for a huge array of triggers, actions, and tasks. For example, you can turn on WiFi automatically when you get home (location-based trigger), generate a special alert when you receive a text message from a specific sender, and on and on; the possibilities are quite overwhelming. To solve this particular problem, I took advantage of Tasker’s “BT Near” trigger, which can be used to detect when a BlueTooth device matching specified criteria is within range of my phone.

High-level summary

At the most basic level, I tell Tasker to pay attention to whether I am near one of the computers that I plug my YubiKey into by watching for their BlueTooth interfaces, and to alert me when I walk away from one of them.

But that’s not quite enough. If I left it at that, then my phone would alert me whenever I walked away from my computer, regardless of whether my YubiKey was actually plugged into it, and that would be really annoying. So I also have my computers paying attention to whether my YubiKey is plugged in and setting a flag when it is that Tasker can check, so that Tasker only bothers me when I actually forget to take it with me.

To make this effective, I have Tasker checking for nearby BlueTooth devices more often than the default, so it notices when I’ve left my YubiKey behind quickly enough that I haven’t already left my house or office building. I’ve also increased the amount of time Tasker waits for BlueTooth devices to announce themselves each time it checks for them, because the default is too short and causes frequent false positives.

What follows are more detailed descriptions of the various components of this solution.

BlueTooth check timing

I’ve adjusted the default Tasker Preferences as follows to make BlueTooth device detection faster and more reliable:

  • On the “UI” tab of the Preferences, uncheck “Beginner Mode” (otherwise, I can’t see all of the preferences I need to adjust)
  • On the “Monitor” tab of the Preferences:
    • Under “Display On Monitoring”, change “BT Scan Seconds” to 35
    • Under “Display Off Monitoring”:
      • Change “All Checks Seconds” to 40
      • Change “Timeout Seconds” to 35
      • Check “Use Motion Detection” (otherwise Tasker’s BlueTooth checks when your screen is off will consume a lot more battery)
    • Under “General Monitoring”, change “BT Minimum Timeout Seconds” to 20

Even with these changes to the Preferences, I find that the Tasker Profile for this alert regularly “bounces,” i.e., decides that I am no longer near my computer and then changes its mind a few seconds later and decides that I am, when I’ve never moved. This appears to be due to a bug / deficiency in Tasker which many of its users encounter. I’ve employed a commonly recommended “de-bouncing” workaround for this, described below.

Proximity detection and alerting

Here’s what my profile for this problem looks like. How to create a profile like this within Tasker is left as an exercise to the reader; play around with Tasker or consult its user guide for assistance. I will, however, offer two tips:

  1. You need to name the profile after you create it because one of the actions within the exit task refers to the profile name; to do that, long-tap on the profile after creating it and then tap the little “A” icon that comes up to give it a name.
  2. When you make changes to your profiles, Tasker doesn’t actually apply the changes unless you exit from the app using the back arrow or tap the checkmark that shows up at the top of the main screen when there are unapplied changes. Don’t fall into the trap of scratching your head, wondering why the changes you made aren’t doing anything, when it’s because you haven’t actually applied them.

Note that I’ve actually edited out some pieces of the profile (that’s why there are gaps in the numbering) that I’m going to explain below, so you can just see the basic structure of the profile in this initial presentation of it.

Profile: YubiKey Reminder (31)
State: BT Near [ Name:* Address:first computer BlueTooth address/second computer BlueTooth address/… Major Device Class:Any Standard Devices:On Low-Energy (LE) Devices:Off Unpaired Devices:On Toggle BlueTooth:On ]
Enter: Remove YubiKey Reminder (33)
A1: Notify Cancel [ Title:Don’t Forget Your YubiKey Warn Not Exist:Off ]

Exit: Remind Me About YubiKey (30)
Run Both Together
A4: Notify [ Title:Don’t Forget Your YubiKey Text:Don’t Forget Your YubiKey Icon:null Number:0 Permanent:Off Priority:5 ]
A5: Vibrate [ Time:1000 ]
A6: Beep [ Frequency:8000 Duration:500 Amplitude:50 Stream:4 ]

In other words, “Create a profile called ‘YubiKey Reminder’. This profile is active when my phone is near one of my computers. Whenever the profile becomes Inactive, i.e., I walk away from my computer, alert me with a notification, a vibration, and a beep. Whenever the profile becomes active, i.e., I return to my computer, remove the notification if it’s currently being displayed.” You obviously don’t have to use the same notifications I do; use whatever works for you.

Note that search fields in Tasker use “/” as the separator for OR’ing values, so since I list multiple BlueTooth addresses in the “BT Near” state separate by slashes, the state will match if any of the listed addresses is seen nearby. (On Linux, you can use the command hcitool dev to find out your computer’s BlueTooth address. I don’t know how to do this on other operating systems.)

 

Now, concerning the de-bouncing logic I mentioned, here’s the profile again, with the de-bouncing logic added to it, shown in bold:

Profile: YubiKey Reminder (31)
State: BT Near [ Name:* Address:first computer BlueTooth address/second computer BlueTooth address/… Major Device Class:Any Standard Devices:On Low-Energy (LE) Devices:Off Unpaired Devices:On Toggle BlueTooth:On ]
Enter: Remove YubiKey Reminder (33)
A1: Notify Cancel [ Title:Don’t Forget Your YubiKey Warn Not Exist:Off ]

Exit: Remind Me About YubiKey (30)
Run Both Together
A1: Wait [ MS:0 Seconds:10 Minutes:0 Hours:0 Days:0 ]
A2: Stop [ With Error:Off Task: ] If [ %PACTIVE ~ *,YubiKey Reminder,* ]
A4: Notify [ Title:Don’t Forget Your YubiKey Text:Don’t Forget Your YubiKey Icon:null Number:0 Permanent:Off Priority:5 ]
A5: Vibrate [ Time:1000 ]
A6: Beep [ Frequency:8000 Duration:500 Amplitude:50 Stream:4 ]

In other words, “Whenever Tasker thinks I’ve walked away from my computer, wait five seconds and check again, and don’t generate any alerts if Tasker now thinks I’m back at my computer.”

This de-bouncing logic, coupled with the preference values given above, seems to be enough, at least for me, to prevent false alerts. If you find that it isn’t, then either you need to increase the time in the “Wait” action shown above, or you need to increase the value of the “BT Scan Seconds” preference. You can tell which one is necessary by enabling the Run Log and (More | Run Log from the main menu) and checking whether there’s a long (like more than 30 seconds) gap between when the YubiKey Reminder profile goes inactive and when it goes active again. If it’s a long gap, you need to increase the preference; if it’s a gap of less than that, you need to increase the wait time. Note that when you change the preference, you also have to increase the other preferences mentioned above by the same amount, because they are all linked to each other and Tasker won’t let you increase the one without increasing the others.

Is my YubiKey actually plugged in?

You could leave things here, with Tasker reminding you every time you walk away from your computer to take your YubiKey with you. But there’s more fun to be had: what about making it only remind you if your YubiKey is actually plugged in?

My solution to this has three components:

  1. Teach my computers to notice when my YubiKey is plugged in our unplugged and push that information into the cloud in (near) real-time.
  2. Set up a little service in the cloud to accept the information pushes from my computers and make that information available to Tasker.
  3. Teach Tasker to query the service to find out whether my YubiKey is plugged in, and only bother me with alerts if it is.

I run my own virtual server (which I will call “jik-virtual-server” in the examples below, though that’s not its real host name, obviously) with Apache httpd on it, so it was easy for me to create a little service there to track whether my YubiKey is plugged in (I imagine one might also be able to do this with IFTTT, though I haven’t ever actually used it so I’m not certain). I created the CGI script https://jik-virtual-server/~jik/ykp.cgi (“ykp” stands for “YubiKey Plugged”, though obviously you can name it whatever you want) which looks like this:

#!/bin/bash
case "$QUERY_STRING" in
    *add*) touch ~/public_html/ykp ;;
    *remove*) rm -f ~/public_html/ykp ;;
esac

echo "Content-Type: text/plain"
echo

With this script in place, every time someone fetches the URL https://jik-virtual-server/~jik/ykp.cgi?add, the script creates https://jik-virtual-server/~jik/ykp, and every time someone fetches https://jik-virtual-server/~jik/ykp.cgi?remove, it is removed.

Next, how to make my computers notice when my YubiKey is plugged in or unplugged and notify my little service? For this, I tried two different approaches: a udev rule to detect add and remove events for the YubiKey and call a script to notify the service, and a systemd timer and associated service which run a script every five seconds to check whether the YubiKey is plugged in and notify the service as needed.

The udev rule approach turns out to be problematic because, at least on Ubuntu Linux, udev scripts are blocked from using the network, which means the script can’t look up the IP address of my virtual server or fetch the URLs listed above to notify the service of state changes. However, you can use this approach if your Linux distribution doesn’t impose this restriction or if you’re willing to remove it by removing the IPAddressDeny line from /lib/systemd/system/systemd-udevd.service, after which you will need to either reboot or do systemctl daemon-reload and then systemctl restart udev. Once you’ve done that, create /etc/udev/rules.d/50-yubikey.rules with these contents:

ATTRS{idVendor}=="1050", ACTION=="add|remove", RUN+="/usr/local/bin/yubikey-monitor.sh"

And create /usr/local/bin/yubikey-monitor.sh, tweaked to replace my URLs with yours (note that the lockfile command used in this script comes from the procmail package):

#!/bin/bash -e

FLAG=/var/run/yubikey-watcher
ADD_URL='https://jik-virtual-server/~jik/ykp.cgi?add'
REMOVE_URL='https://jik-virtual-server/~jik/ykp.cgi?remove'

trap "rm -f \"$FLAG.lock\"" EXIT
lockfile -1 -l 5 "$FLAG.lock"

# systemd compatibility
if [ ! "$ACTION" ]; then
    if usb-devices 2>/dev/null | grep -q -s -i -w yubikey; then
        ACTION="add"
    else
        ACTION="remove"
    fi
fi

if [ "$ACTION" = "add" ]; then
    if [ ! -f "$FLAG" ]; then
        curl "$ADD_URL"
        touch "$FLAG"
    fi
elif [ -f "$FLAG" ]; then
    curl "$REMOVE_URL"
    rm -f "$FLAG"
fi

If you don’t want to remove the udev restriction to make the udev approach possible, then create /usr/local/bin/yubikey-monitor.sh exactly as above, and also create /etc/systemd/system/yubikey-monitor.service:

[Unit]
Description=Check for inserted Yubikey
ConditionACPower=true 

[Service]
Type=oneshot
ExecStart=/usr/local/bin/yubikey-monitor.sh

And /etc/systemd/system/yubikey-monitor.timer:

[Unit]
Description=Check for inserted Yubikey every 5 seconds

[Timer]
OnStartupSec=60
OnUnitActiveSec=5

[Install]
WantedBy=timers.target

Then do systemctl daemon-reload, systemctl enable yubikey-monitor.timer, and systemctl start yubikey-monitor.timer.

So, now I’ve got my computers notifying my virtual server when my YubiKey is plugged in and my virtual server making that information available for Tasker to use, I need to make Tasker use it. Here’s how the profile looks with that functionality integrated into it (additions in bold):

Profile: YubiKey Reminder (31)
State: BT Near [ Name:* Address:first computer BlueTooth address/second computer BlueTooth address/… Major Device Class:Any Standard Devices:On Low-Energy (LE) Devices:Off Unpaired Devices:On Toggle BlueTooth:On ]
Enter: Remove YubiKey Reminder (33)
A1: Notify Cancel [ Title:Don’t Forget Your YubiKey Warn Not Exist:Off ]

Exit: Remind Me About YubiKey (30)
Run Both Together
A1: Wait [ MS:0 Seconds:5 Minutes:0 Hours:0 Days:0 ]
A2: Stop [ With Error:Off Task: ] If [ %PACTIVE ~ *,YubiKey Reminder,* ]
A3: HTTP Head [ Server:Port:https://jik-virtual-server Path:~jik/ykp Attributes: Cookies: User Agent: Timeout:10 Trust Any Certificate:Off Continue Task After Error:On ]
A4: Notify [ Title:Don’t Forget Your YubiKey Text:Don’t Forget Your YubiKey Icon:null Number:0 Permanent:Off Priority:5 ] If [ %HTTPR eq 200 ]
A5: Vibrate [ Time:1000 ] If [ %HTTPR eq 200 ]
A6: Beep [ Frequency:8000 Duration:500 Amplitude:50 Stream:4 ] If [ %HTTPR eq 200 ]

In other words, “When Tasker decides I’ve walked away from my computer, before alerting me it should check if the URL indicating that my YubiKey is plugged in exists, and only alert me if it does.”

And there you have it. My phone is now loudly alerting me whenever I walk away from my computer and leave my YubiKey behind, and yours can too, assuming that you’re as ridiculously obsessive about stuff like this as I am and willing to take the time to set it up.

Please email me or comment if you found this useful!

P.S. Don’t forget to back up your Tasker configuration (“Data” -> “Backup” from the home screen menu) and save the backup file somewhere off your phone, so you don’t have to rebuild everything if you lose or break it! Note, however, that preferences aren’t saved in the backups, so you’ll have to redo all the timeouts as described above.


1A quick primer, for those of you who are unfamiliar… The YubiKey sends two-factor authentication information to web sites when I either tap the button on the key, when it is plugged into my computer, or tap it on my phone’s NFC sensor, if I’m logging into somewhere on my phone. Furthermore, for sites that support Universal 2nd Factor (U2F) authentication, the YubiKey adds an additional layer of security, confirming the identity of the web site I’m logging into to ensure that I’m not being phished.

2If someone else has already solved this problem and I’m a fool to have wasted my time on it ;-), please feel free to let me know in a comment below. I’m always happy to throw away my own hacks and use somebody else’s instead, if it means one less hack for me to have to maintain.

Print Friendly, PDF & Email
Share

Leave a Reply

Your email address will not be published.