Skip to content
This repository has been archived by the owner on May 3, 2024. It is now read-only.

wallet_authenticator is outdated and not in line with the message created by the react/web SDK #145

Open
ManZzup opened this issue Dec 26, 2023 · 0 comments

Comments

@ManZzup
Copy link

ManZzup commented Dec 26, 2023

Hi there,

I'll try to improve the issue ticket as i go but for now I realized (after a few hours) that the message body of the created by the react SDK and the verify method used in the python SDK are waay different. Judging by the content, I think python one is the outdated option. For now I've overriden the generate_message and verify methods to get this working. Below is my code if anyone facing the same issue,

def format_time_for_message(timestamp):
    time = timestamp.strftime("%Y-%m-%dT%H:%M:%S")
    microseconds = timestamp.strftime("%f")[0:3]
    formatted_time = f"{time}.{microseconds}Z"
    
    return formatted_time
    
def generate_message(payload: ExtendedPayloadData) -> str:
        """
        Generates an EIP-4361 compliant message to sign based on the login payload
        """

        message = ""

        # Add the domain and login address for transparency
        message += f"{payload.domain} wants you to sign in with your Ethereum account:\n{payload.address}\n\n"

        # Prompt user to make sure domain is correct to prevent phishing attacks
        message += "Please ensure that the domain above matches the URL of the current website.\n\n"

        message += f"Version: {payload.version}\n"

        # Add data fields in compliance with the EIP-4361 standard
        if payload.chain_id is not None:
            message += f"Chain ID: {payload.chain_id}\n"

        message += f"Nonce: {payload.nonce}\n"
        message += f"Issued At: {format_time_for_message(payload.issued_at)}\n"

        message += f"Expiration Time: {format_time_for_message(payload.expiration_time)}\n"

        message += f"Not Before: {format_time_for_message(payload.invalid_before)}"

        return message

def verify(
        domain: str,
        payload,
        options: VerifyOptions = VerifyOptions()
    ) -> str:
        """
        Server-side function to securely verify the address of the logged in client-side wallet
        by validating the provided client-side login request.

        ```python
        domain = "example.com"
        payload = sdk.auth.login(domain)

        # Verify the login request
        address = sdk.auth.verify(domain, payload)
        ```

        :param domain: The domain of the application to verify the login request for
        :param payload: The login payload to verify
        :return: The address of the logged in wallet that signed the payload
        """

        # Check that the intended domain matches the domain of the payload
        if payload.payload.domain != domain:
            raise Exception(
                f"Expected domain '{domain}' does not match domain on payload '{payload.payload.domain}'"
            )

        # Check that the payload hasn't expired
        current_time = datetime.utcnow()
        if current_time.replace(
            tzinfo=pytz.utc
        ) > payload.payload.expiration_time.replace(tzinfo=pytz.utc):
            raise Exception(f"Login request has expired")

        # If chain ID is specified, check that it matches the chain ID of the signature
        if (
            options.chain_id is not None
            and options.chain_id != payload.payload.chain_id
        ):
            raise Exception(
                f"Chain ID '{options.chain_id}' does not match payload chain ID '{payload.payload.chain_id}'"
            )

        # Check that the signing address is the claimed wallet address
        message = generate_message(payload.payload)
        user_address = sdk.auth._recover_address(message, payload.signature)
        
        if user_address.lower() != payload.payload.address.lower():
            raise Exception(
                f"The intended payload address '{payload.payload.address.lower()}' is not the payload signer"
            )

        return user_address
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant