DEV Community

Cover image for Integrating KC Authorization Services into NestJS API
OUMERZOUG Haïtham
OUMERZOUG Haïtham

Posted on • Edited on

6

Integrating KC Authorization Services into NestJS API

In this article, we are going to connect between Keycloak Authorization Services and a real NestJS API. After setting up all the resources, scopes, policies, and permissions in Keycloak, it's time to see it in action.
We'll integrate Keycloak into our NestJS backend, protect specific endpoints based on permissions not just roles and test everything using Insomnia.

Like i always say if you're new to Keycloak, check out my previous articles:

So let's get started!

Application configuration

In this article, we'll build on the API code created in the Secure Your RESTful API Using Keycloak Role-Based Access Control article.

First let's define some constants :

  • resouces.ts : In this file, we define a list of resources that our application will work with.
export const RESOURCES = {
  USER: 'user',// user resource for /users/* endpoints
};
Enter fullscreen mode Exit fullscreen mode
  • scopes.ts: In this file, we define all the scopes that represent the actions users can perform on our resources.
export const SCOPES = {
  READ: 'read',
  WRITE: 'write',
  DELETE: 'delete',
};
Enter fullscreen mode Exit fullscreen mode

Now let's update our user.controller.ts file to stop relying on roles and instead use fine-grained permissions with scopes.

import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Post,
  Put,
} from '@nestjs/common';
import { Resource, Scopes } from 'nest-keycloak-connect';
import { RESOURCES } from './constants/resources';
import { SCOPES } from './constants/scopes';
import { User } from './models/user';
import { UserService } from './user.service';

@Controller('users')
@Resource(RESOURCES.USER)
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post('create')
  @Scopes(SCOPES.WRITE)
  createUser(@Body() payload: User) {
    return this.userService.createUser(payload);
  }

  @Put(':userId/update')
  @Scopes(SCOPES.WRITE)
  updateUser(@Param('userId') userId: number, @Body() payload: User) {
    return this.userService.updateUser(userId, payload);
  }

  @Delete('delete/:id')
  @Scopes(SCOPES.DELETE)
  deleteUser(@Param('id') id: number) {
    return this.userService.deleteUser(id);
  }

  @Get('all')
  @Scopes(SCOPES.READ)
  findAllUsers() {
    return this.userService.findAllUsers();
  }
}

Enter fullscreen mode Exit fullscreen mode

Test in Insomnia (or Postman)

  • Viewer User:

Viewer User

The viewer user, who has the viewer role, is granted access only to the /users/all endpoint, which is protected using the read scope.

Viewer: Read Users

If the viewer user tries to access other endpoints, they will receive a Forbidden error.

Viewer: Create Users

  • Manager User:

Manager User

The manager user, who has the manager role, is allowed to access endpoints protected by the read and write scopes — like viewing all users and creating new ones.

Manager User : Create User

However, if the manager tries to access an endpoint that requires the delete scope, they’ll receive a Forbidden error.

Manager User : Delete User

  • Admin User:

Admin User

The admin user, with the admin role, has full access to all user-related endpoints, including those protected by the read, write, and delete scopes.

As expected, all authorized requests from the admin user will succeed without any Forbidden errors.

Admin User: Delete User

Admin User: Read Users

Conclusion

And that's it! In this article, we've integrated Keycloak Authorization Services into a NestJS API and used fine-grained permissions to protect our endpoints. By replacing static role checks, we've unlocked a more powerful and flexible way to handle authorization.

Now your API can enforce access rules more cleanly, and users only get access to what they truly need. Much cleaner, much safer.

If you think the Keycloak series ends here, you're wrong! Next, we'll explore testing additional policy types, moving beyond just roles to enhance authorization flexibility even further.

Feel free to reach out if you have questions or feedback!

About the Author

Created by OUMERZOUG Haitham

Thanks for reading and stay tuned!

For builders shipping the next wave of software

For builders shipping the next wave of software

Whether it's agents, tools, or something brand new, Kinde gives you auth and billing that scale with your vision.

Get a free account

Top comments (2)

Collapse
 
alexander_mounir_70c5fa6a profile image
Alexander Mounir

Hello and thank you for the series! Any plans to continue with the contextual and ownership configurations?

Collapse
 
haithamoumer profile image
OUMERZOUG Haïtham • Edited

Hi! Thanks a lot for your feedback, I really appreciate it.
I'll be sharing how to enforce resource ownership, handle per-project or per-team roles, and use custom guards in NestJS.
Stay tuned, and feel free to suggest any specific use cases you'd like to see!

Feature flag article image

Create a feature flag in your IDE in 5 minutes with LaunchDarkly’s MCP server 🏁

How to create, evaluate, and modify flags from within your IDE or AI client using natural language with LaunchDarkly's new MCP server. Follow along with this tutorial for step by step instructions.

Read full post

Announcing the First DEV Education Track: "Build Apps with Google AI Studio"

The moment is here! We recently announced DEV Education Tracks, our new initiative to bring you structured learning paths directly from industry experts.

Dive in and Learn

DEV is bringing Education Tracks to the community. Dismiss if you're not interested. ❤️