0Pricing
React Academy · Lección

Proveedor de credenciales e inicio de sesión personalizado

Autentique usuarios contra una base de datos mediante un proveedor de credenciales y un formulario de inicio de sesión personalizado.

Proveedor de credenciales e inicio de sesión personalizado es una lección gratuita de React Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de React Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de React Academy incluye 4 lecciones en total.

Cuándo usar el proveedor Credentials

Use el proveedor Credentials cuando se autentique contra su propia base de datos (correo electrónico y contraseña) en lugar de usar un proveedor OAuth. Requiere gestionar cuidadosamente el hash de las contraseñas y la seguridad.

Definir el proveedor Credentials

Añada Credentials al array de proveedores. La función authorize recibe las credenciales enviadas y devuelve un objeto de usuario o null.

import Credentials from 'next-auth/providers/credentials';
import bcrypt from 'bcryptjs';

export const { handlers, auth } = NextAuth({
  providers: [
    Credentials({
      name: 'Credentials',
      credentials: {
        email: { label: 'Email', type: 'email' },
        password: { label: 'Password', type: 'password' },
      },
      async authorize(credentials) {
        const user = await db.user.findUnique({ where: { email: credentials.email as string } });
        if (!user) return null;
        const valid = await bcrypt.compare(credentials.password as string, user.passwordHash);
        if (!valid) return null;
        return { id: user.id, name: user.name, email: user.email };
      },
    }),
  ],
});

Formulario de inicio de sesión personalizado

Construya un formulario de inicio de sesión como Client Component que llame a signIn('credentials', { email, password }) desde next-auth/react.

'use client';
import { signIn } from 'next-auth/react';

export function LoginForm() {
  const [error, setError] = useState('');

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const form = new FormData(e.currentTarget);
    const result = await signIn('credentials', {
      email: form.get('email'),
      password: form.get('password'),
      redirect: false, // handle redirect manually
    });
    if (result?.error) setError('Invalid email or password');
    else router.push('/dashboard');
  }

  return (
    <form onSubmit={handleSubmit}>
      {error && <p className="error">{error}</p>}
      <input name="email" type="email" required />
      <input name="password" type="password" required />
      <button type="submit">Sign in</button>
    </form>
  );
}

redirect: false para gestionar errores

Pase redirect: false a signIn() para recibir el objeto de resultado y gestionar los errores en el componente, en lugar de redirigir a una página de error.

const result = await signIn('credentials', { email, password, redirect: false });
if (result?.error) {
  // result.error is 'CredentialsSignin' for auth failures
  setError('Invalid email or password');
}

Validación con Zod en authorize

Valide las credenciales con Zod dentro de la función authorize antes de consultar la base de datos.

import { z } from 'zod';

const schema = z.object({ email: z.string().email(), password: z.string().min(8) });

async authorize(credentials) {
  const parsed = schema.safeParse(credentials);
  if (!parsed.success) return null;
  const { email, password } = parsed.data;
  // ... db lookup
}

Estrategia de sesión para credenciales

El proveedor de credenciales requiere una estrategia de sesión JWT (no se necesita un adaptador de base de datos para las sesiones). Especifique explícitamente session: { strategy: 'jwt' }.

export const { handlers, auth } = NextAuth({
  session: { strategy: 'jwt' },
  providers: [Credentials({ ... })],
});

Añadir campos personalizados a la sesión

Pase datos adicionales del usuario mediante los callbacks de JWT y de sesión para exponerlos en useSession().

callbacks: {
  async jwt({ token, user }) {
    if (user) { token.id = user.id; token.role = user.role; }
    return token;
  },
  async session({ session, token }) {
    session.user.id = token.id as string;
    session.user.role = token.role as string;
    return session;
  },
},

Hash de contraseñas

Utilice siempre bcrypt para aplicar un hash a las contraseñas antes de almacenarlas. Nunca almacene contraseñas en texto plano.

import bcrypt from 'bcryptjs';

// On registration:
const passwordHash = await bcrypt.hash(password, 12);
await db.user.create({ data: { email, passwordHash } });

// On login (in authorize):
const valid = await bcrypt.compare(submittedPassword, user.passwordHash);

Limitación de intentos de inicio de sesión

Proteja el endpoint de credenciales contra ataques de fuerza bruta mediante la limitación de los intentos de inicio de sesión con middleware o un almacén en memoria.

// middleware.ts or in a rate-limiting library
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';

const ratelimit = new Ratelimit({ redis: Redis.fromEnv(), limiter: Ratelimit.slidingWindow(10, '10 s') });

// Check in authorize before DB query:
const { success } = await ratelimit.limit(credentials.email as string);
if (!success) return null;

Flujo de registro

El registro es independiente de Auth.js: cree el usuario en su base de datos (con la contraseña protegida mediante hash) a través de una Server Action o una ruta de API y, después, inicie sesión con signIn('credentials', ...).

Comprobación rápida

¿Por qué debe pasar redirect: false al llamar a signIn() en un formulario de inicio de sesión personalizado?

Resumen

El proveedor de credenciales llama a su función authorize con los datos enviados por el formulario. Valídelos con Zod, compare las contraseñas con hash mediante bcrypt y devuelva un objeto de usuario o null. Utilice redirect: false en el formulario para gestionar los errores de forma personalizada y use siempre la estrategia JWT con las credenciales.

Preguntas frecuentes

¿La lección «Proveedor de credenciales e inicio de sesión personalizado» es gratis?

Sí — el texto completo de «Proveedor de credenciales e inicio de sesión personalizado» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de React Academy, actualiza a CoddyKit PRO. El curso de React Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Proveedor de credenciales e inicio de sesión personalizado»?

Autentique usuarios contra una base de datos mediante un proveedor de credenciales y un formulario de inicio de sesión personalizado. Practicas React Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar React Academy?

No se requiere experiencia previa. React Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Proveedor de credenciales e inicio de sesión personalizado»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de React Academy?

Sí. Cada lección de React Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Configurar Auth.js en Next.js App Router
  2. Gestión de sesiones y hook useSession
  3. Proveedor de credenciales e inicio de sesión personalizado
  4. Protección de rutas mediante middleware
← Volver a React Academy