Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions packages/auth0-fastify-api/src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ afterEach(() => {
server.resetHandlers();
});

test('should return 400 when no token', async () => {
test('should return 401 when no authorization header', async () => {
const fastify = Fastify();
fastify.register(fastifyAuth0Api, {
domain: domain,
Expand All @@ -77,9 +77,43 @@ 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');
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: '<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('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 () => {
Expand Down
41 changes: 28 additions & 13 deletions packages/auth0-fastify-api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually have to have an auth-param component here in order for the www-authenticate to be valid as per its definition.

This can the form of WWW-Authenticate: Bearer realm="${currentUrlOrSomeArbitraryIdentifier}"

: `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, 400, 'invalid_request', 'No Authorization provided');
// If the authorization header was malformed, we need to return a 400.
return replyWithError(reply, 400, 'invalid_request', 'Invalid Authorization provided');
}

try {
Expand All @@ -110,7 +126,6 @@ async function auth0FastifApi(fastify: FastifyInstance, options: Auth0FastifyApi
});
}


export default fp(auth0FastifApi);

function getToken(request: FastifyRequest): string | undefined {
Expand Down