Auth
Autenticación sobre NextAuth v5 con tablas drizzle, bloqueo por intentos, revocación de sesiones, 2FA y SSO.
@fesa/components/auth-v2 trae las piezas para montar NextAuth v5 con credenciales sobre MySQL y drizzle. Requiere next-auth y drizzle-orm en la app.
import { createAuthTables } from '@fesa/components/auth-v2'
export const ROLES = ['admin', 'usuario'] as const
export const { users, authTokens, revokedSessions, activeSessions } = createAuthTables({
roles: ROLES,
defaultRole: 'usuario',
})import NextAuth from 'next-auth'
import Credentials from 'next-auth/providers/credentials'
import {
createAuthCallbacks,
createCredentialsAuthorize,
createDrizzleAuthStorage,
createRevocation,
createSessionUserCache,
} from '@fesa/components/auth-v2'
import { activeSessions, authTokens, revokedSessions, users } from '@/db/schema'
import { db } from '@/lib/db'
const authStorage = createDrizzleAuthStorage(db, { users, authTokens, revokedSessions, activeSessions })
const revocation = createRevocation({ storage: authStorage })
const callbacks = createAuthCallbacks({
getCachedSessionUser: createSessionUserCache(authStorage),
getFreshSessionUser: (userId) => authStorage.getSessionUser(userId),
isSessionRevoked: revocation.isSessionRevoked,
claimsFromSignInUser: (user) => ({ role: user.role }),
claimsFromSessionUser: (user) => ({ role: user.role, name: user.name, email: user.email }),
sessionUserFromToken: (token) => ({ role: token.role, name: token.name, email: token.email }),
})
export const { handlers, auth, signIn, signOut } = NextAuth({
session: { strategy: 'jwt' },
providers: [
Credentials({
credentials: { email: {}, password: {} },
authorize: createCredentialsAuthorize({ storage: authStorage }),
}),
],
callbacks: { jwt: callbacks.jwt, session: callbacks.session },
})Ejemplo completo en producción: lib/auth.ts de developers.fesa.com.pa.