YubiKey TOTP to clipboard

generates totp codes using YubiKey and copy to clipboard, supports touch and touchless code generation

Image preview of YubiKey TOTP to clipboard plugin.

Yubikey.30m.sh

Edit
Open on GitHub
#!/bin/bash
#
# <xbar.title>YubiKey TOTP to clipboard</xbar.title>
# <xbar.version>v1.0</xbar.version>
# <xbar.author>jebabin</xbar.author>
# <xbar.author.github>jebabin</xbar.author.github>
# <xbar.image>https://i.imgur.com/F1zHc17.png</xbar.image>
# <xbar.desc>generates totp codes using YubiKey and copy to clipboard, supports touch and touchless code generation</xbar.desc>
# <xbar.dependencies>bash,perl</xbar.dependencies>
# <xbar.version>1.2</xbar.version>

# <xbar.var>string(VAR_YKMAN): Path to the ykman binary (optional).</xbar.var>

# v1.2
# Better handle ykman return code
# Now automatically create and update the .b64 image when a .png, .jpg, etc.. exist in YubiKey directory for the issuer.
# Directory changed from Yubikey to YubiKey (uppercase K)
# You can set http link to open for each issue with the `defaults write com.xbarapp.plugins.yubikey "issuer" "https://..."` command in terminal

# v1.1
# Put the menu bar icon un green when YubiKey is present
# Put a message when YubiKey need to be inserted
# Remove temporary file
# Add a variable to set ykman path and try to auto detect if not set
# If a file with <issuer name>.b64 (an image file encoded as base64 - height of 32px recommended) is present in YubiKey (uppercase Y and K!) subdirectory, it will be displayed in the menu)

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

if [ ! -x "$VAR_YKMAN" ]; then
	if [ -x "/Applications/YubiKey Manager.app/Contents/MacOS/ykman" ]; then
		VAR_YKMAN="/Applications/YubiKey Manager.app/Contents/MacOS/ykman"
	else
		VAR_YKMAN=ykman
	fi
fi

if [ $# -eq 3 ] && [ "$1" = "copy" ]; then
	if [ "$3" -eq 1 ]; then
		osascript -e "display notification \"You need to touch your YubiKey to get the code\" with title \"$2\"" &> /dev/null
	fi
	code=$("$VAR_YKMAN" oath code "$2" | sed 's/.*[[:space:]]//')
	if [ "$code" -ge 0 ]; then
		echo -n "$code" | pbcopy
		osascript -e "display notification \" $code copied to clipboard\" with title \"$2\"" &> /dev/null
	else
		osascript -e "display notification \" $code You were too long to touch the key, please retry\" with title \"$2\"" &> /dev/null
	fi
	exit
else

	tmpfile=$(mktemp)

	if [ -d "YubiKey" ]; then
		cd "YubiKey" || exit
		for file in *; do
			extension="${file##*.}"
			filename="${file%.*}"
			if [ "$extension" != "b64" ]; then
				if [ -f "$filename.b64" ]; then
					if [ "$file" -nt "$filename.b64" ]; then
#						echo "$file is newer than the b64, updating b64 file" >> "$tmpfile"
						base64 < "$file" > "$filename.b64"
					fi
				else
#					echo "no b64 file for $file, creating b64 file" >> "$tmpfile"
					base64 < "$file" > "$filename.b64"
				fi
			fi
		done
		cd ".."
	fi

	"$VAR_YKMAN" oath code | while read -r line
	do
		parsed=$(echo "${line}" | perl -ne 'm/^([^:]+):(.*?)\s+(\d+|\[Touch Credential\])$/; print sprintf(int($3) ? 0 : 1).";$1 ($2)\n"')
		name=$(echo "${parsed}" | cut -c 3-100)
		needtouch=$(echo "${parsed}" | cut -c 1)
		account=$(echo "${line}" | perl -ne 'm/^(.*?)\s+(\d+|\[Touch Credential\])$/; print $1')
		issuer=$(echo "${line}" | perl -ne 'm/^([^:]+):(.*?)\s+(\d+|\[Touch Credential\])$/; print "$1"')

		addimage=""
		if [ -e "YubiKey/$issuer.b64" ]; then
			addimage="image="$(cat "YubiKey/$issuer.b64")
		fi
		URL=$(defaults read com.xbarapp.plugins.yubikey "$issuer")

		echo "$name | $addimage href=$URL font=Menlo size=13 bash='$0' param1=copy param2=\"$account\" param3=$needtouch terminal=false" >> "$tmpfile"
	done

	color="#008000"
	if [ ! -s "$tmpfile" ]; then
		"$VAR_YKMAN" oath code >> /dev/null
		if [ "$?" -eq 2 ]; then
			echo "Please insert your YubiKey then select this line to refresh | font=Menlo size=13 refresh=true terminal=false" >> "$tmpfile"
		else
			echo "Your YubiKey has probably no OATH entry configured | font=Menlo size=13 terminal=false" >> "$tmpfile"
		fi
		color="black"
	fi 

	echo "y| font=Meiryo size=14 color=$color"
	echo "---"
	cat "$tmpfile"
	rm "$tmpfile"

	exit
fi