Building JWT Authentication for My Placement Portal with Django and Next.js
After setting up the project structure for my Placement Portal, the very first feature I decided to implement wasn't the dashboard or the student profile.
It was authentication.
Every request made to the backend should answer two fundamental questions:
- Who is making this request?
- Is this user authorized to perform this action?
Without authentication, the rest of the application simply cannot function securely.

Figure 1: JWT-based authentication architecture used in my Placement Portal, where Django acts as the backend API and Next.js serves as the frontend.
Choosing Email and Password Authentication
For the MVP, I implemented a traditional email and password login.
A user enters their credentials, and upon successful authentication, the backend issues two JSON Web Tokens (JWT):
- Access Token
- Refresh Token
These tokens are then used to authenticate every future request made by the frontend.
Although the login process appears simple from the user's perspective, the authentication mechanism behind it is significantly different from traditional session-based authentication.
Session Authentication vs JWT Authentication
Initially, I was more familiar with session-based authentication.
In a session-based system:
- The server creates a session.
- A unique Session ID is generated.
- The browser stores that Session ID.
- Every request sends the same Session ID back to the server.
The session remains valid until it expires or the user logs out.
The downside is that if an attacker manages to steal a valid session identifier, they may be able to impersonate the user until the session ends.
JWT authentication approaches the problem differently.
Instead of relying on one long-lived session, authentication is divided into two tokens with different responsibilities.
Access Token and Refresh Token
Using dj-rest-auth, I implemented JWT authentication with:
- Access Token (15-minute lifetime)
- Refresh Token (1-week lifetime)
The Access Token is used to authenticate API requests.
Once it expires, the frontend silently requests a new Access Token using the Refresh Token.
If the Refresh Token has also expired, the user is redirected to the login page and must authenticate again.
This creates a much smoother user experience while limiting the lifetime of compromised Access Tokens.
Why HTTP-Only Cookies?
The authentication tokens are stored as HTTP-only cookies.
Unlike tokens stored in browser local storage, HTTP-only cookies cannot be accessed through JavaScript.
This significantly reduces the risk of token theft through Cross-Site Scripting (XSS) attacks.
For a SaaS application where the frontend and backend are deployed separately, this approach provides a good balance between security and usability.
Why I Chose dj-rest-auth
Since my backend is built with Django and my frontend uses Next.js, I wanted an authentication solution designed for separated frontend-backend architectures.
After evaluating different options, I chose dj-rest-auth because it provides:
- JWT authentication
- Secure cookie support
- Login and logout endpoints
- Password reset functionality
- Registration endpoints
- Good integration with Django REST Framework
For the current stage of the project, it offers everything needed for a secure authentication system.
What Still Needs Improvement
Although authentication is working, it isn't complete yet.
The next security feature I plan to implement is Multi-Factor Authentication (MFA) using applications like Google Authenticator.
Adding a second authentication factor will provide another layer of protection, especially for university administrators and company recruiters who have access to sensitive student information.
What's Next?
With authentication complete, the next milestone is implementing Role-Based Access Control (RBAC) so that Students, Companies, Universities, and Administrators only access the resources they're authorized to use.
Authentication identifies who the user is.
Authorization determines what they are allowed to do.
That's the next challenge I'll be solving as I continue building this Placement Portal in public.