Autenticación de Credenciales

Autenticación mediante correo y contraseña para apps creadas con Prisma PHP.

Introducción

La autenticación mediante credenciales permite a los usuarios iniciar sesión con su correo electrónico y contraseña. Prisma PHP admite autenticación segura sin depender de servicios externos.

Este método ofrece una forma fiable de verificar identidades y proteger contenido privado dentro de aplicaciones web desarrolladas con Prisma PHP.

Configuración de la Autenticación de Credenciales

La configuración implica crear un modelo de usuario en schema.prisma con campos de correo y contraseña y generar las migraciones necesarias.

Creación de un modelo de usuario


model User 
  id            String    @id @default(cuid())
  name          String?
  email         String?   @unique
  password      String?
  emailVerified DateTime?
  image         String?

  roleId   Int?
  userRole UserRole? @relation(fields: [roleId], references: [id])

  @@map("Users")


model UserRole 
  id   Int    @id @default(autoincrement())
  name String @unique

  user User[]

Para generar tus clases PHP ejecuta:


npx ppo generate

Prisma PHP crea por defecto los modelos User y UserRole. Puedes modificarlos según lo necesites.

Registro de usuario — Rutas públicas

En modo público, todas las rutas son accesibles y debes controlar manualmente la redirección tras iniciar sesión.

Crea la ruta en: src/app/auth/register/index.php


<?php

use Lib\Auth\Auth;
use Lib\Prisma\Classes\Prisma;
use Lib\Validator;
use Lib\Request;

$auth = Auth::getInstance();

if ($auth->isAuthenticated()) {
  Request::redirect('/dashboard');
}

function register($data)
{
  $name = Validator::string($data->name);
  $email = Validator::email($data->email);
  $password = Validator::string($data->password);
  $confirmPassword = Validator::string($data->confirmPassword);

  if (!$name || !$email || !$password || !$confirmPassword) 
    return ['message' => 'All fields are required'];
  elseif ($password !== $confirmPassword) 
    return ['message' => 'Passwords do not match'];
  else
    $prisma = Prisma::getInstance();
    $userExist = $prisma->user->findUnique([
      'where' => ['email' => $email]
    ]);

    if ($userExist) {
      return ['message' => 'Email already exists'];
    }

    $prisma->user->create([
      'data' => [
        'name' => $name,
        'email' => $email,
        'password' => password_hash($password, PASSWORD_DEFAULT),
        'userRole' => [
          'connectOrCreate' => [
            'where' => ['name' => 'User'],
            'create' => ['name' => 'User']
          ]
        ]
      ]
    ]);

    Request::redirect('/auth/login');
}
?>

<div class="min-h-screen flex items-center justify-center bg-gray-100">
  <div class="bg-white p-8 rounded-lg shadow-lg w-full max-w-md">
    <h1 class="text-2xl font-bold mb-6">Register</h1>

    <form class="space-y-4" onsubmit="register" pp-after-request="registerResponse">
      <div>
        <label for="name">Name</label>
        <input type="text" name="name" id="name" class="mt-1 block w-full border rounded-md" />
      </div>

      <div>
        <label for="email">Email</label>
        <input type="email" name="email" id="email" class="mt-1 block w-full border rounded-md" />
      </div>

      <div>
        <label for="password">Password</label>
        <input type="password" name="password" id="password" class="mt-1 block w-full border rounded-md" />
      </div>

      <div>
        <label for="confirmPassword">Confirm Password</label>
        <input type="password" name="confirmPassword" id="confirmPassword" class="mt-1 block w-full border rounded-md" />
      </div>

      <button type="submit" class="w-full bg-indigo-600 text-white py-2 rounded-md">
        Register
      </button>
    </form>

    <p id="register-message" class="text-red-500 mt-4"></p>

    <a href="/auth/login" class="text-indigo-600 hover:underline mt-4 block">
      Login
    </a>
  </div>
</div>

Formulario de Inicio de Sesión — Rutas públicas

Crea tu ruta en: src/app/auth/login/index.php


<?php
use Lib\Validator;
use Lib\Prisma\Classes\Prisma;
use Lib\Auth\Auth;
use Lib\Request;

$auth = Auth::getInstance();

if ($auth->isAuthenticated()) {
  Request::redirect('/dashboard');
}

function login($data)
{
  $email = Validator::email($data->email);
  $password = Validator::string($data->password);

  if (!$email || !$password) {
    return ['message' => 'All fields are required'];
  }

  $prisma = Prisma::getInstance();
  $user = $prisma->user->findUnique([
    'where' => ['email' => $email]
  ], true);

  if (!$user) {
    return ['message' => 'User not found'];
  }

  if (!password_verify($password, $user->password)) {
    return ['message' => 'Invalid password'];
  }

  $auth->signIn($user);
  Request::redirect('/dashboard');
}
?>

<div class="min-h-screen flex items-center justify-center bg-gray-100">
  <div class="bg-white p-8 rounded-lg shadow-lg w-full max-w-md">
    <h1 class="text-2xl font-bold mb-6 text-center">Login</h1>

    <form class="space-y-6" onsubmit="login" pp-after-request="loginResponse">
      <div>
        <label for="email">Email</label>
        <input type="email" name="email" id="email" class="mt-1 block w-full border rounded-md" />
      </div>

      <div>
        <label for="password">Password</label>
        <input type="password" name="password" id="password" class="mt-1 block w-full border rounded-md" />
      </div>

      <button class="w-full bg-indigo-600 text-white py-2 rounded-md">
        Login
      </button>
    </form>

    <p id="login-message" class="text-red-500 mt-4"></p>

    <a href="/auth/register" class="text-indigo-600 hover:underline block mt-6 text-center">
      Register
    </a>
  </div>
</div>

Conclusión

La autenticación de credenciales en Prisma PHP permite a los usuarios iniciar sesión con correo y contraseña, almacenados de forma segura. Este modelo proporciona flexibilidad, control y una base sólida para implementar sistemas de acceso seguros en cualquier proyecto.