From f43efc2d7c0d3b9da928241ea84258dac2d697c4 Mon Sep 17 00:00:00 2001 From: Frederik Prijck Date: Tue, 1 Apr 2025 10:34:45 +0200 Subject: [PATCH 1/4] fix(auth0-fastify-api): Use 401 instead of 400 when no access token provided --- packages/auth0-fastify-api/src/index.spec.ts | 4 ++-- packages/auth0-fastify-api/src/index.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/auth0-fastify-api/src/index.spec.ts b/packages/auth0-fastify-api/src/index.spec.ts index 25d0fd3..44dc0cd 100644 --- a/packages/auth0-fastify-api/src/index.spec.ts +++ b/packages/auth0-fastify-api/src/index.spec.ts @@ -53,7 +53,7 @@ afterEach(() => { server.resetHandlers(); }); -test('should return 400 when no token', async () => { +test('should return 401 when no token', async () => { const fastify = Fastify(); fastify.register(fastifyAuth0Api, { domain: domain, @@ -77,7 +77,7 @@ test('should return 400 when no token', async () => { url: '/test', }); - expect(res.statusCode).toBe(400); + expect(res.statusCode).toBe(401); expect(res.json().error).toBe('invalid_request'); expect(res.json().error_description).toBe('No Authorization provided'); }); diff --git a/packages/auth0-fastify-api/src/index.ts b/packages/auth0-fastify-api/src/index.ts index 3ef7ea5..97e25b5 100644 --- a/packages/auth0-fastify-api/src/index.ts +++ b/packages/auth0-fastify-api/src/index.ts @@ -83,7 +83,7 @@ async function auth0FastifApi(fastify: FastifyInstance, options: Auth0FastifyApi const accessToken = getToken(request); if (!accessToken) { - return replyWithError(reply, 400, 'invalid_request', 'No Authorization provided'); + return replyWithError(reply, 401, 'invalid_request', 'No Authorization provided'); } try { From 690e29b03a3fb1799b292b73e6e6f82372dbafe3 Mon Sep 17 00:00:00 2001 From: Frederik Prijck Date: Thu, 10 Apr 2025 09:38:30 +0200 Subject: [PATCH 2/4] fix --- packages/auth0-fastify-api/src/index.spec.ts | 36 ++++++++++++++++- packages/auth0-fastify-api/src/index.ts | 41 +++++++++++++------- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/packages/auth0-fastify-api/src/index.spec.ts b/packages/auth0-fastify-api/src/index.spec.ts index 44dc0cd..8b0ecbf 100644 --- a/packages/auth0-fastify-api/src/index.spec.ts +++ b/packages/auth0-fastify-api/src/index.spec.ts @@ -53,7 +53,7 @@ afterEach(() => { server.resetHandlers(); }); -test('should return 401 when no token', async () => { +test('should return 401 when no authorization header', async () => { const fastify = Fastify(); fastify.register(fastifyAuth0Api, { domain: domain, @@ -80,6 +80,40 @@ test('should return 401 when no token', async () => { expect(res.statusCode).toBe(401); expect(res.json().error).toBe('invalid_request'); expect(res.json().error_description).toBe('No Authorization provided'); + expect(res.headers['www-authenticate']).toBe('Bearer'); +}); + +test('should return 400 when invalid authorization header', async () => { + const fastify = Fastify(); + fastify.register(fastifyAuth0Api, { + domain: domain, + audience: '', + }); + + fastify.register(() => { + fastify.get( + '/test', + { + preHandler: fastify.requireAuth(), + }, + async () => { + return 'OK'; + } + ); + }); + + const res = await fastify.inject({ + method: 'GET', + url: '/test', + headers: { + authorization: 'Bearer' + } + }); + + expect(res.statusCode).toBe(400); + expect(res.json().error).toBe('invalid_request'); + expect(res.json().error_description).toBe('No Authorization provided'); + expect(res.headers['www-authenticate']).toBe('Bearer error="invalid_request", error_description="No Authorization provided"'); }); test('should return 200 when valid token', async () => { diff --git a/packages/auth0-fastify-api/src/index.ts b/packages/auth0-fastify-api/src/index.ts index 97e25b5..4fbd0fd 100644 --- a/packages/auth0-fastify-api/src/index.ts +++ b/packages/auth0-fastify-api/src/index.ts @@ -65,25 +65,41 @@ async function auth0FastifApi(fastify: FastifyInstance, options: Auth0FastifyApi customFetch: options.customFetch, }); - const replyWithError = (reply: FastifyReply, statusCode: number, error: string, errorDescription: string) => { - return reply - .code(statusCode) - .header( - 'WWW-Authenticate', - `Bearer error="${error.replaceAll('"', '\\"')}", error_description="${errorDescription.replaceAll('"', '\\"')}"` - ) - .send({ - error: error, - error_description: errorDescription, - }); + const replyWithError = ( + reply: FastifyReply, + statusCode: number, + error: string, + errorDescription: string, + ommitHeaderDetails = false + ) => { + const headerValue = ommitHeaderDetails + ? `Bearer` + : `Bearer error="${error.replaceAll('"', '\\"')}", error_description="${errorDescription.replaceAll( + '"', + '\\"' + )}"`; + + return reply.code(statusCode).header('WWW-Authenticate', headerValue).send({ + error: error, + error_description: errorDescription, + }); }; fastify.decorate('requireAuth', function (opts: AuthRouteOptions = {}) { return async function (request: FastifyRequest, reply: FastifyReply) { + const authorizationHeader = request.headers.authorization; + + if (!authorizationHeader) { + // If there is no authorization header, + // we need to return a 401 with just the supported scheme and no error/error_description in www-authenticate. + return replyWithError(reply, 401, 'invalid_request', 'No Authorization provided', true); + } + const accessToken = getToken(request); if (!accessToken) { - return replyWithError(reply, 401, 'invalid_request', 'No Authorization provided'); + // If the authorization header was malformed, we need to return a 400. + return replyWithError(reply, 400, 'invalid_request', 'No Authorization provided'); } try { @@ -110,7 +126,6 @@ async function auth0FastifApi(fastify: FastifyInstance, options: Auth0FastifyApi }); } - export default fp(auth0FastifApi); function getToken(request: FastifyRequest): string | undefined { From bc31e7a0524b64361f171a269f1f9916b334b0ca Mon Sep 17 00:00:00 2001 From: Frederik Prijck Date: Thu, 10 Apr 2025 09:40:55 +0200 Subject: [PATCH 3/4] fix --- packages/auth0-fastify-api/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth0-fastify-api/src/index.ts b/packages/auth0-fastify-api/src/index.ts index 4fbd0fd..310a768 100644 --- a/packages/auth0-fastify-api/src/index.ts +++ b/packages/auth0-fastify-api/src/index.ts @@ -99,7 +99,7 @@ async function auth0FastifApi(fastify: FastifyInstance, options: Auth0FastifyApi if (!accessToken) { // If the authorization header was malformed, we need to return a 400. - return replyWithError(reply, 400, 'invalid_request', 'No Authorization provided'); + return replyWithError(reply, 400, 'invalid_request', 'Invalid Authorization provided'); } try { From f32e52318c5855a96fa5f70be3f55747d2f29c0e Mon Sep 17 00:00:00 2001 From: Frederik Prijck Date: Thu, 10 Apr 2025 09:41:39 +0200 Subject: [PATCH 4/4] fix test --- packages/auth0-fastify-api/src/index.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/auth0-fastify-api/src/index.spec.ts b/packages/auth0-fastify-api/src/index.spec.ts index 8b0ecbf..1c6f42c 100644 --- a/packages/auth0-fastify-api/src/index.spec.ts +++ b/packages/auth0-fastify-api/src/index.spec.ts @@ -112,8 +112,8 @@ test('should return 400 when invalid authorization header', async () => { expect(res.statusCode).toBe(400); expect(res.json().error).toBe('invalid_request'); - expect(res.json().error_description).toBe('No Authorization provided'); - expect(res.headers['www-authenticate']).toBe('Bearer error="invalid_request", error_description="No Authorization provided"'); + expect(res.json().error_description).toBe('Invalid Authorization provided'); + expect(res.headers['www-authenticate']).toBe('Bearer error="invalid_request", error_description="Invalid Authorization provided"'); }); test('should return 200 when valid token', async () => {