Skip to content

Commit

Permalink
Merge pull request #20 from dcreemer/dzc/support-2fa
Browse files Browse the repository at this point in the history
use expect for 'op' interaction; test for 2fa prompt
  • Loading branch information
dcreemer authored Apr 12, 2019
2 parents 06c834a + 0b27c1d commit 93e14d8
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 8 deletions.
44 changes: 38 additions & 6 deletions 1pass
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
set -e
set -o pipefail

VERSION="1.0.1"
VERSION="1.1"

if [ "$XDG_CONFIG_HOME" != "" ] && [ ! -d "${HOME}/.1pass" ]; then
op_dir="${XDG_CONFIG_HOME}/1pass"
Expand Down Expand Up @@ -127,26 +127,56 @@ With no arguments, prints a list of all Logins and Passwords in all 1Password va
With a single argument, fetches the Item (Login, Password, or TOTP) matching the
given name, and copies the resulting password to the clipboard.
With two arguments, fetches the specified field (e.g.) "usernmae" from the named
With two arguments, fetches the specified field (e.g.) "username" from the named
item, and copies the results to the clipboard.
USAGE
}

sanity_check()
{
for cmd in "op" "jq" "gpg" "expect"
do
if [ $verbose -eq 1 ]; then
echo "checking for $cmd"
fi
if [ ! -x "`which $cmd`" ]; then
echo "Cannot find the '$cmd' command. Please make sure it is installed"
exit 1
fi
done
}

signin()
{
local pw=$(gpg -d -q $master)
local se=$(gpg -d -q $secret)
if [ $verbose -eq 1 ]; then
echo "signing in to ${domain} $email"
fi
local token=$(echo -n "${pw}" | op signin --output=raw ${domain} $email $se || echo -n "_fail_")
if [ "$token" == "_fail_" ]; then
local script="
spawn op signin ${domain} ${email} ${se}
expect \"${domain}:\"
send \"${pw}\n\"
expect {
\"Enter your six-digit authentication code:\" {
puts -nonewline stderr \"Enter your six-digit authentication code: \"
flush stderr
interact -o \"\r\" return
puts stderr \"\"
exp_continue
}
eof
}
"
local output0=$(expect -c "${script}")
local output=$(echo "${output0}" | grep "export" || echo -n "_fail_")
if [ "$output" == "_fail_" ]; then
echo "1pass failed to signin to ${domain}"
exit 1
fi
# extract token from 'export OP_SESSION_domain="asdsad"'
local token=$(expr "${output}" : '.*="\(.*\)"')
echo -n "${token}" | gpg -qe --batch -r $self_key > $session
# also export it in case we use the op command in the shell:
export $OP_SESSION_NAME=$token
}

init_session()
Expand Down Expand Up @@ -363,6 +393,8 @@ done

shift $((OPTIND-1))

sanity_check

if [ $# -eq 0 ]; then
list_items
elif [ $# -eq 1 ]; then
Expand Down
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
**1pass** is a caching wrapper for the [1Password
CLI](https://support.1password.com/command-line-getting-started/) `op`.

## UPGRADE NOTE

Upgrading to version 1.1 requires installation of the
[expect](https://core.tcl.tk/expect/index) tool. `1pass` will check for this (and
other) dependencies and remind you to install them.

## Introduction

**1pass** is designed to make using your 1Password usernames and passwords quick and easy. It is
Expand Down Expand Up @@ -34,11 +40,14 @@ Together these features enable easy use of 1Password-stored credentials.
## Installation

First make sure that the `op` [1Password
CLI](https://support.1password.com/command-line-getting-started/) and the `jq` [JQ](https://stedolan.github.io/jq) are installed. If you use homebrew cask on Mac OS X, this works well:
CLI](https://support.1password.com/command-line-getting-started/) and the `jq`
[JQ](https://stedolan.github.io/jq) and
[expect](https://core.tcl.tk/expect/index) requirements are installed. If you use
homebrew cask on Mac OS X, this works well:

```sh
$ brew cask install 1password-cli
$ brew install jq
$ brew install jq expect
```

Copy the 1pass executable file to a suitable location on your PATH (for example, /usr/local/bin)
Expand Down Expand Up @@ -167,6 +176,8 @@ $ 1pass -p MyBankAccount pin

**1pass** has special support for TOTP fields -- these are fetched directly via `op`
rather than a local cache. (Thanks to (@ev0rtex)[https://github.com/ev0rtex]).
Note that this **is different** from using TOTP 2FA to log into your 1Password
account (that is supported too -- see below)

```sh
$ 1pass -p MyBankAccount totp
Expand Down Expand Up @@ -197,6 +208,14 @@ from the online 1Password vault.
Similarly, 1Password CLI sessions last for 30 minutes from the time of last use. **1pass** will
manage the session for you, and refresh it as needed.

## 2FA for 1Password

If you have turned on two-factor authentication (2FA) support for your 1Password
account, then 1pass will prompt for you to enter a TOTP code when creating a
session. Currently, you will need to re-enter this code after every session
expiration (30 minutes of inactivity). Unfortunately this makes using 1pass in
non-interactive scripts less useful.

## License

Copyright (c) 2017, David Creemer (twitter: [@dcreemer](https://twitter.com/dcreemer)) with some
Expand Down

0 comments on commit 93e14d8

Please sign in to comment.