dbstudios/veritas
Laravel package for verifying and validating incoming request data and payloads with a consistent rule-based approach. Helps enforce data integrity across APIs and forms, offering a lightweight way to define checks, run assertions, and return clear validation feedback.
Install and Publish Config
composer require dbstudios/veritas
php artisan vendor:publish --provider="DbStudios\Veritas\VeritasServiceProvider"
Configure config/veritas.php with:
secret: Your JWT signing key (use openssl rand -base64 32 for HS256).issuer: Your application’s identifier (e.g., your-app-name).audience: Target audience (e.g., mobile-app or api).Register the Guard
In AuthServiceProvider.php, extend the guard in boot():
public function boot()
{
$this->app['auth']->extend('jwt', function ($app) {
return new \DbStudios\Veritas\Guard(
$app['auth']->createUserProvider(),
app('request')
);
});
}
First Token Generation
use DbStudios\Veritas\Facades\Veritas;
$user = User::find(1);
$token = Veritas::generate([
'sub' => $user->id,
'name' => $user->name,
'iat' => now()->getTimestamp(),
'exp' => now()->addMinutes(60),
]);
First Validation:
$payload = Veritas::verify($token);
// $payload now contains the decoded claims
Protect a Route
Use the auth:jwt middleware in routes/api.php:
Route::middleware('auth:jwt')->get('/user', function () {
return response()->json(auth()->user());
});
Veritas excels at decoupling validation logic from controllers. Define reusable rules in service classes or form request objects:
// app/Rules/UserRegistrationRules.php
namespace App\Rules;
use DbStudios\Veritas\Rules\RuleSet;
class UserRegistrationRules extends RuleSet
{
public function rules()
{
return [
'email' => ['required', 'email', 'unique:users'],
'password' => ['required', 'min:8', 'confirmed'],
'terms_accepted' => ['accepted'],
];
}
public function messages()
{
return [
'email.unique' => 'This email is already taken.',
'password.min' => 'Password must be at least 8 characters.',
];
}
}
public function register(Request $request)
{
$validator = app(UserRegistrationRules::class);
if ($validator->fails($request->all())) {
return response()->json(['errors' => $validator->errors()], 422);
}
// Proceed with registration...
}
Generate tokens with context-aware claims (e.g., tenant ID, IP address):
$token = Veritas::generate([
'sub' => auth()->id(),
'tenant_id' => request()->tenant_id, // Dynamic claim
'ip' => request()->ip(),
'exp' => now()->addMinutes(15),
], [
'alg' => 'HS256',
'key' => config('veritas.secret'),
]);
Extend Veritas middleware to enforce custom claims (e.g., roles):
// app/Http/Middleware/CheckRole.php
namespace App\Http\Middleware;
use Closure;
use DbStudios\Veritas\Facades\Veritas;
class CheckRole
{
public function handle($request, Closure $next, $role)
{
$payload = Veritas::verify($request->bearerToken());
if (!in_array($role, $payload->get('roles', []))) {
abort(403, 'Forbidden');
}
return $next($request);
}
}
Register in Kernel.php:
protected $routeMiddleware = [
'role' => \App\Http\Middleware\CheckRole::class,
];
Usage:
Route::middleware(['auth:jwt', 'role:admin'])->get('/admin');
Implement refresh tokens with short-lived access tokens:
$user->refresh_token = $refreshToken;
$user->refresh_token_expires_at = now()->addDays(30);
$user->save();
public function refresh(Request $request)
{
$refreshToken = $request->input('refresh_token');
$user = User::where('refresh_token', $refreshToken)
->where('refresh_token_expires_at', '>', now())
->firstOrFail();
$newAccessToken = Veritas::generate([
'sub' => $user->id,
'exp' => now()->addMinutes(15),
]);
return response()->json(['access_token' => $newAccessToken]);
}
Use Veritas tokens in Laravel Policies for authorization:
// app/Policies/PostPolicy.php
public function update(User $user, Post $post)
{
$payload = Veritas::verify(request()->bearerToken());
return $payload->get('sub') === $user->id;
}
Extend Veritas with domain-specific rules:
// app/Rules/Custom/ValidAge.php
namespace App\Rules\Custom;
use DbStudios\Veritas\Rules\AbstractRule;
class ValidAge extends AbstractRule
{
public function passes($attribute, $value)
{
return $value >= 18;
}
public function message()
{
return 'You must be at least 18 years old.';
}
}
Usage in RuleSet:
public function rules()
{
return [
'age' => ['required', new ValidAge],
];
}
Clock Skew Issues
exp claims fail if server/client clocks are misaligned.exp claims:
'exp' => now()->addMinutes(65), // 60 + 5-minute buffer
Secret Key Management
VERITAS_SECRET=your_32_byte_base64_encoded_key
In config/veritas.php:
'secret' => env('VERITAS_SECRET'),
Token Revocation Complexity
// app/Http/Middleware/CheckRevokedToken.php
public function handle($request, Closure $next)
{
$token = $request->bearerToken();
if (Veritas::isRevoked($token)) {
abort(401, 'Token revoked');
}
return $next($request);
}
Large Payloads
$token = Veritas::generate([
'sub' => $user->id,
'user_data_id' => $user->userData->id, // Reference only
]);
Algorithm Mismatch
HS256 with a weak secret or RS256 without a private key.HS256 with a 32-byte random secret or RS256 with a PEM key pair:
// For RS256:
'alg' => 'RS256',
'key' => file_get_contents('path/to/private.key'),
Decode Tokens Locally Use jwt.io to inspect tokens or decode via PHP:
$payload = Veritas::verify($token, false); // Decode without validation
Enable Verbose Logging
Add to config/veritas.php:
'debug' => env('APP_DEBUG', false),
Check logs for validation errors in storage/logs/laravel.log.
Test Token Expiry
Manually set exp to a past date to simulate expiry:
$token = Veritas
How can I help you explore Laravel packages today?