diff --git a/README.md b/README.md index ad833a5..5d165f2 100644 --- a/README.md +++ b/README.md @@ -7,102 +7,103 @@ Go library for generating and using One Time Passwords. Supports both HOTP ([RFC ## Examples ### OTP Server +```go +import ( + "dev.justinjudd.org/justin/otp" +) - import ( - "dev.justinjudd.org/justin/otp" - ) +var Issuer = "example.com" - var Issuer = "example.com" +func CreateKeyForUser(user string) { - func CreateKeyForUser(user string) { + opts := otp.NewHOTPKeyOptions() + opts.Issuer = Issuer + opts.Label = user + key := otp.NewHOTPKey(opts) - opts := otp.NewHOTPKeyOptions() - opts.Issuer = Issuer - opts.Label = user - key := otp.NewHOTPKey(opts) + keyURL := key.URL() + Store(user, keyURL) - 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 +} - // 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 "" +} + +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 } - - // 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) { - 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 - } - +``` ### OTP Client +```go +import ( + "dev.justinjudd.org/justin/otp" +) - import ( - "dev.justinjudd.org/justin/otp" - ) - - // Just an example for storing OTP keys on the client - var keys map[Key]string +// 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 - } +// Key is used as keys for the otp key storing map +type Key struct { + Issuer, Label string +} - func GetCode(issuer, username string) (string, error) { +func GetCode(issuer, username string) (string, error) { - mapKey := Key{issuer, username} + mapKey := Key{issuer, username} - // Get the stored Key URL - keyURL, ok := keys[mapKey] - if !ok { - return "", nil - } + // 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 - } + // 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 - } + // Verify Issuer and Label are correct + if key.Issuer() != issuer || key.Label() != username { + return "", nil + } - code := key.OTP() + code := key.OTP() - // If using HOTP, than need to save the state - keyURL = key.URL() - keys[mapKey]= keyURL + // If using HOTP, than need to save the state + keyURL = key.URL() + keys[mapKey]= keyURL - return code, nil - } + return code, nil +} +```