Actually support clock mocking.
This commit is contained in:
8
totp.go
8
totp.go
@@ -15,7 +15,7 @@ import (
|
|||||||
"github.com/benbjohnson/clock"
|
"github.com/benbjohnson/clock"
|
||||||
)
|
)
|
||||||
|
|
||||||
var time clock.Clock
|
var timeSource = clock.New()
|
||||||
|
|
||||||
// TOTP represents an RFC 6238 Time-based One-Time Password instance.
|
// TOTP represents an RFC 6238 Time-based One-Time Password instance.
|
||||||
type TOTP struct {
|
type TOTP struct {
|
||||||
@@ -53,7 +53,7 @@ func (otp *TOTP) otpCounter(t uint64) uint64 {
|
|||||||
|
|
||||||
// OTPCounter returns the current time value for the OTP.
|
// OTPCounter returns the current time value for the OTP.
|
||||||
func (otp *TOTP) OTPCounter() uint64 {
|
func (otp *TOTP) OTPCounter() uint64 {
|
||||||
return otp.otpCounter(uint64(time.Now().Unix()))
|
return otp.otpCounter(uint64(timeSource.Now().Unix()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTOTP takes a new key, a starting time, a step, the number of
|
// NewTOTP takes a new key, a starting time, a step, the number of
|
||||||
@@ -166,3 +166,7 @@ func totpFromURL(u *url.URL) (*TOTP, string, error) {
|
|||||||
func (otp *TOTP) QR(label string) ([]byte, error) {
|
func (otp *TOTP) QR(label string) ([]byte, error) {
|
||||||
return otp.OATH.QR(otp.Type(), label)
|
return otp.OATH.QR(otp.Type(), label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetClock(c clock.Clock) {
|
||||||
|
timeSource = c
|
||||||
|
}
|
||||||
|
|||||||
28
totp_test.go
28
totp_test.go
@@ -4,6 +4,9 @@ import (
|
|||||||
"crypto"
|
"crypto"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/benbjohnson/clock"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rfcTotpKey = []byte("12345678901234567890")
|
var rfcTotpKey = []byte("12345678901234567890")
|
||||||
@@ -53,3 +56,28 @@ func TestTotpRFC(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTOTPTime(t *testing.T) {
|
||||||
|
otp := GenerateGoogleTOTP()
|
||||||
|
|
||||||
|
testClock := clock.NewMock()
|
||||||
|
testClock.Add(2*time.Minute)
|
||||||
|
SetClock(testClock)
|
||||||
|
|
||||||
|
code := otp.OTP()
|
||||||
|
|
||||||
|
testClock.Add(-1 * time.Minute)
|
||||||
|
if newCode := otp.OTP(); newCode == code {
|
||||||
|
t.Errorf("twofactor: TOTP: previous code %s shouldn't match code %s", newCode, code)
|
||||||
|
}
|
||||||
|
|
||||||
|
testClock.Add(2 * time.Minute)
|
||||||
|
if newCode := otp.OTP(); newCode == code {
|
||||||
|
t.Errorf("twofactor: TOTP: future code %s shouldn't match code %s", newCode, code)
|
||||||
|
}
|
||||||
|
|
||||||
|
testClock.Add(-1 * time.Minute)
|
||||||
|
if newCode := otp.OTP(); newCode != code {
|
||||||
|
t.Errorf("twofactor: TOTP: current code %s shouldn't match code %s", newCode, code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user