Fix wallet connect signature mismatch on mobile and desktop.
Align backend EIP-191 auth message with the DBIS Explorer text the frontend and legacy SPA already sign, instead of the stale SolaceScan string. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -110,6 +110,12 @@ type WalletAuthResponse struct {
|
||||
InstitutionName string `json:"institution_name,omitempty"`
|
||||
}
|
||||
|
||||
// walletAuthSignMessage returns the EIP-191 plaintext users sign during wallet login.
|
||||
// Must stay in sync with frontend buildWalletMessage() in access.ts and explorer-spa.js.
|
||||
func walletAuthSignMessage(nonce string) string {
|
||||
return fmt.Sprintf("Sign this message to authenticate with DBIS Explorer.\n\nNonce: %s", nonce)
|
||||
}
|
||||
|
||||
// GenerateNonce generates a random nonce for wallet authentication
|
||||
func (w *WalletAuth) GenerateNonce(ctx context.Context, address string) (*NonceResponse, error) {
|
||||
// Validate address format
|
||||
@@ -184,7 +190,7 @@ func (w *WalletAuth) AuthenticateWallet(ctx context.Context, req *WalletAuthRequ
|
||||
}
|
||||
|
||||
// Verify signature
|
||||
message := fmt.Sprintf("Sign this message to authenticate with SolaceScan.\n\nNonce: %s", req.Nonce)
|
||||
message := walletAuthSignMessage(req.Nonce)
|
||||
messageHash := accounts.TextHash([]byte(message))
|
||||
|
||||
sigBytes, err := decodeWalletSignature(req.Signature)
|
||||
|
||||
@@ -5,9 +5,42 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestWalletAuthSignMessageMatchesFrontend(t *testing.T) {
|
||||
nonce := "abc123def456"
|
||||
require.Equal(
|
||||
t,
|
||||
"Sign this message to authenticate with DBIS Explorer.\n\nNonce: abc123def456",
|
||||
walletAuthSignMessage(nonce),
|
||||
)
|
||||
}
|
||||
|
||||
func TestAuthenticateWalletRecoversSignerFromFrontendMessage(t *testing.T) {
|
||||
privateKey, err := crypto.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
address := crypto.PubkeyToAddress(privateKey.PublicKey).Hex()
|
||||
nonce := "test-nonce-001"
|
||||
|
||||
message := walletAuthSignMessage(nonce)
|
||||
messageHash := accounts.TextHash([]byte(message))
|
||||
signature, err := crypto.Sign(messageHash, privateKey)
|
||||
require.NoError(t, err)
|
||||
signature[64] += 27
|
||||
|
||||
sigBytes := make([]byte, len(signature))
|
||||
copy(sigBytes, signature)
|
||||
if sigBytes[64] >= 27 {
|
||||
sigBytes[64] -= 27
|
||||
}
|
||||
pubKey, err := crypto.SigToPub(messageHash, sigBytes)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, address, crypto.PubkeyToAddress(*pubKey).Hex())
|
||||
}
|
||||
|
||||
func TestDecodeWalletSignatureRejectsMalformedValues(t *testing.T) {
|
||||
_, err := decodeWalletSignature("deadbeef")
|
||||
require.ErrorContains(t, err, "signature must start with 0x")
|
||||
|
||||
Reference in New Issue
Block a user