Skip to main content

Locking routes behind authentication

When writing an API that is publicly available for consumption, it is often desirable to lock some routes behind them requiring authentication. For example routes that would interact with your database. On this page we will guide you to write your own authentication system that integrates with Sapphire.

Because authentication with the built-in OAUTH2 system always adds a request.auth property it is actually quite easy to ensure a request is authenticated before processing it any further! The following code will check if request.auth.token is defined or not. When it is not, we exit out of the function with a 401 Unauthorized response.

const { HttpCodes, methods, Route } = require('@sapphire/plugin-api');
const { isNullishOrEmpty } = require('@sapphire/utilities');

class MyRoute extends Route {
async [methods.POST](request, response) {
if (isNullishOrEmpty(request.auth?.token)) return response.error(HttpCodes.Unauthorized);
}
}
module.exports = {
MyRoute
};

An alternative way to implement this that is currently only possible for TypeScript users is by writing a decorator that does the check. This allows your code to be a bit cleaner, as you can remove the if statement and instead provide the decorator. A decorator that does the authentication check can look like:

const { createFunctionPrecondition } = require('@sapphire/decorators');
const { HttpCodes } = require('@sapphire/plugin-api');

const authenticated = () =>
createFunctionPrecondition(
(request) => Boolean(request.auth?.token),
(_request, response) => response.error(HttpCodes.Unauthorized)
);
module.exports = {
authenticated
};

You can then use the decorator on your route like so:

import { methods, Route, type ApiRequest, type ApiResponse } from '@sapphire/plugin-api';

export class MyRoute extends Route {
@authenticated()
public [methods.POST](request: ApiRequest, response: ApiResponse) {
// Implementation
}
}