Credential Authentication
The classic, robust approach. Enable users to sign up and log in using their email and password, featuring secure storage, hashing, and built-in validation.
Persistence
Simple data modeling using Prisma ORM schemas.
Security
Password hashing and automatic CSRF protection handled by the framework.
Full Stack
Colocate your backend logic and frontend forms in a single file.
Database Schema
First, define the user model in your schema.prisma. You will need fields for credentials and roles to support the AuthRole enum.
model User { id String @id @default(cuid()) name String? email String? @unique password String? // Password Hash 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[] }
npx ppo generate
User Registration
Create the route src/app/auth/register/index.php. We use the #[Exposed] attribute to allow the frontend to call the PHP function directly.
<?php use Lib\Auth\Auth; use Lib\Prisma\Classes\Prisma; use Lib\Validator; use PP\Attributes\Exposed; // Redirect if already logged in if (Auth::getInstance()->isAuthenticated()) { Request::redirect('/dashboard'); } #[Exposed] function register($data) { $email = Validator::email($data->email); $pass = Validator::string($data->password); if (!$email || !$pass) return ['error' => 'Invalid data']; $prisma = Prisma::getInstance(); // Check existence if ($prisma->user->findUnique([ 'where' => ['email' => $email] ])) { return ['error' => 'Email already exists']; } // Create User $prisma->user->create([ 'data' => [ 'email' => $email, 'password' => password_hash($pass, PASSWORD_DEFAULT), 'userRole' => [ 'connectOrCreate' => [ 'where' => ['name' => 'User'], 'create' => ['name' => 'User'] ] ] ] ]); Request::redirect('/auth/login'); } ?>
<div class="max-w-md mx-auto mt-10"> <form onsubmit="register" pp-after-request="onReg"> <!-- Inputs --> <input name="email" type="email" /> <input name="password" type="password" /> <button>Register</button> </form> <p id="error-msg" class="text-red-500"></p> </div> <script> function onReg(response) { if (response.error) { document.getElementById('error-msg') .innerText = response.error; } } </script>
Sign In
In src/app/auth/login/index.php, we verify credentials and use the Auth::signIn method to establish the session.
<?php use Lib\Auth\Auth; use Lib\Prisma\Classes\Prisma; use PP\Attributes\Exposed; #[Exposed] function login($data) { $email = $data->email; $pass = $data->password; // Fetch user and include Role relation $user = Prisma::getInstance()->user->findUnique([ 'where' => ['email' => $email], 'include' => ['userRole' => true] ]); if (!$user || !password_verify($pass, $user->password)) { return ['error' => 'Invalid credentials']; } // Sign in with data and Role name Auth::getInstance()->signIn([ 'id' => $user->id, 'role' => $user->userRole->name ?? 'User' ]); Request::redirect('/dashboard'); } ?> <!-- Simple HTML Form --> <form onsubmit="login" class="space-y-4"> <input name="email" placeholder="user@example.com" /> <input name="password" type="password" /> <button>Sign In</button> </form>