Files
sonr/client/auth/webauthn_test.go.bak
T
Prad NukalaandGitHub 13e6c3e84d Master (#1262)
* clear

* feat: Add everything

* fix: Commenht
2025-10-03 14:45:52 -04:00

338 lines
9.7 KiB
Plaintext

package auth
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/sonr-io/sonr/x/did/types"
)
// Mock DIDClient for testing
type mockDIDClient struct {
credentials []*types.WebAuthnCredential
didDoc *types.DIDDocument
error error
}
func (m *mockDIDClient) QueryCredentials(ctx context.Context, did string) ([]*types.WebAuthnCredential, error) {
if m.error != nil {
return nil, m.error
}
return m.credentials, nil
}
func (m *mockDIDClient) QueryCredential(ctx context.Context, did, credentialID string) (*types.WebAuthnCredential, error) {
if m.error != nil {
return nil, m.error
}
for _, cred := range m.credentials {
if cred.CredentialId == credentialID {
return cred, nil
}
}
return nil, fmt.Errorf("key not found")
}
func (m *mockDIDClient) UpdateCredential(ctx context.Context, did string, credential *types.WebAuthnCredential) error {
if m.error != nil {
return m.error
}
for i, cred := range m.credentials {
if cred.CredentialId == credential.CredentialId {
m.credentials[i] = credential
return nil
}
}
return fmt.Errorf("key not found")
}
func (m *mockDIDClient) RevokeCredential(ctx context.Context, did, credentialID string) error {
if m.error != nil {
return m.error
}
for i, cred := range m.credentials {
if cred.CredentialId == credentialID {
// Remove from slice
m.credentials = append(m.credentials[:i], m.credentials[i+1:]...)
return nil
}
}
return fmt.Errorf("key not found")
}
func (m *mockDIDClient) QueryDIDDocument(ctx context.Context, did string) (*types.DIDDocument, error) {
if m.error != nil {
return nil, m.error
}
return m.didDoc, nil
}
func (m *mockDIDClient) AuthenticateWithDID(ctx context.Context, did string, assertion []byte) (bool, error) {
if m.error != nil {
return false, m.error
}
return true, nil
}
func (m *mockDIDClient) SignTransaction(ctx context.Context, did string, txBytes []byte, credentialID string) ([]byte, error) {
if m.error != nil {
return nil, m.error
}
// Mock signature
return []byte("mock_signature"), nil
}
// Helper function to create test credentials
func createTestCredential(id string) *types.WebAuthnCredential {
return &types.WebAuthnCredential{
CredentialId: id,
RawId: base64.RawURLEncoding.EncodeToString([]byte(id)),
ClientDataJson: `{"type":"webauthn.create","challenge":"test","origin":"http://localhost"}`,
AttestationObject: base64.RawURLEncoding.EncodeToString([]byte("test_attestation")),
PublicKey: []byte("test_public_key"),
Algorithm: -7, // ES256
Origin: "http://localhost",
CreatedAt: 1234567890,
}
}
func TestWebAuthnClient_CompleteRegistration(t *testing.T) {
client := &webAuthnClient{
origin: "http://localhost",
rpID: "localhost",
}
challenge := &RegistrationChallenge{
Challenge: []byte("test_challenge"),
User: &User{
ID: []byte("test_user"),
Name: "Test User",
DisplayName: "Test",
},
}
// Create valid client data JSON
clientData := map[string]any{
"type": "webauthn.create",
"challenge": challenge.Challenge,
"origin": "http://localhost",
}
clientDataJSON, _ := json.Marshal(clientData)
response := &AuthenticatorAttestationResponse{
ClientDataJSON: clientDataJSON,
AttestationObject: []byte("test_attestation"),
}
// Test successful registration
cred, err := client.CompleteRegistration(context.Background(), challenge, response)
assert.NoError(t, err)
assert.NotNil(t, cred)
// Test with invalid client data
response.ClientDataJSON = []byte("invalid_json")
_, err = client.CompleteRegistration(context.Background(), challenge, response)
assert.Error(t, err)
}
func TestWebAuthnClient_CompleteAuthentication(t *testing.T) {
credential := createTestCredential("test_cred_1")
client := &webAuthnClient{
origin: "http://localhost",
rpID: "localhost",
}
challenge := &AuthenticationChallenge{
Challenge: []byte("test_challenge"),
}
// Create valid client data JSON
clientData := map[string]any{
"type": "webauthn.get",
"challenge": challenge.Challenge,
"origin": "http://localhost",
}
clientDataJSON, _ := json.Marshal(clientData)
response := &AuthenticatorAssertionResponse{
ClientDataJSON: clientDataJSON,
AuthenticatorData: []byte("test_auth_data"),
Signature: []byte("test_signature"),
UserHandle: []byte("test_user"),
}
// Test successful authentication
result, err := client.CompleteAuthentication(context.Background(), challenge, response, "test_cred_1")
assert.NoError(t, err)
assert.NotNil(t, result)
assert.True(t, result.Verified)
// Test with wrong origin
clientData["origin"] = "http://evil.com"
clientDataJSON, _ = json.Marshal(clientData)
response.ClientDataJSON = base64.RawURLEncoding.EncodeToString(clientDataJSON)
_, err = client.CompleteAuthentication(context.Background(), challenge, response, "test_cred_1")
assert.Error(t, err)
}
func TestWebAuthnClient_ListCredentials(t *testing.T) {
cred1 := createTestCredential("cred1")
cred2 := createTestCredential("cred2")
client := &webAuthnClient{
didClient: &mockDIDClient{
credentials: []*types.WebAuthnCredential{cred1, cred2},
},
}
// Test successful list
creds, err := client.ListCredentials(context.Background(), "did:test:123")
require.NoError(t, err)
assert.Len(t, creds, 2)
assert.Equal(t, "cred1", creds[0].CredentialId)
assert.Equal(t, "cred2", creds[1].CredentialId)
// Test with error
client.didClient = &mockDIDClient{error: assert.AnError}
_, err = client.ListCredentials(context.Background(), "did:test:123")
assert.Error(t, err)
}
func TestWebAuthnClient_GetCredential(t *testing.T) {
cred := createTestCredential("test_cred")
client := &webAuthnClient{
didClient: &mockDIDClient{
credentials: []*types.WebAuthnCredential{cred},
},
}
// Test successful get
retrieved, err := client.GetCredential(context.Background(), "did:test:123", "test_cred")
require.NoError(t, err)
assert.Equal(t, cred.CredentialId, retrieved.CredentialId)
// Test credential not found
_, err = client.GetCredential(context.Background(), "did:test:123", "non_existent")
assert.Error(t, err)
}
func TestWebAuthnClient_UpdateCredential(t *testing.T) {
cred := createTestCredential("test_cred")
client := &webAuthnClient{
didClient: &mockDIDClient{
credentials: []*types.WebAuthnCredential{cred},
},
}
// Update the credential
updatedCred := createTestCredential("test_cred")
updatedCred.Origin = "https://updated.example.com"
err := client.UpdateCredential(context.Background(), "did:test:123", updatedCred)
require.NoError(t, err)
// Verify update
mock := client.didClient.(*mockDIDClient)
assert.Equal(t, "https://updated.example.com", mock.credentials[0].Origin)
// Test update non-existent credential
nonExistent := createTestCredential("non_existent")
err = client.UpdateCredential(context.Background(), "did:test:123", nonExistent)
assert.Error(t, err)
}
func TestWebAuthnClient_RevokeCredential(t *testing.T) {
cred1 := createTestCredential("cred1")
cred2 := createTestCredential("cred2")
client := &webAuthnClient{
didClient: &mockDIDClient{
credentials: []*types.WebAuthnCredential{cred1, cred2},
},
}
// Revoke first credential
err := client.RevokeCredential(context.Background(), "did:test:123", "cred1")
require.NoError(t, err)
// Verify revocation
mock := client.didClient.(*mockDIDClient)
assert.Len(t, mock.credentials, 1)
assert.Equal(t, "cred2", mock.credentials[0].CredentialId)
// Test revoke non-existent credential
err = client.RevokeCredential(context.Background(), "did:test:123", "non_existent")
assert.Error(t, err)
}
func TestWebAuthnClient_AuthenticateWithDID(t *testing.T) {
client := &webAuthnClient{
origin: "http://localhost",
didClient: &mockDIDClient{
didDoc: &types.DIDDocument{
Id: "did:test:123",
},
},
}
assertion := &AuthenticationAssertion{
CredentialID: "test_cred",
ClientDataJSON: base64.RawURLEncoding.EncodeToString([]byte(`{"type":"webauthn.get"}`)),
AuthenticatorData: base64.RawURLEncoding.EncodeToString([]byte("auth_data")),
Signature: base64.RawURLEncoding.EncodeToString([]byte("signature")),
UserHandle: base64.RawURLEncoding.EncodeToString([]byte("user")),
}
// Test successful authentication
result, err := client.AuthenticateWithDID(context.Background(), "did:test:123", assertion)
require.NoError(t, err)
assert.NotNil(t, result)
assert.True(t, result.Success)
assert.Equal(t, "test_cred", result.CredentialId)
// Test with error
client.didClient = &mockDIDClient{error: assert.AnError}
_, err = client.AuthenticateWithDID(context.Background(), "did:test:123", assertion)
assert.Error(t, err)
}
func TestWebAuthnClient_SignWithWebAuthn(t *testing.T) {
client := &webAuthnClient{
didClient: &mockDIDClient{},
}
txData := []byte("transaction_data")
// Test successful signing
sig, err := client.SignWithWebAuthn(context.Background(), "did:test:123", txData, "test_cred")
require.NoError(t, err)
assert.Equal(t, []byte("mock_signature"), sig)
// Test with error
client.didClient = &mockDIDClient{error: assert.AnError}
_, err = client.SignWithWebAuthn(context.Background(), "did:test:123", txData, "test_cred")
assert.Error(t, err)
}
func TestWebAuthnClient_BindCredential(t *testing.T) {
client := &webAuthnClient{}
cred := createTestCredential("test_cred")
// Test that BindCredential returns the existing implementation message
result, err := client.BindCredential(context.Background(), "did:test:123", cred)
require.NoError(t, err)
assert.NotNil(t, result)
assert.Equal(t, "test_cred", result.CredentialId)
// The actual binding logic would be implemented in a later phase
// For now, it just returns the credential as-is
}