Should student grade be accessible to all?? Preventing unnecessary access to information without requiring any identity or revealing data should happen in an application. In this article, we will see how it can be done safely by developing an application that lets students ask to see their grades.
On the frontend, we are going to use React and on the backend we will use Node.js, and Permit for access permission control. Following these instructions, you will make an application a very smooth, safe, and user-friendly experience.
Prerequisite
- Basic understanding of JavaScript and React : A prior knowledge about the basic javascript concepts along with familiarity in using react framework is a must on the frontend part for validation.
- Basic Node.js and Express knowledge: Learn the basics of Node. The backend server needs to setup and handle with js, for instance Express.
- Permit Account: Register for a Permit.
Setting Up Permit
Using Permit Elements, you can "share your app" with end users and know that they will have access control using a set of wide covering pre-built embeddable UI components which are fully functional.
Major Features of Permit Elements are;
- Advanced Security: Follows industry-standard protocols for secure, modern user identification.
- Automatically adjusts to different screen sizes, maintaining the same user experience regardless of platform. This is what you would call responsive design.
- Use custom stylistic: Using these you can make your website look and feel consistent.
- Basic Embedder: Pass and play for your Setup.
Implementing Access Request Element
A frontend component called Access Request Element enables users to request access to restricted or specific permission-required resources. If a request is made, it goes to the workspace owner who can choose either approve or deny.
It is an embedded, dedicated UI in your application for end-users to request dynamic updates on what they should be allowed access no matter if they are not being given it at the moment.
When a user sends in a request it goes to an "admin" role from the definition that you made on your User Management Element tagged under: This can be beneficial because it allows you to open access, by default restricted components.
Including the Access Request Element in your frontend app is really simple, users can click on this button "Request access" to request their permissions. These requests can then be managed and responded to within the "User Management" Element by admins.
The image below, will explain what would be seen when the Access Request element has been clicked;
What is the Connected User Management Element? This is a list of dropdowns of the created User Management element. The user Management element will be integrated with the Access-Request element. The Access Request Element will be triggered when a student wants to request access, the User Management will allow the student to be approved or denied.
Implementing User Management Element
With the help of the embeddable User Management Element, you can take command of your entire team and assign different team members varying degrees of access based on how they will be managing other team members.
The image above shows the User management element. Below is an image, which shows the properties in the User Management element;
The User Management element will integrate with the Access-Request element. This will be shown in the image below;
Connecting the Elements into your application
To connect these elements, you'd need to implement the iFrame for each element which will be shown below;
Copy the iFrame code generated above, and connect it to your frontend application. The generated iFrame code will look like the below;
<iframe
title="Permit Element Name"
src="https://embed.permit.io/<ELEMENT_NAME>?envId=<SOME_UNIQUE_ID>&darkMode=false&resourceInstanceKey=<RESOURCE_INSTANCE_KEY>&tenantKey=<TENANT_KEY>"
width="100%"
height="100%"
/>
In the coming sections, I will explain how to connect it with your front-end application.
Implementing the Backend Logic
In this one, we will be discussing at what type of works Permit is targeted to use. io for user management tasks including access control. A server offers an endpoint to grant access (and uses Permit) -ibm-dx-connect: io can authenticate all users with tenant ID and Api-key.
Server: It sets the middleware used for CORS
(Cross Origin Resource Sharing), cookies and parsing JSON
to be able to have a safe communication process. The main framework is contained in a route that takes the access request, authenticates it if valid and routes to associated controller area. Example of this setup is implemented as below;
npm install express @permitio/permit-js cookie-parser cors dotenv
const express = require("express");
const { Permit } = require("permitio");
const cookieParser = require("cookie-parser");
const cors = require("cors");
require('dotenv').config();
const TENANT = process.env.TENANT_ID
const apikey = process.env.PERMIT_API_KEY
const permit = new Permit({
pdp: "https://cloudpdp.api.permit.io",
token: apikey,
});
const app = express();
const port = 5000;
app.use(cors({ origin: "http://localhost:3000", credentials: true }));
app.use(cookieParser());
app.use(express.json());
app.get("/request_access", async (req, res) => {
try {
const {email} = req.body;
const result = await permit.elements.loginAs({
userId: email,
tenantId: TENANT,
});
if(result.token !== null){
return res.status(302).redirect(result.redirect_url);
}
return res.status(403).send({ message: result.error });
} catch (error) {
return res.status(500).json({ error: "Failed to request access" });
}
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
This code snippet above controls user access permissions that connects with Permit.io. The dotenv uses environment variables, CORS
for Cross-Origin Resource Sharing support, cookieParser
with what helps work with cookies in Js and Permit. The following steps will set the tenantID
and apikey on the server so that these can be accessed using environment variables with apikey
and Permit. When creating an instance of Permit from a PDP URL, Then we start the application and let it listen to port 5000
.
This line defines a route that handles GET requests to /request_access
. Upon a request to this endpoint, the server parses out the email from that request body and logs into requesting access using loginAs
method with another Payload instance referring again to Permit. Server logs in the redirect URL and redirects client to it with status 302
(Source)
If no token is sent back, it will reply a 403
status with an error message. All errors you face will return a 500
status response with error message.
Implementing the Frontend Logic
In this section, we will connect our Permit with our React application, including the iFrame component.
npx create-react-app secure-grades-viewer
The command above will initialize the React application.
npm install @permitio/permit-js
The command above, will install the Permit SDK
into your react application.
// Login.js
import React, { useEffect } from 'react';
import permit from '@permitio/permit-js';
import { LoginMethod } from '@permitio/permit-js/dist/types';
const backendURL = 'http://localhost:5000';
const loginUser = async () => {
try {
await permit.elements.login({
loginUrl: `${backendURL}/request_access`,
loginMethod: LoginMethod.cookie,
tenant: "default"
});
} catch (error) {
console.log(error, 'here is the error');
}
};
const logoutUser = async () => {
await permit.elements.logout();
};
const Login = () => {
useEffect(() => {
loginUser();
}, []);
return null;
};
export default Login;
The code above manages logging in the user interface by means of Permit.io. The code snippet above ensures that as soon as this component is installed, the login attempt will be made. The loginUser
function in this component will trigger the permit.elements.login
method, the backend URL
and the login method(cookie), tenant name. Wrapping loginUser
inside of useEffect
with an empty dependency array ensures that the login only happens once when this component is first rendered.
// CheckGrade.js
import React from 'react';
import { useNavigate } from 'react-router-dom';
const CheckGrade = () => {
const navigate = useNavigate();
const handleCheckGrade = () => {
const permitSession = document.cookie.split('; ').find(row => row.startsWith('permit_session='));
if (permitSession) {
navigate('/viewgrade');
} else {
navigate('/users-embed');
}
};
return (
<div>
<button onClick={handleCheckGrade} style={{ margin: '10px' }}>
Check your grade
</button>
</div>
);
};
export default CheckGrade;
The CheckGrade
component - checking for the presence of a cookie (permit_session) and redirecting using history. It uses the useNavigate
hook from react-router-dom
to navigate through code. This function gets called whenever the user presses "Check your grade" and when that happens we are going to send a request in handleCheckGrade
. It checks for the existence of a permit_session
cookie from within document cookies in this function.
If it exists, the user is using to be sent through /viewgrade
; if not they are redirected to the login form at /users-embed
. It can do a good job of centralizing the checking session status logic inside our application.
// UserEmbed.js
import React from 'react'
import { useNavigate } from 'react-router-dom'
export default function UsersEmbed() {
const nav = useNavigate()
return (
<div style={{height: '75vh'}}>
<button onClick={() => nav('/')} style={{margin: '10px'}}>Back</button>
<iframe
title="Permit Element request-student-access"
src="https://embed.permit.io/<ELEMENT_NAME>?envId=<SOME_UNIQUE_ID>&darkMode=false&resourceInstanceKey=<RESOURCE_INSTANCE_KEY>&tenantKey=<TENANT_KEY>"
width="100%"
height="100%"/>
</div>
)
}
Embedded Permit using UsersEmbed
Component ui interface for controlling student authorization requests in app. This is a button that does the navigation and an iFrame loading the Permit.io element. This makes it possible for you to work with external access management functionalities and keep navigation standards in your application.
// App.js
import React from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import UsersEmbed from './UsersEmbed';
import CheckGrade from './CheckGrade';
import Login from './Login';
function App() {
return (
<BrowserRouter>
<div className="App">
<Login />
<Routes>
<Route path="/" element={<CheckGrade />} />
<Route path="/users-embed" element={<UsersEmbed />} />
<Route path="/viewgrade" element={<ViewGrade />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
The App
component is where our app starts it specifies some of the routing uses a Login that lets you log in. Routing is handled by react-router-dom
, which we use BrowserRouter
to implement it The available routes in the application are defined inside the router via Routes component.
These routes are the root path ( / ), which makes use of CheckGrade
component, the users-embed /users-embed
, that renders UsersEmbed
Component and lastly a viewgrade /viewgrade
,that currently shows a placeholder for user grade details. This way the App
component stays abstracted enough to handle routes and use login logic within it.
To start the backend server, first run the following to make sure you are in line with all steps below:
npm run dev
To start your frontend application, you will run the command below;
npm start
So once a student wants to request for to view their result, they will see the image below;
So once the student has requested for access, the teacher who must be an admin, will see the following;
So once the teacher who is an admin, accepts the student's request, the student will be redirected to the /viewgrade
where the result shows.
Conclusion
In this article, we learned how user authentication and also handling controls through the use of Permit.io. Breaking it down into different steps (login, session validation and embedded access request) has taught us how to have in a modular approach that makes modifying code easy.
Top comments (0)