Authentication

Authentication

Keel supports passwordless OTP, magic-link, or both.

Environment toggle

# otp | magic_link | both
AUTH_METHOD=both

Routes

$router->post('/auth/otp/request', [AuthController::class, 'requestOtp']);
$router->post('/auth/otp/verify', [AuthController::class, 'verifyOtp']);
$router->post('/auth/magic/request', [AuthController::class, 'requestMagicLink']);
$router->get('/auth/magic', [AuthController::class, 'verifyMagicLink']);

Current behavior

  • OTP: 6-digit code, hashed with password_hash(), 10-minute expiry.
  • Magic link: 32-byte token, SHA-256 hash at rest, 15-minute expiry.
  • Both flows send mail through the shared Mailer (see the Mailing docs page for SMTP/log setup).
  • Both flows rate-limit token issuance to 5 requests per 15 minutes per user.
  • Successful sign-in regenerates the session and sets user_id, user_email, and org/theme session values.
  • If multi-tenancy is enabled and no org is assigned, login redirects to /onboarding/organization; otherwise /dashboard.