Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Usage
`gotp` encrypts tokens with one or more GPG key. Keys can be specified with either
a key's 20-byte fingerprint or with the email associated with the key.

### Enrolling
Enrolling a token is simple. The enroll command takes several parameters:
* `--token`: the name of the token being enrolled (ex: `github`, `dropbox`)
* `--emails`: a comma-separated list of emails identifying GPG keys. The first matching GPG key is used; if in doubt, specify using the key's fingerprint. (ex: `me@company.com,coworker@company.com`)
Expand All @@ -47,14 +48,17 @@ Mon Jul 10 14:26:49 PDT 2017
another-service: 961126
```

To view the value of an HOTP token, use `increment`. This also increments the counter by one:
### HOTP
After enrolling a token as shown above, the current token value can be shown with `increment`.
This also increments the counter by one:

```
$ gotp increment -t hotp-token
Wed Apr 12 12:27:06 PDT 2017
hotp-token: 535293
```

### Deleting
To delete a token:

```
Expand All @@ -67,6 +71,30 @@ Token deleted successfully!
If you wish to remove without prompting, the `--force/-f` parameter removes this check.
The delete command simply removes the directory `$HOME/.otptokens/[tokenname]`.

Serving over HTTP
-----------------
`gotp` comes with an HTTP server. It is designed for using behind some kind of auth proxy
(such as [oauth2_proxy](https://github.com/bitly/oauth2_proxy)) By serving tokens
over authenticated HTTP, a team of people can make use of two-factor authentication
on a shared account *and* revoke access to individuals, without needing to rotate the secret.

To start the HTTP server:
```
$ gotp serve
2017/07/14 16:11:23 Starting HTTP server...
```

In a separate terminal window:
```
$ curl http://localhost:8080/tokens/my-fav-service
279790
```

**Note:** because `gotp` prompts for the GPG key upon attempted decryption of a token,
it will either be necessary to set `gpg-agent` to never forget the key password, or
to use an unencrypted GPG key.

**TODO:** Verify that it doesn't prompt if you use an unecrypted key.

Generating Testing Tokens
-------------------------
Expand Down
54 changes: 54 additions & 0 deletions cmd/serve.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package cmd

import (
"fmt"
"log"
"net/http"

"github.com/gorilla/mux"
otp "github.com/hgfischer/go-otp"
"github.com/spf13/cobra"
"github.com/tschuy/gotp/token"
)

func TokenHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
tkName := vars["token"]
tk, err := token.ReadToken(tkName)
if err != nil {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "token not found\n")
return
}
totp := &otp.TOTP{Secret: tk.Token, IsBase32Secret: true}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, totp.Get())
}

var serveCmd = &cobra.Command{
Use: "serve",
Short: "Start an HTTP server on port 8080 sharing tokens",
Long: `Start an HTTP server on port 8080 sharing TOTP tokens.

To get a token: curl http://localhost:8080/tokens/{name}

Intended usage: Add an auth proxy on top of the service. Two factor
tokens can then be shared between members of a team without giving the
token secret to each individual.
`,
Run: func(cmd *cobra.Command, args []string) {
r := mux.NewRouter()
r.HandleFunc("/tokens/{token}", TokenHandler)
http.Handle("/", r)

log.Print("Starting HTTP server...")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal(err)
}
},
}

func init() {
RootCmd.AddCommand(serveCmd)
}