Introduction
In one of my recent projects, I needed to manage user permissions to access private & sensitive contents. But while implementing the solution, I struggled a lot.
After researching the problem, I found a solution that resolved the issue. That’s when I thought of writing this article.
In this article, we will be building a private link-sharing app using Next.js and Permit.io. Through the implementation, we will explore how to handle access requests, manage approvals, and enforce permissions to protect sensitive data.
Prerequisites
To build this application, we will be using Next.js with “Permit Share-If,” which simplifies permission management. “Permit Share-If” is a suite of prebuilt, embeddable UI components that make access sharing in applications a breeze.
Before moving on to the main part, make sure you know the basics of Next.js structure. If you want, you can read more from here
To implement Permit.io into the Next.js application, you first need to set up Permit.io. Let’s begin
Building a private link-sharing app
Setup Next.js project
To get started, let’s create a Next.js project.
- Open a terminal and paste the command to create a new Next.js project.
npx create-next-app@latest .
- Next, we’ll Install the required dependencies
npm install @permitio/permit-js dotenv permitio
- Now we will create a
.env
file to storeENV
&JWT
secrets.
// .env
ENV=<permit env key>
JWT=<your JWT key>
Now that the app is ready to go, we’ve successfully built the project.
Add the Access request Element
To create an access request element, you first need to create a user management element. Let’s create it.
- Go to the Elements section of the permit dashboard
- Click on “Create Element.” option Under the User Management
- Set up the user management element by following these steps:
- Add a name, i.e. “User Management.”
- Choose the RBAC role
- Move the admin role from the ”Hidden Roles” section to “Level 1 – Workspace Owner.”
- And last, create the element.
User management creation is complete; let’s jump onto the next part.
- Click on the Elements option
- Under the Access request, click on “Create Element.”
- Choose the user management element you want to connect.
- Customize the element as needed
Implement the Access Request Element within the application.
- Create a component called
Linklist
for our project- The
Linklist
component displays a list of links and provides an option to delete any of them. - The components render an unordered list with a delete button.
- The
// src/components/Linklist.jsx
const LinkList=({ links, deleteLink }) => { return ( <ul> {links.map((link, index) => ( <li key={index}> <a href={link} target="_blank" rel="noopener noreferrer">{link}</a> <button onClick={() => deleteLink(index)}>Delete</button> </li> ))} </ul> );
}; export default LinkList;
- Create a component named
Linkform
for adding links by users.
// src/components/Linkform.jsx
import { useState } from 'react'; const LinkForm=({ addLink }) => { const [url, setUrl] = useState(''); const handleSubmit = (e) => { e.preventDefault(); if (url) { addLink(url); setUrl(''); } }; return ( <form onSubmit={handleSubmit}> <input className='text-black' type="url" value={url} onChange={(e) => setUrl(e.target.value)} placeholder="Enter URL" required /> <button type="submit">Add Link</button> </form> );
}; export default LinkForm;
Here, when a user triggers the Add Link button, it will add links.
- Now we have to create another component for user management named
UserManagement.jsx
import React from 'react' function UserManagement() { return (
<iframe
title="Permit Element user-management"
src="https://embed.permit.io/user-management?envId=e0ffba3632274e8085d92c793d34f0c1&darkMode=false"
width="100%"
height="100%"
/> )
} export default UserManagement;
- Now we have to create another components for access request named
AccessRequest.jsx
import React from 'react' function AccessRequest() { return ( <iframe title="Permit Element AR" src="https://embed.permit.io/ar?envId=e0ffba3632274e8085d92c793d34f0c1&darkMode=false&tenantKey=default" width="100%" height="100%" style={{ border: 'none' }} /> )
} export default AccessRequest;
- Next, Create another component for
Dashboard
that will use Permit Share-If
// src/components/Dashboard.jsx 'use client';
import permit, { LoginMethod } from '@permitio/permit-js';
import 'dotenv/config';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react'; const Dashboard = () => { const router=useRouter(); const [authenticated, setAuthenticated]=useState(false); useEffect(() => { const login=async () => { try { await permit.elements.login({ loginMethod: LoginMethod.frontendOnly, userJwt: process.env.NEXT_PUBLIC_JWT, tenant: 'default', envId: process.env.NEXT_PUBLIC_ENV, }); console.log('Login successful'); setAuthenticated(true); } catch (err) { console.error('Login error:', err); } }; if (process.env.NEXT_PUBLIC_JWT&&process.env.NEXT_PUBLIC_ENV) { login(); } else { console.error('JWT token or ENV variable is not defined.'); } }, []); useEffect(() => { if (authenticated) { router.push('/links'); } }, [authenticated, router]); return ( <AccessRequest /> <UserManagement /> );
}; export default Dashboard;
Here we have implemented auth, redirection & rendering now let’s understand a little bit about these
Authentication Handling: alogin
function that tries to authenticate the user usingpermit.elements.login
.Usesprocess.env.NEXT_PUBLIC_JWT
andprocess.env.NEXT_PUBLIC_ENV
from environment variables for authentication.
If authentication succeeds, it updates the state to indicate that the user is authenticated. Logs a success message or an error message if authentication fails.
Redirection: When authentication is successful, the component redirects the user to the /links
page.
Rendering: Displays two different
iframe
by calling the components that embeds access request element from Permit.io.
Now we have to call the AccessRequest component on the page.js
file
import Dashboard from '../components/Dashboard'; export default function Home() { return ( <div> <h1>Private Link Sharing App</h1> <Dashboard/> </div> );
}
Lastly, implement the link page route that will handle the link page.
// src/app/links/page.jsx
'use client';
import LinkForm from '@/components/Linkform';
import LinkList from '@/components/Linklist';
import { useState } from 'react'; const Links=() => { const [links, setLinks] = useState([]); const addLink=(url) => { setLinks([...links, url]); }; const deleteLink = (index) => { setLinks(links.filter((_, i) => i!==index)); }; return ( <div className='p-5'> <h1>Manage Links</h1> <LinkForm addLink={addLink} /> <LinkList links={links} deleteLink={deleteLink} /> </div> );
}; export default Links;
With that, our application is fully complete.
Conclusion
By reading this guide, you have understood how to create a private link-sharing app using Next.js and Permit.io. You read about making access requests, approving the users, and permissions to be implemented to protect your private information.
If you want to explore and build more similar tools using Permit, check out their latest Product Hunt launch, “Permit Share-If,” and find out more about it.
Also, if you have any questions, feel free to write them in the comments.
Happy Coding!