Labs ICT
Pro Login

API Authentication

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.