authelia/internal/totp/totp_test.go
James Elliott 9b6bcca1ba
feat(totp): secret customization (#2681)
Allow customizing the shared secrets size specifically for apps which don't support 256bit shared secrets.
2022-04-08 09:01:01 +10:00

152 lines
3.7 KiB
Go

package totp
import (
"encoding/base32"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/authelia/authelia/v4/internal/configuration/schema"
)
func TestTOTPGenerateCustom(t *testing.T) {
testCases := []struct {
desc string
username, algorithm, secret string
digits, period, secretSize uint
err string
}{
{
desc: "ShouldGenerateSHA1",
username: "john",
algorithm: "SHA1",
digits: 6,
period: 30,
secretSize: 32,
},
{
desc: "ShouldGenerateLongSecret",
username: "john",
algorithm: "SHA1",
digits: 6,
period: 30,
secretSize: 42,
},
{
desc: "ShouldGenerateSHA256",
username: "john",
algorithm: "SHA256",
digits: 6,
period: 30,
secretSize: 32,
},
{
desc: "ShouldGenerateSHA512",
username: "john",
algorithm: "SHA512",
digits: 6,
period: 30,
secretSize: 32,
},
{
desc: "ShouldGenerateWithSecret",
username: "john",
algorithm: "SHA512",
secret: "ONTGOYLTMZQXGZDBONSGC43EMFZWMZ3BONTWMYLTMRQXGZBSGMYTEMZRMFYXGZDBONSA",
digits: 6,
period: 30,
secretSize: 32,
},
{
desc: "ShouldGenerateWithBadSecretB32Data",
username: "john",
algorithm: "SHA512",
secret: "@#UNH$IK!J@N#EIKJ@U!NIJKUN@#WIK",
digits: 6,
period: 30,
secretSize: 32,
err: "totp generate failed: error decoding base32 string: illegal base32 data at input byte 0",
},
{
desc: "ShouldGenerateWithBadSecretLength",
username: "john",
algorithm: "SHA512",
secret: "ONTGOYLTMZQXGZD",
digits: 6,
period: 30,
secretSize: 0,
},
}
totp := NewTimeBasedProvider(schema.TOTPConfiguration{
Issuer: "Authelia",
Algorithm: "SHA1",
Digits: 6,
Period: 30,
SecretSize: 32,
})
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
c, err := totp.GenerateCustom(tc.username, tc.algorithm, tc.secret, tc.digits, tc.period, tc.secretSize)
if tc.err == "" {
assert.NoError(t, err)
require.NotNil(t, c)
assert.Equal(t, tc.period, c.Period)
assert.Equal(t, tc.digits, c.Digits)
assert.Equal(t, tc.algorithm, c.Algorithm)
expectedSecretLen := int(tc.secretSize)
if tc.secret != "" {
expectedSecretLen = base32.StdEncoding.WithPadding(base32.NoPadding).DecodedLen(len(tc.secret))
}
secret := make([]byte, expectedSecretLen)
n, err := base32.StdEncoding.WithPadding(base32.NoPadding).Decode(secret, c.Secret)
assert.NoError(t, err)
assert.Len(t, secret, expectedSecretLen)
assert.Equal(t, expectedSecretLen, n)
} else {
assert.Nil(t, c)
assert.EqualError(t, err, tc.err)
}
})
}
}
func TestTOTPGenerate(t *testing.T) {
skew := uint(2)
totp := NewTimeBasedProvider(schema.TOTPConfiguration{
Issuer: "Authelia",
Algorithm: "SHA256",
Digits: 8,
Period: 60,
Skew: &skew,
SecretSize: 32,
})
assert.Equal(t, uint(2), totp.skew)
config, err := totp.Generate("john")
assert.NoError(t, err)
assert.Equal(t, "Authelia", config.Issuer)
assert.Less(t, time.Since(config.CreatedAt), time.Second)
assert.Greater(t, time.Since(config.CreatedAt), time.Second*-1)
assert.Equal(t, uint(8), config.Digits)
assert.Equal(t, uint(60), config.Period)
assert.Equal(t, "SHA256", config.Algorithm)
secret := make([]byte, base32.StdEncoding.WithPadding(base32.NoPadding).DecodedLen(len(config.Secret)))
_, err = base32.StdEncoding.WithPadding(base32.NoPadding).Decode(secret, config.Secret)
assert.NoError(t, err)
assert.Len(t, secret, 32)
}