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:
- Advanced RBAC concepts and use cases.
- Configuring roles and permissions in Kinde.
- Implementing RBAC in a production-ready app (e.g., a file-sharing platform).
This tutorial assumes familiarity with basic Kinde setup.
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?
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.
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.
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 Functionalities
View details, edit, share, download, and delete files.
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.
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.
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.
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.
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>
);
};
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>
);
};
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:
And if we were to restrict Basic Users from uploading files to the application from our Kinde Dashboard:
You would also see that they have now be denied access to uploading a file to the application:
Best Practices for RBAC
- 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.
- 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.
- 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!
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
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:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
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)