-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathtotp_test.go
More file actions
59 lines (47 loc) · 1.87 KB
/
Copy pathtotp_test.go
File metadata and controls
59 lines (47 loc) · 1.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package mfa
import (
"testing"
"time"
"github.com/pquerna/otp"
"github.com/pquerna/otp/totp"
"github.com/stretchr/testify/require"
)
func totpOpts() totp.ValidateOpts {
return totp.ValidateOpts{Period: totpPeriod, Skew: totpSkew, Digits: otp.DigitsSix, Algorithm: otp.AlgorithmSHA1}
}
// TestValidateTOTPCode covers replay protection: a code is single-use per
// time-step, while a code from a later step is still accepted.
func TestValidateTOTPCode(t *testing.T) {
key, err := totp.Generate(totp.GenerateOpts{Issuer: "dex", AccountName: "user@example.com"})
require.NoError(t, err)
secret := key.Secret()
now := time.Unix(1700000000, 0)
code, err := totp.GenerateCodeCustom(secret, now, totpOpts())
require.NoError(t, err)
// First use is accepted and reports the matched counter.
ok, counter := validateTOTPCode(secret, code, now, 0)
require.True(t, ok)
require.Equal(t, now.Unix()/totpPeriod, counter)
// Replaying the same code with that counter recorded is rejected.
ok, _ = validateTOTPCode(secret, code, now, counter)
require.False(t, ok, "replayed code must be rejected")
// A wrong code is rejected.
ok, _ = validateTOTPCode(secret, "000000", now, 0)
require.False(t, ok)
// A code from the next step is accepted and advances the counter.
next := now.Add(totpPeriod * time.Second)
nextCode, err := totp.GenerateCodeCustom(secret, next, totpOpts())
require.NoError(t, err)
ok, nextCounter := validateTOTPCode(secret, nextCode, next, counter)
require.True(t, ok)
require.Greater(t, nextCounter, counter)
}
func TestTOTPManualSecret(t *testing.T) {
key, err := totp.Generate(totp.GenerateOpts{Issuer: "example", AccountName: "user@example.com"})
require.NoError(t, err)
manualSecret, err := totpManualSecret(key.String())
require.NoError(t, err)
require.Equal(t, key.Secret(), manualSecret)
_, err = totpManualSecret("otpauth://totp/%ZZ")
require.Error(t, err)
}