Use Cases

Como construir un sistema de autenticacion con Claude Code (JWT y OAuth)

Como construir un sistema de autenticacion con Claude Code (JWT y OAuth). Guia practica con ejemplos de codigo.

Ventajas de usar Claude Code para construir sistemas de autenticacion

La autenticacion es una funcionalidad directamente relacionada con la seguridad, y los errores de implementacion pueden causar vulnerabilidades graves. Claude Code puede generar implementaciones basadas en las mejores practicas de seguridad y tambien proponer contramedidas contra vectores de ataque que a menudo se pasan por alto.

Implementacion de autenticacion JWT

> Implementa autenticacion JWT con Express + TypeScript.
> Usa un esquema de 2 tokens: access token (15 min) y refresh token (7 dias).
> Gestiona el refresh token con cookies httpOnly.

Servicio de autenticacion

import jwt from 'jsonwebtoken';
import bcrypt from 'bcrypt';
import { prisma } from './db';

const ACCESS_TOKEN_SECRET = process.env.ACCESS_TOKEN_SECRET!;
const REFRESH_TOKEN_SECRET = process.env.REFRESH_TOKEN_SECRET!;

interface TokenPayload {
  userId: string;
  email: string;
}

export class AuthService {
  async register(email: string, password: string, name: string) {
    const existing = await prisma.user.findUnique({ where: { email } });
    if (existing) throw new Error('El correo ya esta registrado');

    const hashedPassword = await bcrypt.hash(password, 12);
    const user = await prisma.user.create({
      data: { email, password: hashedPassword, name },
    });

    return this.generateTokens({ userId: user.id, email: user.email });
  }

  async login(email: string, password: string) {
    const user = await prisma.user.findUnique({ where: { email } });
    if (!user) throw new Error('Credenciales invalidas');

    const valid = await bcrypt.compare(password, user.password);
    if (!valid) throw new Error('Credenciales invalidas');

    return this.generateTokens({ userId: user.id, email: user.email });
  }

  async refreshToken(token: string) {
    const payload = jwt.verify(token, REFRESH_TOKEN_SECRET) as TokenPayload;

    // Verificar la validez del refresh token en la BD
    const stored = await prisma.refreshToken.findFirst({
      where: { token, userId: payload.userId, revoked: false },
    });
    if (!stored) throw new Error('Refresh token invalido');

    // Invalidar el token antiguo (rotacion de tokens)
    await prisma.refreshToken.update({
      where: { id: stored.id },
      data: { revoked: true },
    });

    return this.generateTokens(payload);
  }

  private async generateTokens(payload: TokenPayload) {
    const accessToken = jwt.sign(payload, ACCESS_TOKEN_SECRET, {
      expiresIn: '15m',
    });
    const refreshToken = jwt.sign(payload, REFRESH_TOKEN_SECRET, {
      expiresIn: '7d',
    });

    await prisma.refreshToken.create({
      data: { token: refreshToken, userId: payload.userId },
    });

    return { accessToken, refreshToken };
  }
}

Middleware de autenticacion

import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';

export function authMiddleware(req: Request, res: Response, next: NextFunction) {
  const header = req.headers.authorization;
  if (!header?.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Token no proporcionado' });
  }

  const token = header.slice(7);

  try {
    const payload = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET!);
    req.user = payload as TokenPayload;
    next();
  } catch (err) {
    return res.status(401).json({ error: 'Token invalido o expirado' });
  }
}

Configuracion del router

import { Router } from 'express';
import { AuthService } from './auth-service';

const router = Router();
const auth = new AuthService();

router.post('/register', async (req, res) => {
  try {
    const { accessToken, refreshToken } = await auth.register(
      req.body.email, req.body.password, req.body.name
    );
    res.cookie('refreshToken', refreshToken, {
      httpOnly: true,
      secure: true,
      sameSite: 'strict',
      maxAge: 7 * 24 * 60 * 60 * 1000,
    });
    res.json({ accessToken });
  } catch (err) {
    res.status(400).json({ error: (err as Error).message });
  }
});

router.post('/login', async (req, res) => {
  try {
    const { accessToken, refreshToken } = await auth.login(
      req.body.email, req.body.password
    );
    res.cookie('refreshToken', refreshToken, {
      httpOnly: true,
      secure: true,
      sameSite: 'strict',
      maxAge: 7 * 24 * 60 * 60 * 1000,
    });
    res.json({ accessToken });
  } catch (err) {
    res.status(401).json({ error: 'Credenciales invalidas' });
  }
});

router.post('/refresh', async (req, res) => {
  try {
    const token = req.cookies.refreshToken;
    const { accessToken, refreshToken } = await auth.refreshToken(token);
    res.cookie('refreshToken', refreshToken, {
      httpOnly: true,
      secure: true,
      sameSite: 'strict',
      maxAge: 7 * 24 * 60 * 60 * 1000,
    });
    res.json({ accessToken });
  } catch (err) {
    res.status(401).json({ error: 'Refresh token invalido' });
  }
});

export default router;

Integracion OAuth (Google)

> Anade login con Google usando PassportJS. Integralo con la autenticacion JWT existente.
import passport from 'passport';
import { Strategy as GoogleStrategy } from 'passport-google-oauth20';

passport.use(new GoogleStrategy({
  clientID: process.env.GOOGLE_CLIENT_ID!,
  clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
  callbackURL: '/auth/google/callback',
}, async (accessToken, refreshToken, profile, done) => {
  let user = await prisma.user.findFirst({
    where: { providerId: profile.id, provider: 'google' },
  });

  if (!user) {
    user = await prisma.user.create({
      data: {
        email: profile.emails![0].value,
        name: profile.displayName,
        provider: 'google',
        providerId: profile.id,
      },
    });
  }

  done(null, user);
}));

Lista de verificacion de seguridad

Puedes solicitar a Claude Code una auditoria de seguridad con el siguiente prompt.

> Revisa el codigo de autenticacion desde la perspectiva de seguridad.
> Verifica segun el OWASP Top 10.

Los principales puntos de verificacion son:

  • Se utiliza bcrypt para el hash de contrasenas
  • La clave secreta JWT es suficientemente larga
  • La rotacion de refresh tokens esta implementada
  • Se aplican medidas contra CSRF
  • El rate limiting esta configurado

Para mantener la calidad del codigo incluyendo seguridad, la automatizacion de refactorizacion tambien es efectiva. Ademas, si documentas las politicas de configuracion de autenticacion en CLAUDE.md, Claude Code generara codigo consistente.

Summary

Con Claude Code puedes construir eficientemente un sistema de autenticacion robusto que incluye autenticacion JWT e integracion OAuth. Al generar codigo basado en las mejores practicas de seguridad, resulta mas facil abordar vulnerabilidades que a menudo se pasan por alto. Asegurate de gestionar las claves secretas de forma segura y de usar comunicacion HTTPS en el entorno de produccion.

Para mas detalles, consulta la documentacion oficial de Anthropic.

#Claude Code #authentication #JWT #OAuth #security