pomerium/pkg/webauthnutil/options_test.go

175 lines
6.2 KiB
Go

package webauthnutil
import (
"testing"
"github.com/pomerium/webauthn"
"github.com/pomerium/webauthn/cose"
"github.com/stretchr/testify/assert"
"github.com/pomerium/pomerium/pkg/grpc/device"
"github.com/pomerium/pomerium/pkg/grpc/user"
)
func TestGenerateCreationOptions(t *testing.T) {
t.Run("random challenge", func(t *testing.T) {
key := []byte{1, 2, 3}
options1 := GenerateCreationOptions(key, predefinedDeviceTypes[DefaultDeviceType], &user.User{
Id: "example",
Email: "test@example.com",
Name: "Test User",
})
options2 := GenerateCreationOptions(key, predefinedDeviceTypes[DefaultDeviceType], &user.User{
Id: "example",
Email: "test@example.com",
Name: "Test User",
})
assert.NotEqual(t, options1.Challenge, options2.Challenge)
})
t.Run(DefaultDeviceType, func(t *testing.T) {
key := []byte{1, 2, 3}
options := GenerateCreationOptions(key, predefinedDeviceTypes[DefaultDeviceType], &user.User{
Id: "example",
Email: "test@example.com",
Name: "Test User",
})
options.Challenge = nil
assert.Equal(t, &webauthn.PublicKeyCredentialCreationOptions{
RP: webauthn.PublicKeyCredentialRPEntity{
Name: "Pomerium",
},
User: webauthn.PublicKeyCredentialUserEntity{
ID: []byte{
0x14, 0x7b, 0x2e, 0x3b, 0xae, 0x95, 0x5b, 0x99,
0xbb, 0x4e, 0x89, 0xdd, 0x03, 0xac, 0xae, 0x1d,
},
DisplayName: "Test User",
Name: "test@example.com",
},
Challenge: nil,
PubKeyCredParams: []webauthn.PublicKeyCredentialParameters{
{Type: "public-key", COSEAlgorithmIdentifier: -7},
{Type: "public-key", COSEAlgorithmIdentifier: -257},
{Type: "public-key", COSEAlgorithmIdentifier: -65535},
},
Timeout: 900000000000,
ExcludeCredentials: nil,
AuthenticatorSelection: &webauthn.AuthenticatorSelectionCriteria{
UserVerification: "preferred",
},
Attestation: "direct",
}, options)
})
}
func TestGenerateRequestOptions(t *testing.T) {
t.Run("random challenge", func(t *testing.T) {
key := []byte{1, 2, 3}
options1 := GenerateRequestOptions(key, predefinedDeviceTypes[DefaultDeviceType], nil)
options2 := GenerateRequestOptions(key, predefinedDeviceTypes[DefaultDeviceType], nil)
assert.NotEqual(t, options1.Challenge, options2.Challenge)
})
t.Run(DefaultDeviceType, func(t *testing.T) {
key := []byte{1, 2, 3}
options := GenerateRequestOptions(key, predefinedDeviceTypes[DefaultDeviceType], []*device.Credential{
{Id: "device1", Specifier: &device.Credential_Webauthn{Webauthn: &device.Credential_WebAuthn{
Id: []byte{4, 5, 6},
}}},
})
options.Challenge = nil
assert.Equal(t, &webauthn.PublicKeyCredentialRequestOptions{
Timeout: 900000000000,
AllowCredentials: []webauthn.PublicKeyCredentialDescriptor{
{Type: "public-key", ID: []byte{4, 5, 6}},
},
UserVerification: "preferred",
}, options)
})
}
func TestFillAttestationConveyance(t *testing.T) {
for _, testCase := range []struct {
expect webauthn.AttestationConveyancePreference
in *device.WebAuthnOptions_AttestationConveyancePreference
}{
{"", nil},
{"none", device.WebAuthnOptions_NONE.Enum()},
{"indirect", device.WebAuthnOptions_INDIRECT.Enum()},
{"direct", device.WebAuthnOptions_DIRECT.Enum()},
{"enterprise", device.WebAuthnOptions_ENTERPRISE.Enum()},
} {
options := new(webauthn.PublicKeyCredentialCreationOptions)
fillAttestationConveyance(options, testCase.in)
actual := options.Attestation
assert.Equal(t, testCase.expect, actual, "expected %v for %v", testCase.expect, testCase.in)
}
}
func TestFillAuthenticatorSelection(t *testing.T) {
for _, testCase := range []struct {
expect webauthn.AuthenticatorAttachment
in *device.WebAuthnOptions_AuthenticatorAttachment
}{
{"", nil},
{"cross-platform", device.WebAuthnOptions_CROSS_PLATFORM.Enum()},
{"platform", device.WebAuthnOptions_PLATFORM.Enum()},
} {
criteria := new(webauthn.AuthenticatorSelectionCriteria)
fillAuthenticatorAttachment(criteria, testCase.in)
actual := criteria.AuthenticatorAttachment
assert.Equal(t, testCase.expect, actual, "expected %v for %v", testCase.expect, testCase.in)
}
}
func TestFillPublicKeyCredentialParameters(t *testing.T) {
for _, testCase := range []struct {
expectedType webauthn.PublicKeyCredentialType
expectedAlgorithm cose.Algorithm
in *device.WebAuthnOptions_PublicKeyCredentialParameters
}{
{"", 0, nil},
{"public-key", -7, &device.WebAuthnOptions_PublicKeyCredentialParameters{
Type: device.WebAuthnOptions_PUBLIC_KEY, Alg: -7}},
} {
params := new(webauthn.PublicKeyCredentialParameters)
fillPublicKeyCredentialParameters(params, testCase.in)
actualType := params.Type
assert.Equal(t, testCase.expectedType, actualType, "expected %v for %v", testCase.expectedType, testCase.in)
actualAlgorithm := params.COSEAlgorithmIdentifier
assert.Equal(t, testCase.expectedAlgorithm, actualAlgorithm, "expected %v for %v", testCase.expectedType, testCase.in)
}
}
func TestFillResidentKeyRequirement(t *testing.T) {
for _, testCase := range []struct {
expect webauthn.ResidentKeyType
in *device.WebAuthnOptions_ResidentKeyRequirement
}{
{"", nil},
{"discouraged", device.WebAuthnOptions_RESIDENT_KEY_DISCOURAGED.Enum()},
{"preferred", device.WebAuthnOptions_RESIDENT_KEY_PREFERRED.Enum()},
{"required", device.WebAuthnOptions_RESIDENT_KEY_REQUIRED.Enum()},
} {
criteria := new(webauthn.AuthenticatorSelectionCriteria)
fillResidentKeyRequirement(criteria, testCase.in)
actual := criteria.ResidentKey
assert.Equal(t, testCase.expect, actual, "expected %v for %v", testCase.expect, testCase.in)
}
}
func TestFillUserVerificationRequirement(t *testing.T) {
for _, testCase := range []struct {
expect webauthn.UserVerificationRequirement
in *device.WebAuthnOptions_UserVerificationRequirement
}{
{"", nil},
{"discouraged", device.WebAuthnOptions_USER_VERIFICATION_DISCOURAGED.Enum()},
{"preferred", device.WebAuthnOptions_USER_VERIFICATION_PREFERRED.Enum()},
{"required", device.WebAuthnOptions_USER_VERIFICATION_REQUIRED.Enum()},
} {
criteria := new(webauthn.AuthenticatorSelectionCriteria)
fillUserVerificationRequirement(criteria, testCase.in)
actual := criteria.UserVerification
assert.Equal(t, testCase.expect, actual, "expected %v for %v", testCase.expect, testCase.in)
}
}