Sign-In with Ethereum - API Harmonization and TypeScript v2.0 Beta Release

In our continued updates on Sign-In with Ethereum support, we're pleased to announce that we've harmonized the behavior of our SIWE Core APIs across different languages, added a number of optimizations, and have released a new beta of our TypeScript library with the included changes.

Sign-In with Ethereum - API Harmonization and TypeScript v2.0 Beta Release

In our continued updates on Sign-In with Ethereum (SIWE) support, we're pleased to announce that we've harmonized the behavior of our SIWE Core APIs across different languages, added a number of optimizations, and have released a new beta of our TypeScript library with the included changes.

While watching SIWE adoption we've identified multiple cases of how SIWE is typically integrated, and we decided to update our SIWE Core Packages to what we learned from our observations. We recently harmonized the behavior of our SIWE Core APIs across different languages with a focus on unifying handling for the parsing, validating, and verification of SIWE messages and all SIWE Core Packages (TypeScript, Rust, Go, Ruby, Elixir, and Python) have now been streamlined to support this.

All checks from EIP-4361 are now enforced, and we also implemented type checks for fields contained in SIWE messages stricter. One won’t be able to create a SIWE message with an Ethereum account that is not EIP-155 compliant, as required by EIP-4361.

Finally, verifiers (backend applications, APIs, cloud functions, lambdas etc.) which rely on the outcome of the verification process can now get more granular reasons in case some checks have failed and provide additional checks as needed (e.g., domain, nonce, timestamp). We've now also released a v2.0 beta version of our TypeScript library reflecting these changes:

Release SIWE 2.0 Release · spruceid/siwe
SIWE 2.0 has been released. The interfaces have been updated to allow consistent usage across languages for SIWE message parsing, creation, and verification. Message parsing has been split into its...

The interfaces have been updated to allow consistent usage across languages for SIWE message parsing, creation, and verification. Wallet implementers are mostly interested in SIWE message parsing, so we also now have a SIWE parser package (TypeScript) to optimize for dependency footprint. siwe-parser allows implementers to utilize this functionality standalone without importing larger cryptographic dependencies.

Additional Developer Notes for the TypeScript v2.0 Beta Release

The update introduces the following breaking changes (hence the major version update) and implements stricter checks from the EIP-4361 specification:

  • validate(…) was deprecated and renamed to verify(…) with a new API. A backwards-compatible helper function exists to allow existing implementers to upgrade without concern for changed behavior, but SIWE 1.0 users are advised to review the upgrade section below.
  • ethers has been updated to a peer dependency, allowing for more efficient builds.
  • EIP-55 validation of EIP-155 is now enforced, and non-EIP-155 messages are considered as invalid.
  • The type and signature properties have been removed from SiweMessage.
  • The not-before message field is now checked during verify.
  • This update introduces more granular error types returned after verification or message parsing failures: EXPIRED_MESSAGE, INVALID_DOMAIN, DOMAIN_MISMATCH, NONCE_MISMATCH, INVALID_ADDRESS, INVALID_URI, INVALID_NONCE, NOT_YET_VALID_MESSAGE, INVALID_SIGNATURE, INVALID_TIME_FORMAT, INVALID_MESSAGE_VERSION, and UNABLE_TO_PARSE.

Upgrading from SIWE 1.x to 2.0
For most implementers, the existing code will continue to work as expected without changes, but there will be a warning message that validate() has been deprecated and may be removed in future versions. To get rid of this warning, you can simply update instances of validate(signature) to verify({ signature: signature }).

Instead of validate(...), SIWE 2.0 uses verify(params, opts). The verify function accepts the primary argument params, which satisfies the following interface:

export interface VerifyParams {
    /** Signature of the message signed by the wallet */
    signature: string;

    /** RFC 4501 dns authority that is requesting the signing. */
    domain?: string;

    /** Randomized token used to prevent replay attacks, at least 8 alphanumeric characters. */
    nonce?: string;

    /**ISO 8601 datetime string of the current time. */
    time?: string;
}

The opts argument contains the options which dictate how the verification should proceed, namely:

export interface VerifyOpts {
    /** ethers provider to be used for EIP-1271 validation */
    provider?: providers.Provider;

    /** If the library should reject promises on errors, defaults to false */
    suppressExceptions?: boolean;
}

With the suppressExceptions option above, a SiweResponse with a populated error will be resolved instead of the promise being rejected, allowing for normal control flow handling. However, by default, promises are rejected to ensure defensive programming practices.

Finally, the verify(...) function returns an object of type SiweResponse defined as:

export interface SiweResponse {
    /** Boolean representing if the message was verified with success. */
    success: boolean;

    /** If present `success` MUST be false and will provide extra information on the failure reason. */
    error?: SiweError;

    /** Original message that was verified. */
    data: SiweMessage;
}

If you're interested in integrating Sign-In with Ethereum into your dapp, app, or service, we are more than happy to help and provide any support we can. As we continue our work supporting Sign-In with Ethereum, we especially welcome implementers who already have users relying on similar workflows, authors of related EIPs, and wallet vendors who would like to do more to support user-owned identities to join us.

If you are interested in being involved, please join our Discord server: