This repository was archived by the owner on May 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 35
This repository was 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
Copy link
Copy link
Open
Description
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
Metadata
Metadata
Assignees
Labels
No labels