Authorization with decorators
Authorization of requests can be implemented using decorators that checks if a user is authorised and passes down useful information such as current user to the controller handler via metadata that can be accessed via req.vovk.meta()
method.
For an illustration, letβs create a simple authorization decorator that checks if a user is authorised and has the required permissions to access the resource. The authGuard
decorator below does the following:
- Checks if a user is authorised and returns an
Unauthorised
status if not. - Adds
currentUser
to the request metadata object, represented asAuthMeta
interface. - Implements role-based access control with
Permission
enum.
src/decorators/authGuard.ts
import { createDecorator, HttpException, HttpStatus, type VovkRequest } from 'vovk';
import type { User } from '@/types';
export enum Permission {
CAN_DO_THIS = 'CAN_DO_THIS',
CAN_DO_THAT = 'CAN_DO_THAT',
}
// Metadata interface allows to access the currentUser in the controller
export interface AuthMeta {
currentUser: User;
}
// Create a function that identifies the user, checks permissions and updates the request metadata
const checkAuth = async (req: VovkRequest, permission: Permission) => {
const currentUser = identifyUserAndCheckPermissions(req, permission);
if (!currentUser) {
return false;
}
// Add currentUser to the request metadata
req.vovk.meta<AuthMeta>({ currentUser });
return true;
};
// Create the decorator
const authGuard = createDecorator(async (req, next, permission: Permission) => {
const isAuthorized = await checkAuth(req, permission);
if (!isAuthorized) {
throw new HttpException(HttpStatus.UNAUTHORIZED, 'Unauthorized');
}
// The user is authorized, and the metadata is set; proceed to the next decorator or controller handler
return next();
});
export default authGuard;
Then import the authGuard
decorator and related members and apply it to the controller methods, passing it after the @get
, @post
, etc. decorators.
src/modules/user/UserController.ts
import { get, prefix } from 'vovk';
import { openapi } from 'vovk-openapi';
import authGuard, { Permission, type AuthMeta } from '../decorators/authGuard';
@prefix('users')
export default class UserController {
// ...
@openapi({
summary: 'Get something',
description: 'Returns something',
})
@get('something')
@authGuard(Permission.CAN_DO_THIS)
static async getSomething(req: VovkRequest) {
const { currentUser } = req.vovk.meta<AuthMeta>();
// ...
}
// ...
}
Last updated on