Authentication (JWT)

Nova provides first-class JWT authentication support through the Auth class and authentication decorators.

Setup

Register the JWT plugin via app.security():

main.ts TypeScript
import { NovaFactory, Auth } from '@abrahambass/nova';

const app = await NovaFactory.create();

await app.security(
  Auth.jwt({
    secret: 'your-secret-key',
  })
);

Auth.jwt(options)

Registers @fastify/jwt with the given options. It accepts all @fastify/jwt options.

PropertyTypeRequiredDescription
secret string Required Secret key for signing tokens.
cookie object Optional When provided, @fastify/cookie is also registered and JWT is read from cookies.

JWT with Cookies

main.ts TypeScript
await app.security(
  Auth.jwt({
    secret: 'your-secret-key',
    cookie: {
      cookieName: 'token',
      signed: false,
    },
  })
);

@RequiresAuth()

Marks a controller or method as requiring authentication. The JWT is verified automatically before the handler runs.

Can be applied to:

  • Class level — All methods require authentication
  • Method level — Only that specific method requires authentication
Example TypeScript
import { Controller, Get, RequiresAuth, CurrentUser } from '@abrahambass/nova';

// Controller-level: all methods require auth
@RequiresAuth()
@Controller('/profile')
class ProfileController {

  @Get()
  async getProfile(@CurrentUser() user: any) {
    return user;
  }
}

// Method-level: only this method requires auth
@Controller('/items')
class ItemController {

  @Get()    // public
  async findAll() { ... }

  @RequiresAuth()
  @Get('/mine')    // requires JWT
  async findMine(@CurrentUser() user: any) { ... }
}

@Scopes(...scopes)

Restricts access to users with specific scopes in their JWT payload. The JWT payload must include a scopes array.

ParameterTypeRequiredDescription
scopes string[] Required List of scopes. The user must have at least one matching scope.
Example TypeScript
import { RequiresAuth, Scopes, Delet } from '@abrahambass/nova';

@RequiresAuth()
@Controller('/admin')
class AdminController {

  @Scopes('admin', 'super-admin')
  @Delet('/:id')
  async deleteUser(@Path('id') id: number) {
    // Only users with 'admin' or 'super-admin' scope
    return { deleted: id };
  }
}
💡 JWT Payload Format

For @Scopes to work, the JWT payload must contain a scopes array, e.g.: { "sub": 1, "scopes": ["admin", "user"] }