diff --git a/keyserver/src/deleters/siwe-nonce-deleters.js b/keyserver/src/deleters/siwe-nonce-deleters.js
--- a/keyserver/src/deleters/siwe-nonce-deleters.js
+++ b/keyserver/src/deleters/siwe-nonce-deleters.js
@@ -9,9 +9,21 @@
   const earliestValidCreationTime = Date.now() - nonceLifetime;
   const query = SQL`
     DELETE FROM siwe_nonces
-      WHERE creation_time < ${earliestValidCreationTime}
+    WHERE creation_time < ${earliestValidCreationTime}
   `;
   await dbQuery(query);
 }
 
-export { deleteStaleSIWENonceEntries };
+async function checkAndInvalidateSIWENonceEntry(
+  nonce: string,
+): Promise<boolean> {
+  const earliestValidCreationTime = Date.now() - nonceLifetime;
+  const query = SQL`
+    DELETE FROM siwe_nonces
+    WHERE nonce = ${nonce} AND creation_time > ${earliestValidCreationTime}
+  `;
+  const [result] = await dbQuery(query);
+  return result.affectedRows && result.affectedRows > 0;
+}
+
+export { deleteStaleSIWENonceEntries, checkAndInvalidateSIWENonceEntry };
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
@@ -47,6 +47,7 @@
 import { dbQuery, SQL } from '../database/database';
 import { deleteAccount } from '../deleters/account-deleters';
 import { deleteCookie } from '../deleters/cookie-deleters';
+import { checkAndInvalidateSIWENonceEntry } from '../deleters/siwe-nonce-deleters.js';
 import { fetchEntryInfos } from '../fetchers/entry-fetchers';
 import { fetchMessageInfos } from '../fetchers/message-fetchers';
 import { fetchThreadInfos } from '../fetchers/thread-fetchers';
@@ -316,6 +317,16 @@
     throw new ServerError('invalid_parameters');
   }
 
+  // 2. Ensure that the `nonce` exists in the `siwe_nonces` table
+  //    AND hasn't expired. If those conditions are met, delete the entry to
+  //    ensure that the same `nonce` can't be re-used in a future request.
+  const wasNonceCheckedAndInvalidated = await checkAndInvalidateSIWENonceEntry(
+    siweMessage.nonce,
+  );
+  if (!wasNonceCheckedAndInvalidated) {
+    throw new ServerError('invalid_parameters');
+  }
+
   return false;
 }