SIWE 2.0 Release
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 own package, siwe-parser
, allowing implementers to utilize this functionality standalone without importing larger cryptographic dependencies.
As a result, this 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 toverify(…)
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
andsignature
properties have been removed fromSiweMessage
. - The
not-before
message field is now checked duringverify
. - 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
, andUNABLE_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 })
.
validate
(SIWE 1.x) vs verify
(SIWE 2.0)
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;
}
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;
}
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.