Updating some of the examples.

This commit is contained in:
Justin Judd 2016-01-11 09:56:15 +09:00
parent 01fd3e5886
commit 395d932f93
4 changed files with 159 additions and 14 deletions

View File

@ -21,16 +21,25 @@ Go library for generating and using One Time Passwords. Supports both HOTP ([RFC
opts.Label = user opts.Label = user
key := otp.NewHOTPKey(opts) key := otp.NewHOTPKey(opts)
// Store this string variable in your database
keyURL := key.URL() keyURL := key.URL()
Store(user, keyURL)
// Provide the URL to the customer so they can include it in their 2FA client. // 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 // Can email URL, or present QR code encoding of the URL
} }
// Store this string variable in your database
func Store(user, url string) {
}
// Retrieve the url string variable from your database
func GetURL(user string) string {
return ""
}
func CheckUsersCode(user string, code string) (bool, error) { func CheckUsersCode(user string, code string) (bool, error) {
// Retrieve this string variable from your database keyURL := GetURL(user)
var keyURL string
key, err := otp.FromURL(keyURL) key, err := otp.FromURL(keyURL)
if err != nil { if err != nil {
@ -38,7 +47,7 @@ Go library for generating and using One Time Passwords. Supports both HOTP ([RFC
} }
// Ensure you are using the correct key // Ensure you are using the correct key
if key.Label != user { if key.Label() != user {
return false, nil return false, nil
} }
@ -48,11 +57,11 @@ Go library for generating and using One Time Passwords. Supports both HOTP ([RFC
// Don't need this step for TOTP keys as the counter is time-based // Don't need this step for TOTP keys as the counter is time-based
keyURL = key.URL() keyURL = key.URL()
return success, nil
return success
} }
### OTP Client ### OTP Client
import ( import (
@ -85,7 +94,7 @@ Go library for generating and using One Time Passwords. Supports both HOTP ([RFC
} }
// Verify Issuer and Label are correct // Verify Issuer and Label are correct
if key.Issuer != issuer || key.Label != username { if key.Issuer() != issuer || key.Label() != username {
return "", nil return "", nil
} }

View File

@ -0,0 +1,58 @@
package otp_test
import (
"fmt"
"dev.justinjudd.org/justin/otp"
)
// Just an example for storing OTP keys on the client
var keys map[Key]string
// Key is used as keys for the otp key storing map
type Key struct {
Issuer, Label string
}
func GetCode(issuer, username string) (string, error) {
mapKey := Key{issuer, username}
// Get the stored Key URL
keyURL, ok := keys[mapKey]
if !ok {
return "", nil
}
// Build the key from the URL
key, err := otp.FromURL(keyURL)
if err != nil {
return "", err
}
// Verify Issuer and Label are correct
if key.Issuer() != issuer || key.Label() != username {
return "", nil
}
code := key.OTP()
// If using HOTP, than need to save the state
keyURL = key.URL()
keys[mapKey] = keyURL
return code, nil
}
func Example_hOTPClient() {
issuer := "example.com"
username := "username"
code, err := GetCode(issuer, username)
if err != nil {
// Handle error
}
// Present code to user, or send code to server
fmt.Println(code)
}

View File

@ -6,15 +6,15 @@ import (
"dev.justinjudd.org/justin/otp" "dev.justinjudd.org/justin/otp"
) )
type Key struct { type MapKey struct {
Issuer, Label string Issuer, Label string
} }
var keys map[Key]string var keysMap map[MapKey]string
func CreateKey(issuer, username string) error { func CreateKey(issuer, username string) error {
mapKey := Key{issuer, username} mapKey := MapKey{issuer, username}
_, ok := keys[mapKey] _, ok := keysMap[mapKey]
if ok { if ok {
return fmt.Errorf("Key already exists for Issuer:%s, Label:%s", issuer, username) return fmt.Errorf("Key already exists for Issuer:%s, Label:%s", issuer, username)
} }
@ -23,14 +23,14 @@ func CreateKey(issuer, username string) error {
opts.Label = username opts.Label = username
k := otp.NewHOTPKey(opts) k := otp.NewHOTPKey(opts)
keys[mapKey] = k.URL() keysMap[mapKey] = k.URL()
return nil return nil
} }
func CheckCode(issuer, username, code string) bool { func CheckCode(issuer, username, code string) bool {
mapKey := Key{issuer, username} mapKey := MapKey{issuer, username}
keyURL, ok := keys[mapKey] keyURL, ok := keysMap[mapKey]
if !ok { if !ok {
return false return false
} }

View File

@ -0,0 +1,78 @@
package otp_test
import (
"dev.justinjudd.org/justin/otp"
)
var Issuer = "example.com"
func CreateKeyForUser(user string) {
opts := otp.NewHOTPKeyOptions()
opts.Issuer = Issuer
opts.Label = user
key := otp.NewHOTPKey(opts)
keyURL := key.URL()
Store(user, keyURL)
// 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
}
// Store this string variable in your database
func Store(user, url string) {
}
// Retrieve the url string variable from your database
func GetURL(user string) string {
return ""
}
// get the OTP code from the user
func getCode() string {
return ""
}
func CheckUsersCode(user string, code string) (bool, error) {
keyURL := GetURL(user)
key, err := otp.FromURL(keyURL)
if err != nil {
return false, err
}
// Ensure you are using the correct key
if key.Label() != user {
return false, nil
}
success := key.Verify(code)
// 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()
return success, nil
}
func Example_hOTPServer() {
// Create new user
user := "username"
CreateKeyForUser(user)
// When user is authenticating
// Perform password based auth - if that is successful, then continue
code := getCode()
success, err := CheckUsersCode(user, code)
if err != nil {
// Handle error
}
if success {
// User is authenticated
}
}