Understanding Authentication Concepts
What is Axios? Explanation JWT & Bcrypt JWT is a way to securely transmit information between parties as a JSON object. Think of it as a digital passport: Structure: header.payload.signature Use: After login, the ser
What is Axios?
Explanation JWT & Bcrypt
JWT is a way to securely transmit information between parties as a JSON object. Think of it as a digital passport:
- Structure: header.payload.signature
- Use: After login, the server gives you a token. You send this token with every request to prove "you are you"
Bcrypt is a password hashing algorithm:
- Hashing = Turning a password into a scrambled, irreversible string
- Salt = Adds random data to make each hash unique
- Slow = Deliberately slow to prevent brute force attacks
The Authentication Flow:
- User signs up โ Password โ Bcrypt hashes โ Save in database
- User logs in โ Check password with Bcrypt โ If correct, create JWT
- User sends JWT with requests โ Server verifies JWT โ Allow access
How to Install
Run this command in your terminal:
shell
npm install jsonwebtoken bcryptjs
npm install --save-dev @types/jsonwebtoken @types/bcryptjs
Setting Up Environment Variables
Create .env.local:
JWT_SECRET=your-super-secret-key-change-this-in-production
JWT_EXPIRES_IN=7d
Bcrypt - Password Hashing
Create a folder app/api/auth/register/route.ts import:
import { NextResponse } from 'next/server';
import bcrypt from 'bcryptjs';
And Then:
export async function POST(request: Request) {
try {
// 1. Get data from request
const { email, password, name } = await request.json();
// 2. Validate (simple check)
if (!email || !password) {
return NextResponse.json(
{ error: 'Email and password required' },
{ status: 400 }
);
}
// 3. Hash the password with bcrypt
const saltRounds = 10; // Higher = more secure, but slower
const hashedPassword = await bcrypt.hash(password, saltRounds);
// 4. Save user to database (we'll use mock data for now)
// In real project: Save to MongoDB/PostgreSQL
const mockUser = {
id: Date.now(),
email,
name,
password: hashedPassword, // Save HASHED password, NOT plain text!
};
// 5. Return success response
return NextResponse.json(
{
message: 'User created successfully',
user: { id: mockUser.id, email, name }
},
{ status: 201 }
);
} catch (error) {
return NextResponse.json(
{ error: 'Something went wrong' },
{ status: 500 }
);
}
}
Password Hashing Explained
Hash the password:
const hashedPassword = await bcrypt.hash(plainPassword, 10);
Result:
$2a$10$UY8x9sKjdlKjfaksjdf98234kjsdf"
Why?
- Even if database is hacked, hackers can't read the password!
JWT - Creating and Verifying Tokens
Create app/api/auth/login/route.ts:
Import:
import { NextResponse } from 'next/server';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
Mock database (in real project,we use real DB):
const users = [
{
id: 1,
email: '[email protected]',
password: '$2a$10$...', // Hashed password from registration
name: 'Test User'
}
];
And then, Create an async function:
export async function POST(request: Request) {
try {
const { email, password } = await request.json();
// 1. Find user in database
const user = users.find(u => u.email === email);
if (!user) {
return NextResponse.json(
{ error: 'Invalid credentials' },
{ status: 401 }
);
}
// 2. Check password with bcrypt
const isValid = await bcrypt.compare(password, user.password);
if (!isValid) {
return NextResponse.json(
{ error: 'Invalid credentials' },
{ status: 401 }
);
}
// 3. Create JWT token
const token = jwt.sign(
{
userId: user.id,
email: user.email
},
process.env.JWT_SECRET!, // Your secret key
{ expiresIn: '7d' } // Token expires in 7 days
);
// 4. Return token to client
return NextResponse.json({
token,
user: {
id: user.id,
email: user.email,
name: user.name
}
});
} catch (error) {
return NextResponse.json(
{ error: 'Login failed' },
{ status: 500 }
);
}
}
Verifying JWT Token in Protected Routes
Create app/api/auth/profile/route.ts:
Import:
import { NextResponse } from 'next/server';
import jwt from 'jsonwebtoken';
Create a GET Request:
export async function GET(request: Request) {
try {
// 1. Get token from Authorization header
const authHeader = request.headers.get('authorization');
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return NextResponse.json(
{ error: 'No token provided' },
{ status: 401 }
);
}
// 2. Extract token (remove "Bearer " prefix)
const token = authHeader.split(' ')[1];
// 3. Verify and decode token
const decoded = jwt.verify(token, process.env.JWT_SECRET!);
// 4. Return user data
return NextResponse.json({
user: decoded,
message: 'Protected data accessed!'
});
} catch (error) {
return NextResponse.json(
{ error: 'Invalid or expired token' },
{ status: 401 }
);
}
}```
**Using Authentication**
In Login Form Component:
``
try {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || 'Login failed');
}
``
**Save token to cookies:**
``
Cookies.setItem('token', data.token);
Cookies.setItem('user', JSON.stringify(data.user));
``
Or we can create a utility function in lib/auth.ts instead of writing here.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes โ full credit and traffic to the original publisher.