diff --git a/src/app.ts b/src/app.ts index 5765a06..08eecd2 100644 --- a/src/app.ts +++ b/src/app.ts @@ -68,6 +68,20 @@ export async function buildApp( taskDone(null, payload); }); + // Formulaires HTML (déconnexion) : sinon Fastify répond 415 sur le POST du
. + app.addContentTypeParser( + 'application/x-www-form-urlencoded', + { parseAs: 'string' }, + (_request, body: string | Buffer, taskDone) => { + try { + const raw = typeof body === 'string' ? body : body.toString('utf8'); + taskDone(null, Object.fromEntries(new URLSearchParams(raw))); + } catch (error) { + taskDone(error instanceof Error ? error : new Error('Corps de formulaire invalide')); + } + }, + ); + await app.register(secureSession, { key: config.session.key, cookieName: SESSION_COOKIE_NAME, diff --git a/tests/auth-flow.test.ts b/tests/auth-flow.test.ts index 6b6c642..16acec6 100644 --- a/tests/auth-flow.test.ts +++ b/tests/auth-flow.test.ts @@ -71,11 +71,15 @@ describe('flux d’authentification', () => { expect(me.json()).toEqual({ authenticated: true, name: 'Alice' }); }); - it('POST /auth/logout vide la session', async () => { + it('POST /auth/logout vide la session (soumission de HTML)', async () => { const cookie = await login(app, idp); + // Le navigateur envoie un POST application/x-www-form-urlencoded : le serveur + // doit l'accepter (et non répondre 415). const out = await app.inject({ method: 'POST', url: '/auth/logout', + headers: { 'content-type': 'application/x-www-form-urlencoded' }, + payload: '', cookies: { [SESSION_COOKIE]: cookie }, }); expect(out.statusCode).toBe(302);