diff --git a/keyserver/src/responders/user-responders.js b/keyserver/src/responders/user-responders.js --- a/keyserver/src/responders/user-responders.js +++ b/keyserver/src/responders/user-responders.js @@ -1,7 +1,7 @@ // @flow import invariant from 'invariant'; -import { SiweMessage } from 'siwe'; +import { ErrorTypes, SiweMessage } from 'siwe'; import t from 'tcomb'; import bcrypt from 'twin-bcrypt'; @@ -313,7 +313,7 @@ async function siweAuthResponder(viewer: Viewer, input: any): Promise { await validateInput(viewer, siweAuthRequestInputValidator, input); const request: SIWEAuthRequest = input; - const { address, message } = request; + const { address, message, signature } = request; // 1. Ensure that `address` is a well formed Ethereum address. if (!isValidEthereumAddress(address)) { @@ -336,6 +336,24 @@ throw new ServerError('invalid_parameters'); } + // 4. Validate SIWEMessage signature and handle possible errors. + try { + await siweMessage.validate(signature); + } catch (error) { + if (error === ErrorTypes.EXPIRED_MESSAGE) { + // Thrown when the `expirationTime` is present and in the past. + throw new ServerError('Expired message.', { status: 400 }); + } else if (error === ErrorTypes.INVALID_SIGNATURE) { + // Thrown when the `validate()` function can't verify the message. + throw new ServerError('Invalid signature.', { status: 400 }); + } else if (error === ErrorTypes.MALFORMED_SESSION) { + // Thrown when some required field is missing. + throw new ServerError('Malformed session.', { status: 400 }); + } else { + throw new ServerError('Unknown error.', { status: 500 }); + } + } + return false; } diff --git a/lib/types/siwe-types.js b/lib/types/siwe-types.js --- a/lib/types/siwe-types.js +++ b/lib/types/siwe-types.js @@ -107,4 +107,5 @@ // This field will be removed in future releases and will rely on the // message version. +type?: 'Personal signature', + +validate: (signature: string, provider?: any) => Promise, };