diff --git a/server/server/api/v1/client/auth/initiate.post.ts b/server/server/api/v1/client/auth/initiate.post.ts index dddc71e6..fe55073c 100644 --- a/server/server/api/v1/client/auth/initiate.post.ts +++ b/server/server/api/v1/client/auth/initiate.post.ts @@ -18,6 +18,21 @@ const ClientAuthInitiate = type({ }).configure(throwingArktype); export default defineEventHandler(async (h3) => { + // Version gate. Pre-0.4 desktop clients send no User-Agent (0.4+ sends + // "Drop Desktop Client" from the shared remote crate) and use a Nonce auth + // scheme this server no longer speaks. Without this check they pair + // successfully — the handshake is unauthenticated — and then every + // authenticated call 403s, which surfaces as an opaque "Unrecoverable + // error" after sign-in (zack.way, 2026-08-14). Failing here instead hits + // the old client's handshake error path, which DOES display `message`. + const userAgent = getHeader(h3, "User-Agent"); + if (!userAgent) + throw createError({ + statusCode: 400, + message: + "Your Drop client is too old for this server (it uses the pre-0.4 auth protocol). Download the current client from https://cdn.quasarke.net/drop-client/", + }); + const body = await readDropValidatedBody(h3, ClientAuthInitiate); const platformRaw = body.platform; diff --git a/server/server/internal/clients/event-handler.ts b/server/server/internal/clients/event-handler.ts index 103c7579..9295bd68 100644 --- a/server/server/internal/clients/event-handler.ts +++ b/server/server/internal/clients/event-handler.ts @@ -54,9 +54,16 @@ export function defineClientEventHandler(handler: EventHandlerFunction) { break; } default: { + // Pre-0.4 clients authenticate with a "Nonce ..." scheme this server + // no longer speaks. Their pairing handshake still succeeds (it is + // unauthenticated), so this is the first place they fail — and they + // render statusMessage, not message, so both carry the explanation. throw createError({ statusCode: 403, - message: "No authentication", + statusMessage: + "Drop client too old for this server - get the current client at cdn.quasarke.net/drop-client", + message: + "Your Drop client is too old for this server (it uses the pre-0.4 auth protocol). Download the current client from https://cdn.quasarke.net/drop-client/", }); } }