{"version":"https://jsonfeed.org/version/1.1","title":"Aghoghomena Akasukpe: Writing","home_page_url":"https://www.aghoghomena.com/writing","feed_url":"https://www.aghoghomena.com/feed.json","description":"Building and breaking agent systems.","authors":[{"name":"Aghoghomena Akasukpe"}],"language":"en","items":[{"id":"https://www.aghoghomena.com/writing/agent-reliability-is-a-systems-problem","url":"https://www.aghoghomena.com/writing/agent-reliability-is-a-systems-problem","title":"Agent reliability is a systems problem, not a prompt problem","summary":"Most agent failures I see in production are not bad prompts. They are missing boundaries, missing observability, and a planning loop nobody can inspect.","content_html":"<p>The first thing teams try when an agent misbehaves is a better prompt. It\nis the cheapest lever and it is almost never the one that was broken.</p>\n<p>In production, the failures cluster somewhere else: a tool returns\nsomething the plan did not anticipate, that output re-enters context, and\nthree steps later the agent is confidently doing the wrong thing. No\nprompt change fixes that, because the prompt was never the problem. The\nloop was.</p>\n<h2>The three things that actually fail</h2>\n<p><strong>Boundaries.</strong> A tool-using agent runs real actions against real state:\nfiles, APIs, code. If the only thing standing between a mis-planned call\nand your filesystem is a sentence in a system prompt, you do not have a\nboundary. You have a suggestion.</p>\n<p><strong>Observability.</strong> If you cannot replay why the agent did what it did,\nstep by step, you are not debugging. You are guessing with extra latency.</p>\n<p><strong>Loop integrity.</strong> The reflection step is the highest-leverage and\nleast-watched part of most agent systems. It is where a bad tool result\ndoes the most damage and where teams instrument the least.</p>\n<h2>What I do instead</h2>\n<p>I treat the agent as a distributed system whose inputs I don't trust\nblindly. Validate at the execution boundary, make every refusal a\nstructured event the agent can reason about, and instrument the loop before\ntuning the prose. The prompt is the last thing I touch, not the first.</p>","date_published":"2026-04-22T00:00:00.000Z","tags":["agent-systems","reliability","architecture"]},{"id":"https://www.aghoghomena.com/writing/pst2025-industry-summit","url":"https://www.aghoghomena.com/writing/pst2025-industry-summit","title":"PST2025 Industry Summit: reflections and key takeaways","summary":"Field notes from the 2025 Privacy, Security and Trust Industry Summit: AI as a threat amplifier, cyber attribution, and agentic-AI risk frameworks from TD Bank, Mastercard, and the CIC.","content_html":"<p>Proud to have attended the 2025 Privacy, Security and Trust Industry Summit at the <a href=\"https://ca.linkedin.com/company/fredericton-convention-centre\">Fredericton Convention Centre</a>, hosted by the <a href=\"https://ca.linkedin.com/company/canadian_institute_cybersecurity\">Canadian Institute for Cybersecurity</a> at <a href=\"https://ca.linkedin.com/school/university-of-new-brunswick/\">University of New Brunswick</a>. Incredible lineup of keynote speakers included leading organizations like <a href=\"https://www.linkedin.com/company/td\">TD</a> Bank, <a href=\"https://ca.linkedin.com/company/scotiabank\">Scotiabank</a>, <a href=\"https://ca.linkedin.com/company/sun-life-financial\">Sun Life</a>, <a href=\"https://www.linkedin.com/company/mastercard\">Mastercard</a>, and more, who all shared critical insights on the evolving digital threat landscape.</p>\n<p><strong>Disclaimer:</strong> The views and opinions expressed here are my own and do not represent those of any organization I am affiliated with. As a graduate researcher and engineer attending the 2025 Privacy, Security and Trust Industry Summit to present our recent publication, my reflections are shared purely from an academic and professional perspective.</p>\n<figure>\n  <img src=\"/blog/pst2025-industry-summit/img-2.jpg\" alt=\"Keynote speakers for the 2025 Privacy, Security and Trust Industry Summit, held on August 26 at the Fredericton Convention Center. Hosted by the Canadian Institute for Cybersecurity at University of New Brunswick (UNB).\">\n  <figcaption>Keynote speakers for the 2025 Privacy, Security and Trust Industry Summit, held on August 26 at the Fredericton Convention Center. Hosted by the Canadian Institute for Cybersecurity at University of New Brunswick (UNB).</figcaption>\n</figure>\n<h3>Opening Addresses and Keynote Highlights</h3>\n<p>The event opened with a powerful keynote address delivered by Dr. <a href=\"https://ca.linkedin.com/in/ali-a-ghorbani-122872b\">Ali A. Ghorbani</a>, Director of the <a href=\"https://ca.linkedin.com/company/canadian_institute_cybersecurity\">Canadian Institute for Cybersecurity</a>, accompanied by an outstanding team of interdisciplinary support staff, many of whom he acknowledged repeatedly throughout his remarks and afterwards. His leadership, expertise, and genuine gratitude left a strong impression on all in attendance. Dr. <a href=\"https://ca.linkedin.com/in/paul-mazerolle-31232858\">Paul Mazerolle</a>, President and Vice-Chancellor of the <a href=\"https://ca.linkedin.com/school/university-of-new-brunswick/\">University of New Brunswick</a>, followed with a warm welcome that set the stage for distinguished government officials to address the gathering.</p>\n<h3>Insights from Federal Government Leaders</h3>\n<figure>\n  <img src=\"/blog/pst2025-industry-summit/img-3.png\" alt=\"Honorable Rene Legacy addresses the audience at the 2025 Privacy, Security and Trust Industry Summit, held on August 26 at the Fredericton Convention Center.\">\n  <figcaption>Honorable Rene Legacy addresses the audience at the 2025 Privacy, Security and Trust Industry Summit, held on August 26 at the Fredericton Convention Center.</figcaption>\n</figure>\n<p><a href=\"https://ca.linkedin.com/in/tricia-geddes-4298081a9\">Tricia Geddes</a>, Deputy Minister of <a href=\"https://ca.linkedin.com/company/safety-canada-securite-canada\">Public Safety Canada | Sécurité publique Canada</a>, and the Honorable <a href=\"https://ca.linkedin.com/in/rene-legacy-30ab47161\">Rene Legacy</a>, Deputy Premier, Minister of Finance and Treasure Board, Minister of Energy for the Government of New Brunswick, spoke at length on critical issues surrounding cybersecurity, governance, and policy. It was truly inspiring to witness the genuine commitment of these national leaders to strengthening Canada’s cybersecurity landscape. The Honorable <a href=\"https://ca.linkedin.com/in/dominic-leblanc-174606345\">Dominic LeBlanc</a> was also scheduled to speak on related matters but was called away to address urgent national issues.</p>\n<h3>National Efforts to Combat Cybercrime</h3>\n<figure>\n  <img src=\"/blog/pst2025-industry-summit/img-4.jpg\" alt=\"Rajiv Gupta, Director of the Canadian Cyber Center, presents on the growing threat quantum computing poses to modern cryptographic systems at PST2025.\">\n  <figcaption>Rajiv Gupta, Director of the Canadian Cyber Center, presents on the growing threat quantum computing poses to modern cryptographic systems at PST2025.</figcaption>\n</figure>\n<p><a href=\"https://ca.linkedin.com/in/rajiv-gupta-267506131\">Rajiv Gupta</a>, Director of the Canadian Cyber Centre, opened with key statistics underscoring the important work being done to support individuals, enterprises, and agencies across Canada. He went on to discuss multi-tiered security architectures used to address incidents, highlighted several unique attacker threat models, and touched on issues of quantum readiness along with the national efforts underway in this area.</p>\n<p>Chris Lynam, Director General of the National Cybercrime Coordination Centre and the Canadian Anti-Fraud Centre (RCMP), together with Colin MacSween, Director General of National Cyber Security at <a href=\"https://ca.linkedin.com/company/safety-canada-securite-canada\">Public Safety Canada | Sécurité publique Canada</a>, provided insights into major operations and campaigns aimed at combating cybercrime. They outlined both independent and joint initiatives and presented provincial statistics that shed light on specific security incidents and trends across the country.</p>\n<h3>Mastercard’s Role in Advancing Cybersecurity</h3>\n<p><a href=\"https://ca.linkedin.com/in/jennifer-m-sloan\">Jennifer M Sloan</a>, <a href=\"https://ca.linkedin.com/in/kostiantynnikolaiev\">Kostia Nikolaiev</a>, and <a href=\"https://ca.linkedin.com/in/igor-opushnyev-102741b\">Igor Opushnyev</a> spoke extensively on critical issues such as cyber attribution, residential proxy detection, and the evolving threat models of emerging AI-powered attacks. <a href=\"https://www.linkedin.com/company/mastercard\">Mastercard</a>'s strong commitment to advancing cybersecurity excellence was evident as they highlighted key partnerships with the Cyber Attribution Data Center at the <a href=\"https://ca.linkedin.com/school/university-of-new-brunswick/\">University of New Brunswick</a>. During the panel discussions, <a href=\"https://ca.linkedin.com/in/kostiantynnikolaiev\">Kostia Nikolaiev</a> drew on his deep product engineering expertise to unpack complex issues surrounding cyber attribution and related challenges. His insights were consistently practical, strategic, and deeply impactful.</p>\n<h3>EMCEES and event coordination</h3>\n<p>The event featured several nutrition and networking breaks, giving attendees the opportunity to recharge, connect, and engage meaningfully. Special thanks go to Dr. <a href=\"https://ca.linkedin.com/in/samita-bai-ph-d-1b2b0a28\">Samita Bai, Ph.D.</a> and <a href=\"https://ca.linkedin.com/in/griffin-higgins-537562157\">Griffin Higgins</a>, who emceed the entire summit and ensured that the appreciation award presentations, along with the overall event schedule, ran seamlessly and efficiently. The outstanding success of the <strong>#PST2025</strong> Industry Summit was made possible in no small part by their selfless dedication and tireless efforts.</p>\n<h3>TD Bank on AI Risk, Governance, and Security</h3>\n<figure>\n  <img src=\"/blog/pst2025-industry-summit/img-5.jpg\" alt=\"Stephen Sparkes, Chief Information Security Officer, and Pamela Simpson, AI Business Information Security Officer at TD Bank, discuss the evolving intersection of AI and cybersecurity.\">\n  <figcaption>Stephen Sparkes, Chief Information Security Officer, and Pamela Simpson, AI Business Information Security Officer at TD Bank, discuss the evolving intersection of AI and cybersecurity.</figcaption>\n</figure>\n<p><a href=\"https://www.linkedin.com/in/stephen-sparkes-2b866452\">Stephen Sparkes</a>, Chief Information Security Officer and <a href=\"https://ca.linkedin.com/in/pamelaesimpson\">Pamela E. Simpson, M.A., GCTI, CISSP</a>, AI Business Information Security Officer, representing <a href=\"https://www.linkedin.com/company/td\">TD</a> Bank, delivered an in-depth discussion on AI as a threat amplifier. Their session covered pressing issues such as large-scale social engineering, deepfakes, model jailbreaking, supply chain vulnerabilities, and defensive AI strategies including automated red teaming and security testing for AI systems. They also introduced novel architectures for governing AI and its lifecycle, offering strategic recommendations such as implementing a RACI matrix and applying a Capability Maturity Model to track project progress. Importantly, they addressed key Agentic-AI risk frameworks, including the CSA MAESTRO Framework and the NIST AI RMF. Hearing these industry leaders unpack such complex challenges from a real-world, enterprise perspective was both enlightening and thought-provoking, sparking meaningful conversations among attendees.</p>\n<h3>Rogers Communication</h3>\n<figure>\n  <img src=\"/blog/pst2025-industry-summit/img-6.png\" alt=\"Paul Hanley, Senior Vice President of Cyber Security at Rogers Communications, delivering insights on emerging cyber threats at the #PST2025 Industry Summit.\">\n  <figcaption>Paul Hanley, Senior Vice President of Cyber Security at Rogers Communications, delivering insights on emerging cyber threats at the #PST2025 Industry Summit.</figcaption>\n</figure>\n<p><a href=\"https://ca.linkedin.com/in/paulwhanley\">Paul Hanley</a>, Senior Vice President of Cyber Security at <a href=\"https://ca.linkedin.com/company/rogers-communications\">Rogers Communications</a>, opened with a broad overview of today’s cyber risk landscape, highlighting issues such as ransomware (including Fatboy Ransomware), extortion attacks, the growing prevalence of targeted threats, and the role of the dark web and underground marketplaces.</p>\n<figure>\n  <img src=\"/blog/pst2025-industry-summit/img-7.jpg\" alt=\"A slide from Paul Hanley&#x27;s presentation on Emerging Trends in Cyber, highlighting critical issues such as AI manipulation, covert data corruption, adaptive malware, deepfakes, and the rise of super- and hyper-extortion.\">\n  <figcaption>A slide from Paul Hanley's presentation on Emerging Trends in Cyber, highlighting critical issues such as AI manipulation, covert data corruption, adaptive malware, deepfakes, and the rise of super- and hyper-extortion.</figcaption>\n</figure>\n<p>He then explored emerging trends in cybersecurity, including:</p>\n<ul>\n<li>AI and Gen AI manipulation</li>\n<li>Covert data corruption</li>\n<li>Adaptive malware to bypass to bypass defenses</li>\n<li>Quantum entanglement risks</li>\n<li>Deepfakes</li>\n<li>Super and hyper-extortion</li>\n<li>…and several others</li>\n</ul>\n<p>His depth of expertise was evident throughout, as he skillfully combined technical insight with humor to make increasingly complex security issues and trends both accessible and engaging.</p>\n<h3>Cyber Attribution and Panel Discussions</h3>\n<figure>\n  <img src=\"/blog/pst2025-industry-summit/img-8.jpg\" alt=\"Panel discussion on cyber attribution and global security, featuring Dr. Argyri Panezi, Kelly Anderson, Kostiantyn Nikolaiev, and Colin MacSween (Moderator), with Dr. Ahmed Al-Rawi contributing virtually.\">\n  <figcaption>Panel discussion on cyber attribution and global security, featuring Dr. Argyri Panezi, Kelly Anderson, Kostiantyn Nikolaiev, and Colin MacSween (Moderator), with Dr. Ahmed Al-Rawi contributing virtually.</figcaption>\n</figure>\n<p>Dr. <a href=\"https://www.linkedin.com/in/argyripanezi\">Argyri Panezi</a>, Canada Research Chair in Digital Information Law and Policy at the <a href=\"https://ca.linkedin.com/school/university-of-new-brunswick/\">University of New Brunswick</a>, addressed critical issues surrounding cyber attribution, its various classifications, and its inherently interdisciplinary nature. Her expertise as a seasoned legal scholar proved invaluable, particularly during the panel discussions, where she used clear legal analogies to unpack complex questions, ensuring they were thoroughly examined and accessible to the diverse international audience.</p>\n<p>Kelly Anderson, Director of International Cyber and Critical Technology Policy at Global Affairs Canada, delivered insightful remarks on key diplomatic challenges. She skillfully unpacked the complexities of cyber attribution, highlighting its profound implications for political, technical, and international actors alike.</p>\n<p>Dr. <a href=\"https://ca.linkedin.com/in/kwasi-boakye-boateng\">Kwasi Boakye-Boateng</a>, Deputy Director of Research and Training at the Cyber Attribution Data Center (CADC), presented the groundbreaking work being undertaken by the <a href=\"https://ca.linkedin.com/company/canadian_institute_cybersecurity\">Canadian Institute for Cybersecurity</a> to address industry challenges in cyber attribution. He highlighted the use of deceptive networking systems, internet monitoring, and expert threat intelligence, and introduced a comprehensive framework while also candidly discussing key challenges in the field.</p>\n<figure>\n  <img src=\"/blog/pst2025-industry-summit/img-9.jpg\" alt=\"Dr. Kwasi Boakye-Boateng, Deputy Director of Research and Training at the Cyber Attribution Data Center (CADC), slide on Attribution Challenges, including concept drift, data scarcity, misattribution, and interpretability, at #PST2025.\">\n  <figcaption>Dr. Kwasi Boakye-Boateng, Deputy Director of Research and Training at the Cyber Attribution Data Center (CADC), slide on Attribution Challenges, including concept drift, data scarcity, misattribution, and interpretability, at #PST2025.</figcaption>\n</figure>\n<p>Dr. Ahmed Al-Rawi also contributed significantly to the panel, speaking at length on a range of attribution-related issues. His extensive use of practical examples and references to key sources resonated strongly with attendees, bringing clarity and depth to complex debates and striking at the heart of attribution challenges across multiple levels.</p>\n<h3>Cyber Mentorship and Leadership</h3>\n<p><a href=\"https://ca.linkedin.com/in/elainehum\">Elaine Hum</a>, Director of Cybersecurity Partnerships at <a href=\"https://ca.linkedin.com/company/scotiabank\">Scotiabank</a>, shared her personal journey in cybersecurity and the unique path she forged through her work alongside CISOs. Her story was both motivating and memorable, culminating in a lighthearted moment where she donned a superhero cape, sparking laughter and smiles while underscoring the power of leadership and mentorship in the field. The same spirit of inspiration and practical insight mirrored the energy I witnessed earlier this year during her presentation at the Federation of Security Professionals’ Security Conference, hosted by <a href=\"https://ca.linkedin.com/company/rbc\">RBC</a>.</p>\n<h3>Industry Perspectives from Leading Companies</h3>\n<p><a href=\"https://ca.linkedin.com/in/dandoran34\">Dan Doran</a>, Vice President of Business Development and Marketing at <a href=\"https://ca.linkedin.com/company/adga-group\">ADGA Group</a>, delivered an insightful talk on the importance of engaging top-level business executives through carefully tailored executive language and communication techniques.</p>\n<p>Abhay Raman, Senior Vice President and Chief Security Officer at <a href=\"https://ca.linkedin.com/company/sun-life-financial\">Sun Life</a>, addressed targeted risk management challenges and proactive security strategies, with particular focus on emerging issues in Agentic-AI powered systems.</p>\n<h2>Awards Ceremony</h2>\n<figure>\n  <img src=\"/blog/pst2025-industry-summit/img-10.jpg\" alt=\"Dr. Ali Ghorbani, Director of the Canadian Institute for Cybersecurity, presenting one of the Best Poster Award to Ogobuchi Daniel Okey for his research poster at the #PST2025 Industry Summit in Fredericton.\">\n  <figcaption>Dr. Ali Ghorbani, Director of the Canadian Institute for Cybersecurity, presenting one of the Best Poster Award to Ogobuchi Daniel Okey for his research poster at the #PST2025 Industry Summit in Fredericton.</figcaption>\n</figure>\n<p>As part of the summit, distinguished researchers from academia showcased posters highlighting unique projects being conducted across various universities and faculties. These presentations were enriched by engagement with guests, visiting scholars, and fellow presenters, sparking meaningful discussions around innovative research. To conclude, an awards ceremony was held where four research groups were recognized for their outstanding contributions and achievements.</p>\n<h2>Farewell Message</h2>\n<figure>\n  <img src=\"/blog/pst2025-industry-summit/img-11.jpg\" alt=\"A wide-angle view of attendees networking and connecting at the 2025 Privacy, Security and Trust Industry Summit, held at the Fredericton Convention Center.\">\n  <figcaption>A wide-angle view of attendees networking and connecting at the 2025 Privacy, Security and Trust Industry Summit, held at the Fredericton Convention Center.</figcaption>\n</figure>\n<p>It was an absolute honor to attend the <strong>#PST2025</strong> Industry Summit. I thoroughly enjoyed the event, from the insightful keynotes and panel discussions to the vibrant networking sessions that connected industry, academia, and government leaders.</p>\n<p>By way of introduction, my name is <strong>Aghoghomena Akasukpe</strong>, a <strong>systems &#x26; full-stack engineer and graduate researcher</strong> at <a href=\"https://ca.linkedin.com/school/ontariotech/\">Ontario Tech University</a>. I build the infrastructure under AI agents and ship full-stack product, and my research adds rigor to that work. I had the privilege of presenting our accepted paper, “A Per-Bag Suspicion-Based Bagging Strategy for Fighting Poisoning Attacks in Classification”, which proposes novel defense strategies against data poisoning attacks in machine learning systems.</p>\n<figure>\n  <img src=\"/blog/pst2025-industry-summit/img-12.jpg\" alt=\"Aghoghomena Akasukpe, Systems &#x26; Full-Stack Engineer and graduate researcher at Ontario Tech University, at the #PST2025 Industry Summit. His accepted research paper at the conference explored novel defense strategies against data poisoning in machine learning systems.\">\n  <figcaption>Aghoghomena Akasukpe, Systems &#x26; Full-Stack Engineer and graduate researcher at Ontario Tech University, at the #PST2025 Industry Summit. His accepted research paper at the conference explored novel defense strategies against data poisoning in machine learning systems.</figcaption>\n</figure>\n<p>The summit was an incredibly inspiring experience, and I leave even more motivated to contribute to advancing cybersecurity and AI safety. My sincerest gratitude goes to the organizers, speakers, and fellow researchers who made the event impactful and memorable.</p>","date_published":"2025-08-31T00:00:00.000Z","tags":["research","conference","agentic-ai"]},{"id":"https://www.aghoghomena.com/writing/role-based-access-control-nextjs-middleware","url":"https://www.aghoghomena.com/writing/role-based-access-control-nextjs-middleware","title":"Role-based access control using Next.js middleware","summary":"A walkthrough for enforcing role-based page access in a multi-role Next.js App Router app: JWT decoding in middleware, whitelists per role, and redirect logic with the full code.","content_html":"<p>In this article we will explore an approach to implementing <strong>Role-Based Access control</strong> using <strong>Middlewares</strong> when multiple user types exist in a Next.js application.</p>\n<p>Ideally, you should be familiar with the following:</p>\n<ol>\n<li>React.js (Beginner)</li>\n<li>Next.js (Beginner)</li>\n<li>TypeScript (Beginner)</li>\n<li>JSON Web Tokens (JWT's) or OAUTH2.0</li>\n</ol>\n<h2>The Problem</h2>\n<p><strong>Setup 1:</strong> A frontend system must integrate with an Application Programming Interface(API)💻 that has multiple User Roles.</p>\n<ul>\n<li>STUDENT 🎓</li>\n<li>TEACHER 🏫</li>\n<li>ADMIN 💼</li>\n<li>...(Any other roles)</li>\n</ul>\n<p><strong>Setup 2:</strong> An authentication system using <strong>JSON WEB TOKENS(JWT's)</strong> or an <strong>OAUTH2.0</strong> scheme.</p>\n<p><strong>Goal:</strong> A robust access control system (<strong><code>Authorization</code></strong>-after-<strong><code>Authentication</code></strong>) where access is granted strictly based on a users role.</p>\n<p>-> What this means?</p>\n<ul>\n<li>A Student cannot access any endpoint not in the student whitelist.</li>\n</ul>\n<h2>Definitions</h2>\n<p><strong>What is Role-Based Access Control?</strong></p>\n<p>Role-Based Access Control (RBAC) is a method of restricting network access(in our case Page📃 Access) based on the roles of individual users within an organization. <a href=\"https://en.wikipedia.org/wiki/Role-based_access_control\">Learn More</a></p>\n<p><strong>What are JSON Web Tokens?</strong></p>\n<p>JWT (JSON Web Token) is a compact, URL-safe token format that can be used for authentication in web applications. <a href=\"https://jwt.io/introduction\">Learn More</a></p>\n<p>Typical workflow:</p>\n<ol>\n<li>User logs in.</li>\n<li>The server creates a JWT containing user information (We inject the Role in the Payload) and signs it with a secret key.</li>\n<li>JWT is then sent to the client, which <strong>stores</strong> it.</li>\n<li>For subsequent requests, the client includes the JWT <strong>in the request headers</strong>. The server verifies the JWT's signature, extracts the user information, and uses it to authenticate the user and authorize access to protected resources.</li>\n</ol>\n<p><strong>Next.JS Middlewares</strong></p>\n<p>Next.js middleware allows us to run code before a request is completed. Then, based on the <strong>incoming request,</strong> we can modify the response by <strong>rewriting, redirecting, modifying</strong> the (request or response headers), or (responding directly). <a href=\"https://nextjs.org/docs/app/building-your-application/routing/middleware\">Learn More</a></p>\n<h2>Prerequisites</h2>\n<p>You should have following to follow with this walkthrough:</p>\n<ul>\n<li>Instructions for Node.js installation <a href=\"https://nodejs.org/en/download/current\">here</a>.</li>\n<li>View the completed <a href=\"https://github.com/Edolor/rbaccessnext\">Github Repository</a></li>\n</ul>\n<h2>Let's Begin</h2>\n<p>Firstly, we initialize an empty Next.js project:</p>\n<pre><code class=\"hljs language-bash\">npx create-next-app@14 rbaccessnext\n</code></pre>\n<p>Accept all the default configurations.</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-2.png\" alt=\"Output when you run &#x60;create-next-app&#x60; command\">\n  <figcaption>Output when you run `create-next-app` command</figcaption>\n</figure>\n<p>Voila, now let's run our created project:</p>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-built_in\">cd</span> rbaccessnext\nnpm run dev\n</code></pre>\n<p>We have our beautiful default landing page:</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-3.png\" alt=\"Default Next.js index page\">\n  <figcaption>Default Next.js index page</figcaption>\n</figure>\n<p><strong>Let's clean up this boiler plate:</strong></p>\n<ul>\n<li>Delete all non-<strong><code>.tsx</code></strong> files from /app</li>\n<li>Delete all references from <strong>page.tsx</strong> and <strong>layout.tsx</strong></li>\n</ul>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-4.png\" alt=\"After removing Boilerplate code\">\n  <figcaption>After removing Boilerplate code</figcaption>\n</figure>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-5.png\" alt=\"Output of new cleaned up code on the browser\">\n  <figcaption>Output of new cleaned up code on the browser</figcaption>\n</figure>\n<h2>Creating Routes</h2>\n<p>Since we are using <strong>App Router</strong>, given that we installed Next.js version 14:</p>\n<ol>\n<li>Let's create 2 folders in the <strong>src/app</strong> folder: (student / teacher)</li>\n</ol>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-6.png\" alt=\"File tree, showing (Student) and (Teacher)\">\n  <figcaption>File tree, showing (Student) and (Teacher)</figcaption>\n</figure>\n<ol start=\"2\">\n<li>Let's create a file in both folders <strong>page.tsx</strong></li>\n</ol>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-7.png\" alt=\"Home Pages for Student and Teacher\">\n  <figcaption>Home Pages for Student and Teacher</figcaption>\n</figure>\n<ol start=\"3\">\n<li>Now let's test these changes on the browser by visiting <strong>/student</strong> and <strong>/teacher</strong></li>\n</ol>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-8.png\" alt=\"Output from opening both routes on the browser\">\n  <figcaption>Output from opening both routes on the browser</figcaption>\n</figure>\n<h2>Middleware Setup and Code</h2>\n<p>Firstly, we create a <strong>middleware.ts</strong> file in the <strong>src</strong> diretory</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-9.png\" alt=\"Created middleware.ts\">\n  <figcaption>Created middleware.ts</figcaption>\n</figure>\n<p>Next we add some necessary packages to work with <strong>JWT's and Cookies</strong> in <strong>Next.js.</strong></p>\n<p>The packages are</p>\n<ul>\n<li><strong>cookies-next:</strong> Checking for cookie existence / Deletion of cookies on expiry.</li>\n<li><strong>dayjs:</strong> Useful to check if token has expired.</li>\n<li><strong>jwt-decode:</strong> Useful to decode the contents of the Payload contained in a JWT</li>\n</ul>\n<pre><code class=\"hljs language-bash\">npm i cookies-next dayjs jwt-decode\n</code></pre>\n<p>We then advance to importing some required packages:</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-10.png\" alt=\"middleware.ts imports\">\n  <figcaption>middleware.ts imports</figcaption>\n</figure>\n<p>Next we define some types in TypeScript:</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-11.png\" alt=\"Role-based access control using Next.js middleware figure 54\">\n</figure>\n<p>Next we define some variables <strong>(loginURLS, teacherURLS, studentURLS, protectedURLS)</strong> at the Top level to help with page restrictions</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-12.png\" alt=\"Role-based access control using Next.js middleware figure 56\">\n</figure>\n<p>Finally, we get to defining the actual middleware😤, the typical structure for <strong>middlewares in NextJS is</strong></p>\n<pre><code class=\"hljs language-ts\"><span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">default</span> <span class=\"hljs-keyword\">function</span> <span class=\"hljs-title function_\">middleware</span>(<span class=\"hljs-params\"><span class=\"hljs-attr\">req</span>: <span class=\"hljs-title class_\">NextRequest</span></span>) {\n    <span class=\"hljs-keyword\">const</span> res = <span class=\"hljs-title class_\">NextResponse</span>.<span class=\"hljs-title function_\">next</span>();\n\n    <span class=\"hljs-keyword\">return</span> res;\n}\n</code></pre>\n<p>The following middeware logic below from which we will build on handles:</p>\n<ul>\n<li>Deleting <strong>TOKEN</strong> from cookies when JWT is expired</li>\n<li>Setting <strong>isAuthenticated to True if user is LoggedIn</strong></li>\n</ul>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-13.png\" alt=\"Role-based access control using Next.js middleware figure 61\">\n</figure>\n<p>After this, we define two functions below to do the following:</p>\n<ul>\n<li>If a PATH has a given route we defined</li>\n<li>Build an Absolute URL to be returned and used because of <strong>NextResponse.redirect()</strong></li>\n</ul>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-14.png\" alt=\"Role-based access control using Next.js middleware figure 64\">\n</figure>\n<p>Lastly, we handle the actual redirection of users based on the <strong>isAuthenticated variable</strong> and other things defined above. The below image does the following:</p>\n<ul>\n<li><strong>Blocks access to specific URLS</strong> (loginURLS) if the user is <strong>AUTHENTICATED</strong></li>\n<li>Redirects user to their DASHBOARD if they try to access pages that are not in their allowed WHITELISTED pages</li>\n<li>Redirects a user to <strong>LOGIN PAGE</strong> if <strong>UNAUTHENTICATED</strong></li>\n</ul>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-15.png\" alt=\"Role-based access control using Next.js middleware figure 67\">\n</figure>\n<p>Yayy🍃, we are done.</p>\n<p>The completed code is attached below, brace yourself:)</p>\n<pre><code class=\"hljs language-ts\"><span class=\"hljs-keyword\">import</span> { deleteCookie, hasCookie } <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">\"cookies-next\"</span>;\n<span class=\"hljs-keyword\">import</span> { <span class=\"hljs-title class_\">NextResponse</span> } <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">\"next/server\"</span>;\n<span class=\"hljs-keyword\">import</span> { <span class=\"hljs-title class_\">NextRequest</span> } <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">\"next/server\"</span>;\n<span class=\"hljs-keyword\">import</span> { cookies } <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">\"next/headers\"</span>;\n<span class=\"hljs-keyword\">import</span> dayjs <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">\"dayjs\"</span>;\n<span class=\"hljs-keyword\">import</span> { jwtDecode } <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">\"jwt-decode\"</span>;\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">type</span> <span class=\"hljs-title class_\">UserEnumTypes</span> = <span class=\"hljs-string\">\"STUDENT\"</span> | <span class=\"hljs-string\">\"TEACHER\"</span> | <span class=\"hljs-string\">\"ADMIN\"</span>; <span class=\"hljs-comment\">// Add more User Roles at will</span>\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">type</span> <span class=\"hljs-title class_\">Tokens</span> = { <span class=\"hljs-comment\">// Actual Token Type</span>\n    <span class=\"hljs-attr\">access</span>: <span class=\"hljs-built_in\">string</span>;\n    <span class=\"hljs-attr\">refresh</span>?: <span class=\"hljs-built_in\">string</span>;\n}\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">type</span> <span class=\"hljs-title class_\">UserType</span> = { <span class=\"hljs-comment\">// Payload when decrypted from JWT</span>\n    <span class=\"hljs-attr\">accountType</span>: <span class=\"hljs-title class_\">UserEnumTypes</span>;\n    <span class=\"hljs-attr\">accountid</span>: <span class=\"hljs-built_in\">string</span>;\n    <span class=\"hljs-attr\">exp</span>: <span class=\"hljs-built_in\">number</span>;\n    <span class=\"hljs-attr\">firstName</span>?: <span class=\"hljs-built_in\">string</span>;\n    <span class=\"hljs-attr\">iat</span>: <span class=\"hljs-built_in\">number</span>;\n    <span class=\"hljs-attr\">lastName</span>?: <span class=\"hljs-built_in\">string</span>;\n    <span class=\"hljs-attr\">updatedAt</span>: <span class=\"hljs-built_in\">string</span>;\n}\n\n<span class=\"hljs-keyword\">const</span> loginUrls = [ <span class=\"hljs-comment\">// Re-route after USER is authenticated</span>\n    <span class=\"hljs-string\">\"/login\"</span>,\n    <span class=\"hljs-comment\">// Add routes that should not be accessible when logged in here</span>\n];\n\n<span class=\"hljs-keyword\">const</span> studentUrls = [ <span class=\"hljs-comment\">// URLS meant for students only</span>\n    <span class=\"hljs-string\">\"/student\"</span>,\n    <span class=\"hljs-comment\">// Add more protected routes here</span>\n];\n\n<span class=\"hljs-keyword\">const</span> teacherUrls = [ <span class=\"hljs-comment\">// URLS meant for teachers only</span>\n    <span class=\"hljs-string\">\"/teacher\"</span>,\n    <span class=\"hljs-comment\">// Add more protected routes here</span>\n];\n\n<span class=\"hljs-keyword\">const</span> protectedRoutes = [...studentUrls, ...teacherUrls]; <span class=\"hljs-comment\">// Add all protected URLS here</span>\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">default</span> <span class=\"hljs-keyword\">function</span> <span class=\"hljs-title function_\">middleware</span>(<span class=\"hljs-params\"><span class=\"hljs-attr\">req</span>: <span class=\"hljs-title class_\">NextRequest</span></span>) {\n    <span class=\"hljs-keyword\">const</span> res = <span class=\"hljs-title class_\">NextResponse</span>.<span class=\"hljs-title function_\">next</span>();\n    <span class=\"hljs-keyword\">let</span> isAuthenticated = <span class=\"hljs-literal\">false</span>;\n    <span class=\"hljs-keyword\">let</span> <span class=\"hljs-attr\">userType</span>: <span class=\"hljs-title class_\">UserEnumTypes</span> = <span class=\"hljs-string\">\"STUDENT\"</span>; <span class=\"hljs-comment\">// Default</span>\n    <span class=\"hljs-keyword\">const</span> <span class=\"hljs-variable constant_\">BASE_FRONTEND_URL</span> = req.<span class=\"hljs-property\">nextUrl</span>.<span class=\"hljs-property\">origin</span>;\n    <span class=\"hljs-keyword\">const</span> <span class=\"hljs-variable constant_\">CURRENT_URL_PATHNAME</span> = req.<span class=\"hljs-property\">nextUrl</span>.<span class=\"hljs-property\">pathname</span>;\n\n    <span class=\"hljs-comment\">// First page a user will see(Redirected to) when they login based on role</span>\n    <span class=\"hljs-keyword\">const</span> <span class=\"hljs-variable constant_\">DASHBOARDS</span> = {\n        <span class=\"hljs-attr\">student</span>: <span class=\"hljs-string\">\"/student\"</span>,\n        <span class=\"hljs-attr\">teacher</span>: <span class=\"hljs-string\">\"/teacher\"</span>,\n        <span class=\"hljs-comment\">// Can and might be a dashboard page or any other</span>\n    }\n\n    <span class=\"hljs-comment\">// Checking that cookie exists and handling it</span>\n    <span class=\"hljs-keyword\">if</span> (<span class=\"hljs-title function_\">hasCookie</span>(<span class=\"hljs-string\">\"authTokens\"</span>, { cookies })) {\n        <span class=\"hljs-keyword\">let</span> authTokens = req.<span class=\"hljs-property\">cookies</span>.<span class=\"hljs-title function_\">get</span>(<span class=\"hljs-string\">'authTokens'</span>)?.<span class=\"hljs-property\">value</span> <span class=\"hljs-comment\">// Get cookies using Key(authTokens)</span>\n\n        <span class=\"hljs-keyword\">if</span> (authTokens &#x26;&#x26; authTokens !== <span class=\"hljs-literal\">null</span> &#x26;&#x26; authTokens !== <span class=\"hljs-string\">\"{}\"</span>) { <span class=\"hljs-comment\">// Checking for empty cookies</span>\n            <span class=\"hljs-keyword\">const</span> tokens = <span class=\"hljs-title class_\">JSON</span>.<span class=\"hljs-title function_\">parse</span>(authTokens) <span class=\"hljs-keyword\">as</span> <span class=\"hljs-title class_\">Tokens</span>; <span class=\"hljs-comment\">// Casting to actual Token Type</span>\n            <span class=\"hljs-keyword\">const</span> accessToken = tokens?.<span class=\"hljs-property\">access</span>; <span class=\"hljs-comment\">// Getting the access token</span>\n\n            <span class=\"hljs-keyword\">if</span> (accessToken) {\n                <span class=\"hljs-comment\">// Decoding Payload from access Token</span>\n                <span class=\"hljs-keyword\">const</span> data = <span class=\"hljs-title function_\">jwtDecode</span>(accessToken) <span class=\"hljs-keyword\">as</span> <span class=\"hljs-title class_\">UserType</span>;\n\n                <span class=\"hljs-comment\">// Checking for Token expiry</span>\n                <span class=\"hljs-keyword\">const</span> isExpired = dayjs.<span class=\"hljs-title function_\">unix</span>(data.<span class=\"hljs-property\">exp</span> <span class=\"hljs-keyword\">as</span> <span class=\"hljs-built_in\">number</span>).<span class=\"hljs-title function_\">diff</span>(<span class=\"hljs-title function_\">dayjs</span>()) &#x3C; <span class=\"hljs-number\">1</span>;\n\n                <span class=\"hljs-comment\">// If token is not expired set (isAuthenticated to True)</span>\n                <span class=\"hljs-keyword\">if</span> (!isExpired) {\n                    userType = data.<span class=\"hljs-property\">accountType</span> <span class=\"hljs-keyword\">as</span> <span class=\"hljs-title class_\">UserEnumTypes</span>;\n                    isAuthenticated = <span class=\"hljs-literal\">true</span>;\n                } <span class=\"hljs-keyword\">else</span> {\n                    <span class=\"hljs-comment\">// Logout user if Token has expired</span>\n                    <span class=\"hljs-comment\">// (Deleted three times because I have trust issues)</span>\n                    req.<span class=\"hljs-property\">cookies</span>.<span class=\"hljs-title function_\">delete</span>(<span class=\"hljs-string\">\"authTokens\"</span>);\n                    <span class=\"hljs-title function_\">deleteCookie</span>(<span class=\"hljs-string\">\"authTokens\"</span>);\n                    <span class=\"hljs-title function_\">cookies</span>().<span class=\"hljs-title function_\">delete</span>(<span class=\"hljs-string\">\"authTokens\"</span>);\n                }\n            }\n        }\n    }\n\n    <span class=\"hljs-comment\">// Check if the current path has a matching route</span>\n    <span class=\"hljs-comment\">/**\n     * E.g\n     * currentRoute == \"/student/remarks\"\n     */</span>\n    <span class=\"hljs-keyword\">const</span> <span class=\"hljs-title function_\">hasRoute</span> = (<span class=\"hljs-params\"><span class=\"hljs-attr\">routes</span>: <span class=\"hljs-title class_\">Array</span>&#x3C;<span class=\"hljs-built_in\">string</span>>, <span class=\"hljs-attr\">currentPath</span>: <span class=\"hljs-built_in\">string</span></span>) => {\n        <span class=\"hljs-keyword\">let</span> isValid = <span class=\"hljs-literal\">false</span>;\n\n        routes.<span class=\"hljs-title function_\">map</span>(<span class=\"hljs-function\"><span class=\"hljs-params\">route</span> =></span> {\n            <span class=\"hljs-keyword\">if</span> (currentPath.<span class=\"hljs-title function_\">includes</span>(route)) {\n                isValid = <span class=\"hljs-literal\">true</span>;\n            }\n        });\n\n        <span class=\"hljs-keyword\">return</span> isValid;\n    }\n\n    <span class=\"hljs-comment\">// Builds URL to be returned</span>\n    <span class=\"hljs-keyword\">const</span> <span class=\"hljs-title function_\">buildUrl</span> = (<span class=\"hljs-params\"><span class=\"hljs-attr\">route</span>: <span class=\"hljs-built_in\">string</span></span>) => {\n        <span class=\"hljs-keyword\">const</span> absoluteURL = <span class=\"hljs-keyword\">new</span> <span class=\"hljs-title function_\">URL</span>(route, <span class=\"hljs-variable constant_\">BASE_FRONTEND_URL</span>);\n        <span class=\"hljs-keyword\">return</span> absoluteURL.<span class=\"hljs-title function_\">toString</span>();\n    }\n\n    <span class=\"hljs-comment\">// IF USER IS UNATHENTICATED AND TRIES TO access a PROTECTED ROUTE (REDIRECTION)</span>\n    <span class=\"hljs-keyword\">if</span> (!isAuthenticated &#x26;&#x26; <span class=\"hljs-title function_\">hasRoute</span>(protectedRoutes, <span class=\"hljs-variable constant_\">CURRENT_URL_PATHNAME</span>)) {\n        <span class=\"hljs-keyword\">return</span> <span class=\"hljs-title class_\">NextResponse</span>.<span class=\"hljs-title function_\">redirect</span>(<span class=\"hljs-title function_\">buildUrl</span>(<span class=\"hljs-string\">\"/login\"</span>)); <span class=\"hljs-comment\">// SWAP FOR YOUR BASE LOGIN URL</span>\n    }\n\n    <span class=\"hljs-comment\">// Access control based on user type for protected routes:</span>\n    <span class=\"hljs-comment\">// - Check if the user is authenticated</span>\n    <span class=\"hljs-comment\">// - Check if the current path matches the protected routes</span>\n    <span class=\"hljs-comment\">// - Redirect based on user type:</span>\n    <span class=\"hljs-comment\">//   - If userType is STUDENT and the current path is not in studentUrls, redirect to student dashboard</span>\n    <span class=\"hljs-comment\">//   - If userType is TEACHER and the current path is not in teacherUrls, redirect to teacher dashboard</span>\n    <span class=\"hljs-keyword\">if</span> (isAuthenticated &#x26;&#x26; <span class=\"hljs-title function_\">hasRoute</span>(protectedRoutes, <span class=\"hljs-variable constant_\">CURRENT_URL_PATHNAME</span>)) {\n        <span class=\"hljs-keyword\">switch</span> (userType) {\n            <span class=\"hljs-keyword\">case</span> <span class=\"hljs-string\">\"TEACHER\"</span>:\n                <span class=\"hljs-keyword\">if</span> (!<span class=\"hljs-title function_\">hasRoute</span>(teacherUrls, <span class=\"hljs-variable constant_\">CURRENT_URL_PATHNAME</span>)) {\n                    <span class=\"hljs-keyword\">return</span> <span class=\"hljs-title class_\">NextResponse</span>.<span class=\"hljs-title function_\">redirect</span>(<span class=\"hljs-title function_\">buildUrl</span>(<span class=\"hljs-variable constant_\">DASHBOARDS</span>.<span class=\"hljs-property\">teacher</span>));\n                }\n                <span class=\"hljs-keyword\">break</span>;\n            <span class=\"hljs-keyword\">case</span> <span class=\"hljs-string\">\"STUDENT\"</span>:\n                <span class=\"hljs-keyword\">if</span> (!<span class=\"hljs-title function_\">hasRoute</span>(studentUrls, <span class=\"hljs-variable constant_\">CURRENT_URL_PATHNAME</span>)) {\n                    <span class=\"hljs-keyword\">return</span> <span class=\"hljs-title class_\">NextResponse</span>.<span class=\"hljs-title function_\">redirect</span>(<span class=\"hljs-title function_\">buildUrl</span>(<span class=\"hljs-variable constant_\">DASHBOARDS</span>.<span class=\"hljs-property\">student</span>));\n                }\n                <span class=\"hljs-keyword\">break</span>;\n\n            <span class=\"hljs-comment\">// Add more -CASES- as you need</span>\n            <span class=\"hljs-attr\">default</span>: <span class=\"hljs-comment\">// Random fallback if all cases fail (DO AS YOU WISH)</span>\n                <span class=\"hljs-keyword\">return</span> <span class=\"hljs-title class_\">NextResponse</span>.<span class=\"hljs-title function_\">redirect</span>(<span class=\"hljs-title function_\">buildUrl</span>(<span class=\"hljs-variable constant_\">DASHBOARDS</span>.<span class=\"hljs-property\">student</span>));\n        }\n    }\n\n    <span class=\"hljs-comment\">// BLocking access to Login URLS when authenticated</span>\n    <span class=\"hljs-keyword\">if</span> (isAuthenticated &#x26;&#x26; <span class=\"hljs-title function_\">hasRoute</span>(loginUrls, <span class=\"hljs-variable constant_\">CURRENT_URL_PATHNAME</span>)) {\n        <span class=\"hljs-keyword\">if</span> (userType === <span class=\"hljs-string\">\"STUDENT\"</span>) {\n            <span class=\"hljs-keyword\">return</span> <span class=\"hljs-title class_\">NextResponse</span>.<span class=\"hljs-title function_\">redirect</span>(<span class=\"hljs-title function_\">buildUrl</span>(<span class=\"hljs-variable constant_\">DASHBOARDS</span>.<span class=\"hljs-property\">student</span>));\n        } <span class=\"hljs-keyword\">else</span> <span class=\"hljs-keyword\">if</span> (userType === <span class=\"hljs-string\">\"TEACHER\"</span> ) {\n            <span class=\"hljs-keyword\">return</span> <span class=\"hljs-title class_\">NextResponse</span>.<span class=\"hljs-title function_\">redirect</span>(<span class=\"hljs-title function_\">buildUrl</span>(<span class=\"hljs-variable constant_\">DASHBOARDS</span>.<span class=\"hljs-property\">teacher</span>));\n        }\n\n        <span class=\"hljs-comment\">// ADD MORE TYPES AS YOU WISH</span>\n    }\n\n    <span class=\"hljs-keyword\">return</span> res;\n}\n</code></pre>\n<p>Now when we visit <strong>/student</strong> or <strong>/teacher</strong> we get redirected to <strong>/login</strong> which does not exist yet.</p>\n<h2>Login Page Creation and Redirection test</h2>\n<h3>JWT Payload Detour</h3>\n<p>We will be using the following hardcoded tokens for authentication for simplicity, but you can integrate with any Backend API for this (Just verify the payload structure and adapt the code to fit).</p>\n<p>The <strong>Student JWT</strong> we will be using:</p>\n<pre><code class=\"hljs language-json\"><span class=\"hljs-punctuation\">{</span><span class=\"hljs-attr\">\"access\"</span><span class=\"hljs-punctuation\">:</span><span class=\"hljs-string\">\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50aWQiOiJmYmFhMDU0OS05YTJhLTQwZmEtYTAyNi01MDIyMWYyOGRiZDciLCJmaXJzdE5hbWUiOiJqb2huIiwibGFzdE5hbWUiOiJzdGFtb3MiLCJ1cGRhdGVkQXQiOiIyMDI0LTA0LTI0VDE2OjE4OjA5LjM3OFoiLCJhY2NvdW50VHlwZSI6IlNUVURFTlQiLCJpYXQiOjE3MTQ5MTY0MzgsImV4cCI6MTcxNDkzMDgzOH0.7XIWJ7bqQWEhLEKDsHr0MQgnVEKVaRCl4IhfQh67HFw\"</span><span class=\"hljs-punctuation\">}</span>\n</code></pre>\n<p>When we decrypt the Payload (using jwt.io) we get:</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-16.png\" alt=\"Decoded Student JWT Payload\">\n  <figcaption>Decoded Student JWT Payload</figcaption>\n</figure>\n<p>The <strong>Teacher JWT</strong> we will be using:</p>\n<pre><code class=\"hljs language-json\"><span class=\"hljs-punctuation\">{</span><span class=\"hljs-attr\">\"access\"</span><span class=\"hljs-punctuation\">:</span><span class=\"hljs-string\">\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50aWQiOiIwNDUwMWU1Ni0wODE0LTQyNjctYmI4Yy03Nzk2YmZjOGQ5MTIiLCJmaXJzdE5hbWUiOiJVbml2ZXJzYWwiLCJsYXN0TmFtZSI6Ikh1bWFuIiwidXBkYXRlZEF0IjoiMjAyNC0wNC0yNFQxNjoxOToxNy45MDlaIiwiYWNjb3VudFR5cGUiOiJURUFDSEVSIiwiaWF0IjoxNzE0OTE2NjE0LCJleHAiOjE3MTQ5MzEwMTR9.emIvZBIdrRK2W_9UGnsJtbIdlpbMLse6_fYMUrkRPgw\"</span><span class=\"hljs-punctuation\">}</span>\n</code></pre>\n<p>When we decrypt the Payload (using <a href=\"http://jwt.io/\">jwt.io</a>) we get:</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-17.png\" alt=\"Decoded Teacher JWT Payload\">\n  <figcaption>Decoded Teacher JWT Payload</figcaption>\n</figure>\n<p><strong>Note:</strong> The <strong>accountType</strong> in these payload matches the <strong>UserEnumTypes</strong> we defined in the <strong>middelware.ts</strong> file</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-18.png\" alt=\"TypeScript type definitions in middleware.ts\">\n  <figcaption>TypeScript type definitions in middleware.ts</figcaption>\n</figure>\n<h3>Back to Login Page creation</h3>\n<p>Now let's create a folder <strong>/login</strong> and a <strong>page.tsx</strong> inside</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-19.png\" alt=\"Initial login template\">\n  <figcaption>Initial login template</figcaption>\n</figure>\n<p>Now when we visit <strong>/student</strong> or <strong>/teacher</strong> we get redirected to <strong>/login</strong> which has:</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-20.png\" alt=\"Initial login Page\">\n  <figcaption>Initial login Page</figcaption>\n</figure>\n<h3>Creation of Final User Interface</h3>\n<p>Our final user interface will look like:</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-21.png\" alt=\"Final user interface to be designed\">\n  <figcaption>Final user interface to be designed</figcaption>\n</figure>\n<p>The code that designs and handles the final interface is attached below:</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-22.png\" alt=\"Final code for Login Page\">\n  <figcaption>Final code for Login Page</figcaption>\n</figure>\n<h3>Testing Completed User Interface</h3>\n<p>Now when we click <strong>student</strong> and login:</p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-23.png\" alt=\"Role-based access control using Next.js middleware figure 97\">\n</figure>\n<p>We get redirected correctly and can access <strong>/student:</strong></p>\n<figure>\n  <img src=\"/blog/role-based-access-control-nextjs-middleware/img-24.png\" alt=\"Successful access of protected route\">\n  <figcaption>Successful access of protected route</figcaption>\n</figure>\n<p>Redirection successful ✅✅✅✅.</p>\n<p><strong>Note:</strong></p>\n<ol>\n<li>If we visit <strong>/teacher</strong> (or any other protected page we should not have access to) when logged in <strong>as a student</strong> we get redirected to <strong>/student</strong> the student dashboard.</li>\n<li>We cannot access <strong>/login</strong> when we are authenticated, we are redirected to the right dashboard based on our ROLE.</li>\n<li>We can only access the protectedRoutes in our WHITELIST, but we can access all routes not protected or in the loginURLS.</li>\n<li>This works same when we login as a <strong>Teacher</strong> or <strong>any other defined roles</strong>.</li>\n</ol>\n<h2>Conclusion</h2>\n<blockquote>\n<p>We successfully restricted page access when users authenticate based on their roles✅✅.</p>\n</blockquote>\n<p>View the completed <a href=\"https://github.com/Edolor/rbaccessnext\">Github Repository</a>.</p>","date_published":"2024-05-05T00:00:00.000Z","tags":["nextjs","authentication","web-engineering"]},{"id":"https://www.aghoghomena.com/writing/content-based-recommendation-django","url":"https://www.aghoghomena.com/writing/content-based-recommendation-django","title":"Content-based recommendation system with Django and scikit-learn","summary":"Building a content-based recommendation API with Django, Django REST Framework, TF-IDF vectorization, and cosine similarity, with the trained model cached via pickle on app startup.","content_html":"<p>In this article we will explore how we can utilize Django, Django Rest framework TF-IDF Vectorization, Scikit-learn and Cosine Similarity, to build a fully functional Recommendation system.</p>\n<p><strong>Propsed Recommendation model:</strong></p>\n<figure>\n  <img src=\"/blog/content-based-recommendation-django/img-2.jpg\" alt=\"Proposed Recommendation model\">\n  <figcaption>Proposed Recommendation model</figcaption>\n</figure>\n<p><strong>Tools to be used:</strong></p>\n<ul>\n<li>Django</li>\n<li>Scikit-Learn</li>\n<li>Pandas / Numpy</li>\n<li>Django Rest Framework</li>\n<li>Pickle (For storing the cached model)</li>\n</ul>\n<p><strong>Side Note 1:</strong> Link to Github for the completed project - <a href=\"https://github.com/Edolor/E-commerce-Recommendation-System\">Here</a></p>\n<p><strong>Side Note 2:</strong> Link to research paper - <a href=\"https://docs.google.com/document/d/1t3HunS2GO3dCXLV9JKwN15is8W_XhSkV5-DCn9hT4U0/edit\">Here</a></p>\n<h2>Prerequisites:</h2>\n<p>You should have the following setup:</p>\n<ol>\n<li><strong>>= Python3.10</strong> <a href=\"https://www.python.org/downloads/\">Learn more</a></li>\n<li>Docker (<a href=\"https://www.docker.com/get-started/\">Optional</a>)</li>\n<li>Pipenv (<a href=\"https://realpython.com/pipenv-guide/\">Installation and Learning Resource</a>)</li>\n</ol>\n<h2>First Steps:</h2>\n<p>Firstly we setup our Virtual environment using</p>\n<figure>\n  <img src=\"/blog/content-based-recommendation-django/img-3.png\" alt=\"Setting up virtual environment and installng Requirements.\">\n  <figcaption>Setting up virtual environment and installng Requirements.</figcaption>\n</figure>\n<p>Below is the requirements.txt</p>\n<pre><code class=\"hljs language-text\">asgiref==3.6.0\ncachetools==4.2.4\ncertifi==2022.12.7\ncharset-normalizer==3.1.0\ndj-database-url==1.2.0\nDjango==4.1.7\ndjango-cors-headers==3.14.0\ndjango-filter==22.1\ndjango-googledrive-storage==1.6.0\ndjango-pandas==0.6.6\ndjangorestframework==3.14.0\ngoogle-api-core==2.10.2\ngoogle-api-python-client==2.86.0\ngoogle-auth==1.35.0\ngoogle-auth-httplib2==0.1.0\ngoogleapis-common-protos==1.59.0\ngunicorn==20.1.0\nhttplib2==0.22.0\nidna==3.4\nitsdangerous==2.1.2\njoblib==1.2.0\nnumpy==1.24.2\npandas==1.5.3\nPillow==9.4.0\nprotobuf==4.22.4\npsycopg2-binary==2.9.5\npyasn1==0.5.0\npyasn1-modules==0.3.0\npyparsing==3.0.9\npython-dateutil==2.8.2\npython-dotenv==1.0.0\npytz==2022.7.1\nrequests==2.30.0\nrsa==4.9\nscikit-learn==1.2.1\nscipy==1.10.1\nsix==1.16.0\nsqlparse==0.4.3\nthreadpoolctl==3.1.0\ntzdata==2023.3\nuritemplate==4.1.1\nurllib3==2.0.2\nwhitenoise==6.4.0\n</code></pre>\n<p>After that we setup Django using:</p>\n<pre><code class=\"hljs language-bash\">django-admin startproject ecommerce\n</code></pre>\n<p>Next we create a new app using:</p>\n<pre><code class=\"hljs language-bash\">django-admin startapp recommender\n</code></pre>\n<p>Next we setup the app in our <strong>ecommerce/</strong><code>settings.py</code></p>\n<figure>\n  <img src=\"/blog/content-based-recommendation-django/img-4.png\" alt=\"settings.py\">\n  <figcaption>settings.py</figcaption>\n</figure>\n<p>Lets create a <strong>recommender/</strong><code>models.py</code> file and include the below content (<a href=\"https://github.com/Edolor/E-commerce-Recommendation-System/blob/master/recommender/models.py\">File Here</a>):</p>\n<figure>\n  <img src=\"/blog/content-based-recommendation-django/img-5.png\" alt=\"models.py\">\n  <figcaption>models.py</figcaption>\n</figure>\n<p>We then register the file in <strong>recommender/admin.py</strong></p>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from</span> django.contrib <span class=\"hljs-keyword\">import</span> admin\n<span class=\"hljs-keyword\">from</span> .models <span class=\"hljs-keyword\">import</span> SimilarityModel\n\nadmin.site.register(SimilarityModel)\n</code></pre>\n<p>Now in <strong>recommender/<code>views.py</code></strong> we'll have <strong>(<a href=\"https://github.com/Edolor/E-commerce-Recommendation-System/blob/master/recommender/views.py\">File Here</a>)</strong></p>\n<figure>\n  <img src=\"/blog/content-based-recommendation-django/img-6.png\" alt=\"recommender/views.py\">\n  <figcaption>recommender/views.py</figcaption>\n</figure>\n<p>Finally for the recommender, we setup <strong>recommender/<code>apps.py</code></strong> to ensure we train our models immediately our server is spawned on production (<a href=\"https://docs.djangoproject.com/en/5.0/topics/signals/\">Learn more about ready() and Django Signals</a>).</p>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from</span> django.apps <span class=\"hljs-keyword\">import</span> AppConfig\n\n<span class=\"hljs-keyword\">class</span> <span class=\"hljs-title class_\">RecommenderConfig</span>(<span class=\"hljs-title class_ inherited__\">AppConfig</span>):\n    default_auto_field = <span class=\"hljs-string\">'django.db.models.BigAutoField'</span>\n    name = <span class=\"hljs-string\">'recommender'</span>\n\n    <span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">ready</span>(<span class=\"hljs-params\">self</span>):\n        <span class=\"hljs-keyword\">from</span> .views <span class=\"hljs-keyword\">import</span> train_model_init\n        train_model_init() <span class=\"hljs-comment\"># Handle initial setup of model</span>\n</code></pre>\n<p>The end.🔚</p>\n<h2>Conclusion</h2>\n<p>This article primarily <strong>touched the fundamentals</strong> of building a full-scale content-based recommendation systems with Django. View the <a href=\"https://www.geeksforgeeks.org/ml-content-based-recommender-system/\">Completed Project</a> to understand more how the various apps within the Django project communicate and interact.</p>\n<h2>Extra Resources</h2>\n<ol>\n<li>Learn more about <a href=\"https://www.geeksforgeeks.org/understanding-tf-idf-term-frequency-inverse-document-frequency/\">TF-IDF Vectorizer</a></li>\n<li>Learn more about <a href=\"https://medium.com/@arjunprakash027/understanding-cosine-similarity-a-key-concept-in-data-science-72a0fcc57599\">Cosine Similarity</a></li>\n<li>Learn more about <a href=\"https://medium.com/@prateekgaurav/step-by-step-content-based-recommendation-system-823bbfd0541c\">Content Based Recommendation Systems - Practical</a></li>\n<li>View the Github Repository <a href=\"https://github.com/Edolor/E-commerce-Recommendation-System\">Here</a></li>\n<li>Learn more about <a href=\"https://www.geeksforgeeks.org/ml-content-based-recommender-system/\">Content Based Recommendation Systems - Theory</a></li>\n</ol>","date_published":"2024-04-30T00:00:00.000Z","tags":["django","machine-learning","python"]}]}