otp/README.md

110 lines
2.2 KiB
Markdown
Raw Permalink Normal View History

2015-11-28 15:26:18 +00:00
# otp
2016-01-10 23:03:04 +00:00
Go library for generating and using One Time Passwords. Supports both HOTP ([RFC4226](https://tools.ietf.org/html/rfc4226)) and TOTP ([RFC6238](https://tools.ietf.org/html/rfc6238)). Can be used for both server and client roles.
[![GoDoc](https://godoc.org/dev.justinjudd.org/justin/otp?status.svg)](https://godoc.org/dev.justinjudd.org/justin/otp)
## Examples
### OTP Server
```go
import (
"dev.justinjudd.org/justin/otp"
)
2016-01-10 23:03:04 +00:00
var Issuer = "example.com"
2016-01-10 23:03:04 +00:00
func CreateKeyForUser(user string) {
2016-01-10 23:03:04 +00:00
opts := otp.NewHOTPKeyOptions()
opts.Issuer = Issuer
opts.Label = user
key := otp.NewHOTPKey(opts)
2016-01-10 23:03:04 +00:00
keyURL := key.URL()
Store(user, keyURL)
2016-01-10 23:03:04 +00:00
// Provide the URL to the customer so they can include it in their 2FA client.
// Can email URL, or present QR code encoding of the URL
}
2016-01-10 23:03:04 +00:00
// Store this string variable in your database
func Store(user, url string) {
2016-01-11 00:56:15 +00:00
}
2016-01-11 00:56:15 +00:00
// Retrieve the url string variable from your database
func GetURL(user string) string {
return ""
}
2016-01-11 00:56:15 +00:00
func CheckUsersCode(user string, code string) (bool, error) {
keyURL := GetURL(user)
2016-01-10 23:03:04 +00:00
key, err := otp.FromURL(keyURL)
if err != nil {
return false, err
}
2016-01-10 23:03:04 +00:00
// Ensure you are using the correct key
if key.Label() != user {
return false, nil
}
2016-01-10 23:03:04 +00:00
success := key.Verify(code)
2016-01-10 23:03:04 +00:00
// Counter has been updated, update this info in the database
// Don't need this step for TOTP keys as the counter is time-based
keyURL = key.URL()
2016-01-10 23:03:04 +00:00
return success, nil
2016-01-10 23:03:04 +00:00
}
```
2016-01-10 23:03:04 +00:00
2016-01-11 00:56:15 +00:00
2016-01-10 23:03:04 +00:00
### OTP Client
```go
import (
"dev.justinjudd.org/justin/otp"
)
2016-01-10 23:03:04 +00:00
// Just an example for storing OTP keys on the client
var keys map[Key]string
2016-01-10 23:03:04 +00:00
// Key is used as keys for the otp key storing map
type Key struct {
Issuer, Label string
}
2016-01-10 23:03:04 +00:00
func GetCode(issuer, username string) (string, error) {
2016-01-10 23:03:04 +00:00
mapKey := Key{issuer, username}
2016-01-10 23:03:04 +00:00
// Get the stored Key URL
keyURL, ok := keys[mapKey]
if !ok {
return "", nil
}
2016-01-10 23:03:04 +00:00
// Build the key from the URL
key, err := otp.FromURL(keyURL)
if err != nil {
return "", err
}
2016-01-10 23:03:04 +00:00
// Verify Issuer and Label are correct
if key.Issuer() != issuer || key.Label() != username {
return "", nil
}
2016-01-10 23:03:04 +00:00
code := key.OTP()
2016-01-10 23:03:04 +00:00
// If using HOTP, than need to save the state
keyURL = key.URL()
keys[mapKey]= keyURL
2016-01-10 23:03:04 +00:00
return code, nil
}
```