Labs ICT
Pro Login

API Authentication

3 min read | Next.js Tutorial

Want the full learning experience?

Get structured courses, certificates, projects, and instructor support with LabsICT Pro.

Explore Pro Courses

API Authentication

Authentication is crucial for protecting your API routes and user data. Next.js provides several ways to implement authentication, from simple token-based systems to robust solutions like NextAuth.js.

Think of authentication as a bouncer at a club. It checks IDs, verifies credentials, and only lets authorized users in. Your API needs similar protection to prevent unauthorized access.

Token-Based Authentication

The most common approach is using JWT (JSON Web Tokens). Here's how to implement it:

// app/api/auth/login/route.js
import { NextResponse } from 'next/server';
import jwt from 'jsonwebtoken';

export async function POST(request) {
  const { email, password } = await request.json();
  
  const user = await authenticateUser(email, password);
  
  if (!user) {
    return NextResponse.json(
      { error: 'Invalid credentials' },
      { status: 401 }
    );
  }
  
  const token = jwt.sign(
    { userId: user.id, email: user.email },
    process.env.JWT_SECRET,
    { expiresIn: '7d' }
  );
  
  return NextResponse.json({ token, user });
}

This creates a login endpoint that returns a JWT token. The client can store this token and send it with subsequent requests.

Verifying Tokens

You need to verify tokens on protected routes. Create a helper function to extract and validate the token:

// app/api/users/route.js
import { NextResponse } from 'next/server';
import jwt from 'jsonwebtoken';

function verifyAuth(request) {
  const authHeader = request.headers.get('authorization');
  
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return null;
  }
  
  const token = authHeader.split(' ')[1];
  
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    return decoded;
  } catch (error) {
    return null;
  }
}

export async function GET(request) {
  const user = verifyAuth(request);
  
  if (!user) {
    return NextResponse.json(
      { error: 'Unauthorized' },
      { status: 401 }
    );
  }
  
  const users = await getUsers();
  return NextResponse.json(users);
}

Using NextAuth.js

For more complex authentication needs, consider NextAuth.js. It provides a complete authentication solution with multiple providers.

// app/api/auth/[...nextauth]/route.js
import NextAuth from 'next-auth';
import GithubProvider from 'next-auth/providers/github';
import GoogleProvider from 'next-auth/providers/google';

const handler = NextAuth({
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
    GoogleProvider({
      clientId: process.env.GOOGLE_ID,
      clientSecret: process.env.GOOGLE_SECRET,
    }),
  ],
});

export { handler as GET, handler as POST };

NextAuth.js handles the entire authentication flow, including sign-in, sign-out, and session management.

Best Practices

Follow these best practices for secure authentication:

Use HTTPS: Always use HTTPS in production to prevent token interception.

Store tokens securely: Use httpOnly cookies or secure storage mechanisms.

Implement refresh tokens: Use short-lived access tokens with refresh tokens for better security.

Validate on the server: Never trust client-side validation alone. Always verify tokens on the server.

Authentication is a critical security layer. Take it seriously and test your implementation thoroughly.