Overview
Cashify uses Laravel Breeze as its authentication foundation, providing a simple and clean implementation of login, registration, password reset, and email verification. Additionally, it supports social authentication through GitHub OAuth using Laravel Socialite.
Laravel Breeze Setup
Cashify comes with Laravel Breeze pre-configured, providing all the essential authentication features out of the box.
Installation
Breeze is already included in Cashify’s dependencies:
{
"require" : {
"laravel/breeze" : "^2.0" ,
"laravel/socialite" : "^5.15"
}
}
Authentication Routes
All authentication routes are defined in routes/auth.php:
Route :: middleware ( 'guest' ) -> group ( function () {
// Registration
Route :: get ( 'register' , [ RegisteredUserController :: class , 'create' ])
-> name ( 'register' );
Route :: post ( 'register' , [ RegisteredUserController :: class , 'store' ]);
// Login
Route :: get ( 'login' , [ AuthenticatedSessionController :: class , 'create' ])
-> name ( 'login' );
Route :: post ( 'login' , [ AuthenticatedSessionController :: class , 'store' ]);
// Password Reset
Route :: get ( 'forgot-password' , [ PasswordResetLinkController :: class , 'create' ])
-> name ( 'password.request' );
Route :: post ( 'forgot-password' , [ PasswordResetLinkController :: class , 'store' ])
-> name ( 'password.email' );
Route :: get ( 'reset-password/{token}' , [ NewPasswordController :: class , 'create' ])
-> name ( 'password.reset' );
Route :: post ( 'reset-password' , [ NewPasswordController :: class , 'store' ])
-> name ( 'password.store' );
// OAuth Social Login
Route :: get ( 'auth/{driver}/redirect' , [ SocialiteSessionController :: class , 'redirectToProvider' ])
-> where ( 'driver' , '(github|google)' )
-> name ( 'socialite.redirect' );
Route :: get ( 'auth/{driver}/callback' , [ SocialiteSessionController :: class , 'handleProviderCallback' ])
-> name ( 'socialite.callback' );
});
Route :: middleware ( 'auth' ) -> group ( function () {
// Email Verification
Route :: get ( 'verify-email' , EmailVerificationPromptController :: class )
-> name ( 'verification.notice' );
Route :: get ( 'verify-email/{id}/{hash}' , VerifyEmailController :: class )
-> middleware ([ 'signed' , 'throttle:6,1' ])
-> name ( 'verification.verify' );
// Logout
Route :: post ( 'logout' , [ AuthenticatedSessionController :: class , 'destroy' ])
-> name ( 'logout' );
});
Authentication Configuration
The authentication configuration is managed in config/auth.php:
return [
'defaults' => [
'guard' => env ( 'AUTH_GUARD' , 'web' ),
'passwords' => env ( 'AUTH_PASSWORD_BROKER' , 'users' ),
],
'guards' => [
'web' => [
'driver' => 'session' ,
'provider' => 'users' ,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent' ,
'model' => env ( 'AUTH_MODEL' , App\Models\ User :: class ),
],
],
'passwords' => [
'users' => [
'provider' => 'users' ,
'table' => env ( 'AUTH_PASSWORD_RESET_TOKEN_TABLE' , 'password_reset_tokens' ),
'expire' => 60 ,
'throttle' => 60 ,
],
],
'password_timeout' => env ( 'AUTH_PASSWORD_TIMEOUT' , 10800 ),
];
User Model
The User model implements email verification:
class User extends Authenticatable implements MustVerifyEmail
{
use HasFactory , Notifiable ;
protected $fillable = [
'name' ,
'email' ,
'password' ,
'provider' , // OAuth provider (github, google)
'provider_id' , // OAuth provider user ID
];
protected $hidden = [
'password' ,
'remember_token' ,
];
protected function casts () : array
{
return [
'email_verified_at' => 'datetime' ,
'password' => 'hashed' ,
];
}
// Check if user registered via OAuth
public function isSocialiteUser ()
{
return is_null ( $this -> password );
}
}
Standard Registration
Cashify includes Cloudflare Turnstile CAPTCHA protection on registration to prevent spam:
app/Http/Controllers/Auth/RegisteredUserController.php
public function store ( Request $request ) : RedirectResponse
{
$request -> validate ([
'name' => [ 'required' , 'string' , 'max:255' ],
'email' => [ 'required' , 'string' , 'lowercase' , 'email' , 'max:255' , 'unique:' . User :: class ],
'password' => [ 'required' , 'confirmed' , Rules\ Password :: defaults ()],
'cf-turnstile-response' => [ 'required' , 'string' ],
]);
// Validate Turnstile CAPTCHA
$response = Http :: asForm () -> post ( 'https://challenges.cloudflare.com/turnstile/v0/siteverify' , [
'secret' => config ( 'services.turnstile.secret_key' ),
'response' => $request -> input ( 'cf-turnstile-response' ),
'remoteip' => $request -> ip (),
]);
if ( ! $response -> json ( 'success' )) {
throw ValidationException :: withMessages ([
'cf-turnstile-response' => 'The Turnstile challenge failed. Please try again.' ,
]);
}
$user = User :: create ([
'name' => $request -> name ,
'email' => $request -> email ,
'password' => Hash :: make ( $request -> password ),
]);
event ( new Registered ( $user ));
Auth :: login ( $user );
// Initialize user's net worth
Auth :: user () -> netWorth () -> create ([
'net_worth' => 0 ,
]);
return redirect ( route ( 'dashboard' , absolute : false ));
}
Configure Turnstile
Set up your Cloudflare Turnstile keys in .env: TURNSTILE_SITE_KEY = your_site_key
TURNSTILE_SECRET_KEY = your_secret_key
Add to Services Config
The Turnstile configuration is automatically loaded from config/services.php: 'turnstile' => [
'site_key' => env ( 'TURNSTILE_SITE_KEY' ),
'secret_key' => env ( 'TURNSTILE_SECRET_KEY' ),
],
GitHub OAuth Integration
Cashify provides seamless GitHub OAuth authentication using Laravel Socialite.
Setup GitHub OAuth
Create GitHub OAuth App
Go to GitHub Developer Settings
Click “New OAuth App”
Fill in the application details:
Application name : Cashify
Homepage URL : https://yourdomain.com
Authorization callback URL : https://yourdomain.com/auth/github/callback
Click “Register application”
Copy your Client ID and generate a new Client Secret
Configure Environment Variables
Add your GitHub OAuth credentials to .env: GITHUB_CLIENT_ID = your_github_client_id
GITHUB_CLIENT_SECRET = your_github_client_secret
GITHUB_REDIRECT = https://yourdomain.com/auth/github/callback
Update Services Configuration
The GitHub configuration is automatically loaded from config/services.php: 'github' => [
'client_id' => env ( 'GITHUB_CLIENT_ID' ),
'client_secret' => env ( 'GITHUB_CLIENT_SECRET' ),
'redirect' => env ( 'GITHUB_REDIRECT' ),
],
Socialite Controller Implementation
The SocialiteSessionController handles OAuth authentication:
app/Http/Controllers/Auth/SocialiteSessionController.php
class SocialiteSessionController extends Controller
{
public function redirectToProvider ( $driver )
{
return Socialite :: driver ( $driver ) -> redirect ();
}
public function handleProviderCallback ( $driver )
{
try {
if ( ! $this -> requestHasCode ()) {
return $this -> handleFailedAuthentication (
'Authentication cancelled or failed. Please try again.'
);
}
$socialiteUser = Socialite :: driver ( $driver ) -> user ();
$user = $this -> findOrCreateUser ( $driver , $socialiteUser );
Auth :: login ( $user );
return redirect () -> intended ( route ( 'dashboard' , absolute : false ));
} catch ( Exception $e ) {
return $this -> handleFailedAuthentication (
'Authentication failed. Please try again.'
);
}
}
protected function findOrCreateUser ( $driver , $socialiteUser )
{
$user = User :: query ()
-> where ( 'provider' , $driver )
-> where ( 'provider_id' , $socialiteUser -> id )
-> first ();
if ( ! $user ) {
$user = $this -> createUser ( $driver , $socialiteUser );
}
return $user ;
}
protected function createUser ( $driver , $socialiteUser )
{
$user = User :: create ([
'provider' => $driver ,
'provider_id' => $socialiteUser -> id ,
'name' => $socialiteUser -> name ,
'email' => $socialiteUser -> email ,
]);
event ( new Registered ( $user ));
$user -> markEmailAsVerified ();
// Initialize user's net worth
$user -> netWorth () -> create ([
'net_worth' => 0 ,
]);
return $user ;
}
}
Users who register via OAuth have their email automatically verified and no password set (password field is null).
Frontend Integration
The login button for GitHub OAuth:
resources/views/components/buttons/socialite-buttons.blade.php
< a href = " {{ route ('socialite.redirect', 'github') }} " hx-boost = "false"
class = "flex items-center justify-center px-4 py-2.5 border border-black rounded-lg text-sm text-white dark:text-black bg-black dark:bg-white hover:bg-neutral-900 dark:hover:bg-neutral-200 transition-colors duration-200" >
< svg class = "w-6 h-6 mr-2" fill = "currentColor" viewBox = "0 0 24 24" >
< path fill-rule = "evenodd" d = "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule = "evenodd" />
</ svg >
Continue with GitHub
</ a >
Email Verification
Cashify implements Laravel’s email verification feature:
class User extends Authenticatable implements MustVerifyEmail
{
// Implementation
}
Apply Verification Middleware
Protect routes that require verified emails: Route :: middleware ([ 'auth' , 'verified' ]) -> group ( function () {
Route :: get ( '/dashboard' , [ DashboardController :: class , 'index' ])
-> name ( 'dashboard' );
});
Password Reset
Password reset functionality is built-in with Laravel Breeze:
User Requests Reset
User visits /forgot-password and enters their email address.
Email Sent
A password reset link is sent to the user’s email address.
Reset Password
User clicks the link and sets a new password at /reset-password/{token}.
Password reset tokens expire after 60 minutes (configurable in config/auth.php).
Session Management
Cashify uses database-backed sessions for security and scalability:
SESSION_DRIVER = database
SESSION_LIFETIME = 120
SESSION_ENCRYPT = false
To create the sessions table:
php artisan session:table
php artisan migrate
Security Features
CSRF Protection
All forms include CSRF tokens:
< form method = "POST" action = " {{ route ('login') }} " >
@csrf
<!-- Form fields -->
</ form >
Rate Limiting
Authentication endpoints are rate-limited:
Route :: middleware ( 'throttle:6,1' ) -> group ( function () {
// Email verification
Route :: get ( 'verify-email/{id}/{hash}' , VerifyEmailController :: class )
-> name ( 'verification.verify' );
});
Password Hashing
Passwords are automatically hashed using bcrypt:
protected function casts () : array
{
return [
'password' => 'hashed' ,
];
}
Configure bcrypt rounds in .env:
Adding Google OAuth (Optional)
Cashify includes support for Google OAuth, though it’s commented out by default:
Enable Google in Routes
Update the OAuth route constraint in routes/auth.php: Route :: get ( 'auth/{driver}/redirect' , [ SocialiteSessionController :: class , 'redirectToProvider' ])
-> where ( 'driver' , '(github|google)' ) // Already configured
-> name ( 'socialite.redirect' );
Configure Google Credentials
Add your Google OAuth credentials to .env: GOOGLE_CLIENT_ID = your_google_client_id
GOOGLE_CLIENT_SECRET = your_google_client_secret
GOOGLE_REDIRECT = https://yourdomain.com/auth/google/callback
Uncomment Frontend Button
Enable the Google login button in resources/views/components/buttons/socialite-buttons.blade.php.
Testing Authentication
# Test registration
php artisan test --filter=RegistrationTest
# Test login
php artisan test --filter=AuthenticationTest
# Test email verification
php artisan test --filter=EmailVerificationTest
Next Steps
Environment Variables Configure all authentication-related environment variables
Localization Set up multi-language authentication messages