DEV Community

Cover image for Part 2: Master Authentication and Role-Based Access Control (RBAC) with Kinde and Convex in a File-Sharing Application
Shola Jegede
Shola Jegede

Posted on

Part 2: Master Authentication and Role-Based Access Control (RBAC) with Kinde and Convex in a File-Sharing Application

This is the Part 2 to this post: Part 1: Master Authentication and Role-Based Access Control (RBAC) with Kinde and Convex in a File-Sharing Application.

In this guide, we'll dive into building a secure and scalable file-sharing platform powered by Next.js, Kinde Auth, Convex DB, Shadcn UI, and TypeScript. This is a continuation of our journey with Kinde, focusing on advanced Role-Based Access Control (RBAC) concepts, configuration, and implementation.

Introduction

In Part 1, we integrated Kinde Auth and Convex DB with Next.js for passwordless authentication and basic RBAC. In this tutorial, we’ll expand on:

  1. Advanced RBAC concepts and use cases.
  2. Configuring roles and permissions in Kinde.
  3. Implementing RBAC in a production-ready app (e.g., a file-sharing platform).

This tutorial assumes familiarity with basic Kinde setup.

SwiftShare App Preview

Understanding Role-Based Access Control (RBAC)

What is RBAC?

RBAC is a security model that assigns permissions to users based on their roles. Here, we can dive deeper into the concepts behind RBAC, focusing on how roles map to permissions and how users are granted access. Here’s a more detailed explanation:

  • Roles: Represent job functions or responsibilities within the system or organization (e.g., Admin, User, Manager, Support).
  • Permissions: Define what actions users in specific roles are allowed to perform (e.g., upload, view, delete, edit, share).
  • Users: Assigned roles, which determine their access levels and what actions they can perform within the application.

In our file-sharing app, the roles we would be assigning would look like this:

  • Admin: Can manage users, files, and settings. Can also upload, edit, share, and delete files.
  • Basic User: Can upload, view and download files, but cannot edit, delete or manage files or users.

Why RBAC?

  1. Security: RBAC ensures that only authorized users can access sensitive actions and data. It limits the risk of unauthorized actions, especially in a file-sharing platform where sensitive documents may be involved.

  2. Scalability: As your app grows and more users are onboarded, roles allow you to efficiently manage permissions without having to update each individual user's permissions manually.

  3. Efficiency: By defining clear roles, you streamline the process of role assignments. New users can simply be assigned a predefined role with a specific set of permissions, reducing complexity.

Preview of the Application

Our file-sharing application includes the following features:

  • File Uploads
    Users can upload documents, images, videos, audios and more.
    File uploads

  • File Functionalities
    View details, edit, share, download, and delete files.
    File functions dropdown

File sharing

  • File Sorting
    Organize files by creation date, name, or size.
    File sorting

  • Global Search
    Quickly find files across the organization.Global search capabilities

RBAC Implementation with Kinde

Step 1: Setting Up Permissions

For this application, we have created five (5) different permissions for our users. Permissions define what actions users can perform:

  • Upload File: Allows the user to upload files to the platform.
  • View File Details: Grants users the ability to view details of a file, such as size, name, and metadata.
  • Edit File: Lets users edit file details, such as renaming files.
  • Share File: Allows sharing a file with other users.
  • Delete File: Lets users delete files from the platform.

These permissions are mapped to roles in Kinde. This step enables admins to easily assign these permissions to various roles, ensuring that only authorized users can perform specific actions.
Permissions setup in Kinde

Step 2: Creating Roles

Next, we define the roles that will be assigned to users. For our file-sharing platform, we define the following roles:

  • Admin: Full access to all file operations.
  • Basic User: Can upload and view details of files, but cannot edit, share or delete files. Creating roles in Kinde

These roles are configured in the Kinde Dashboard, where admins can assign permissions to each role. This ensures that users have exactly the permissions they need without unnecessary access.
Toggle assign roles to new members

Toggle permissions for Basic Users

Ensure to toggle "Assign to new members", that way every new user that signs up to our application would be assigned a "Basic User" role by default with only two permissions:

  • The ability to upload a new file to the organization
  • The ability to view details of all files within the organization

They will not be able to:

  • Edit or update a file
  • Share a file
  • Delete a file

Step 3: Assigning Roles to Users

By default, new users are assigned the Basic User. Admins can assign other roles if need be such as Editor or Sub-Admin to users based on their responsibilities.

To update a user’s role in Kinde:

  • Go to the Users tab in your Kinde Dashboard.
  • Select a user and navigate to their profile.
  • Assign a new role. Assigning roles in Kinde

UI-Level RBAC Implementation

Now that we've configured the roles and permissions in Kinde, we’ll implement RBAC at the UI level in our file-sharing app. This will allow us to conditionally render UI elements based on the permissions of the currently authenticated user.

Step 4: Integrating Permissions into the UI

We'll use the useKindeBrowserClient hook to fetch user roles and permissions, and then use these permissions to control the visibility and interactivity of various features in the UI. This will allow us to show or hide buttons, dropdown items, and other components based on the user's role.

Usage 1: File Uploader
The FileUploader component shows an upload button. We’ll check if the user has permission to upload files.

const FileUploader = ({ ownerId, accountId, className }: Props) => {
  const { getPermission } = useKindeBrowserClient();

  // Check if user has permission to upload files
  const canUploadFile = getPermission("upload:file");

  if (!canUploadFile?.isGranted) {
    return <div>Access denied</div>;
  }

  return (
    <div {...getRootProps()}>
      <Button type="button">Upload</Button>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • This component uses getPermission("upload:file") to check if the user has permission to upload files.
  • If the permission is not granted, the component shows an "Access Denied" message instead of the upload button.

Usage 2: Action Dropdown
The ActionDropdown component handles file actions (like view, edit, share, delete). We'll filter these actions based on user permissions.

const ActionDropdown: React.FC<FileCardProps> = ({
  fileId,
  storageId,
  fileName,
  url,
  type,
  size,
  createdAt,
  extension,
  users,
  creator,
}) => {
  const { getPermission } = useKindeBrowserClient();

  // Fetch permissions for each action
  const canViewFileDetails = getPermission("view:file");
  const canEditFile = getPermission("edit:file");
  const canShareFile = getPermission("share:file");
  const canDeleteFile = getPermission("delete:file");

  return (
    <DropdownMenu>
      {/* Action items */}
      {actionsDropdownItems
        .filter((actionItem) => {
          if (actionItem.value === "details") {
            return canViewFileDetails?.isGranted;
          }
          if (actionItem.value === "rename") {
            return canEditFile?.isGranted;
          }
          if (actionItem.value === "delete") {
            return canDeleteFile?.isGranted;
          }
          if (actionItem.value === "share") {
            return canShareFile?.isGranted;
          }
          return true;
        })
        .map((actionItem) => (
          <DropdownMenuItem
            key={actionItem.value}
            onClick={() => { /* handle action */ }}
          >
            {actionItem.label}
          </DropdownMenuItem>
        ))}
    </DropdownMenu>
  );
};
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • The getPermission("view:file"), getPermission("edit:file"), etc., are used to check the user's permissions.
  • The actions displayed in the dropdown are filtered based on whether the user has permission for those actions.
  • For instance, a user without the "edit:file" permission will not see the "rename" option

After implementation, the dropdown actions UI would look something like this, restricting Basic Users to only the ability to view and download a file:
Dropdown action UI

And if we were to restrict Basic Users from uploading files to the application from our Kinde Dashboard:
Restrict upload functionality in Kinde

You would also see that they have now be denied access to uploading a file to the application:
Upload access denied

Best Practices for RBAC

  1. Granular Permissions: It’s better to have more granular permissions (e.g., “Can edit metadata” vs. “Can edit file”) rather than assigning overly broad permissions to roles. This helps avoid unnecessary access and keeps your system secure.
  2. Custom Roles: Rather than using predefined roles, create custom roles tailored to your specific app. For instance, you could have a role like Manager who can approve files for sharing, or a Contributor who can upload but not edit or delete files.
  3. Periodic Audits: As your application grows, regularly review roles and permissions. Conducting audits helps ensure that users have appropriate access and prevents privilege creep.

Conclusion

By combining Next.js, Kinde Auth, and Convex DB, we’ve built a secure and scalable file-sharing platform. Advanced RBAC ensures that users only perform actions relevant to their assigned roles, enhancing both security and efficiency.

With the integration of RBAC at the UI level, we've built a flexible and user-friendly system that securely controls access to app features based on user roles. This ensures that users can only access what they are permitted to, while admins have full control over the platform.

Ready to get started? Head to Kinde and build your next app today!

Further Reading:

Access the Full Codebase

Want to explore the complete implementation of the file-sharing application? Check out the codebase on GitHub. Feel free to clone, experiment, and adapt it to your needs. Contributions and stars are always welcome!

GitHub logo sholajegede / swiftshare

Effortlessly store, share, and access your files anywhere with a secure, lightning-fast cloud solution.

This is a Next.js project bootstrapped with create-next-app.

Getting Started

First, run the development server:

npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:3000 with your browser to see the result.

You can start editing the page by modifying app/page.tsx. The page auto-updates as you edit the file.

This project uses next/font to automatically optimize and load Geist, a new font family for Vercel.

Learn More

To learn more about Next.js, take a look at the following resources:

You can check out the Next.js GitHub repository - your feedback and contributions are welcome!

Deploy on Vercel

The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.

Check out our Next.js deployment documentation for more…




We’d love to hear from you!

Got thoughts, questions, or suggestions? Drop them in the comments below or reach out to me directly on GitHub. Your feedback helps to improve and ensures we cover everything you need to succeed. Let us know what you think—let’s build together!

Top comments (0)