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'; @@ -309,7 +309,7 @@ async function siweAuthResponder(viewer: Viewer, input: any): Promise { await validateInput(viewer, siweAuthRequestInputValidator, input); const request: SIWEAuthRequest = input; - const { message } = request; + const { message, signature } = request; // 1. Ensure that `message` is a well formed Comm SIWE Auth message. const siweMessage: SIWEMessage = new SiweMessage(message); @@ -327,6 +327,24 @@ throw new ServerError('invalid_parameters'); } + // 3. 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 @@ -105,4 +105,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, };