Overview
MediaStream uses Laravel Fortify to provide a robust authentication system with modern security features. The platform includes user registration, login, password reset, email verification, and two-factor authentication (2FA).
User Registration Create new accounts with email verification
Secure Login Email and password authentication with rate limiting
Two-Factor Auth TOTP-based 2FA for enhanced security
Password Reset Secure password recovery via email
Authentication Features
Built on Laravel Fortify
MediaStream leverages Laravel Fortify for authentication, providing:
Login and Registration : Email/password authentication
Password Reset : Secure password recovery
Email Verification : Verify user email addresses
Two-Factor Authentication : TOTP-based 2FA
Rate Limiting : Protection against brute force attacks
Fortify Configuration
class FortifyServiceProvider extends ServiceProvider
{
public function boot () : void
{
$this -> configureActions ();
$this -> configureViews ();
$this -> configureRateLimiting ();
}
private function configureActions () : void
{
Fortify :: resetUserPasswordsUsing ( ResetUserPassword :: class );
Fortify :: createUsersUsing ( CreateNewUser :: class );
}
private function configureViews () : void
{
Fortify :: loginView ( fn ( Request $request ) => Inertia :: render ( 'auth/Login' , [
'canResetPassword' => Features :: enabled ( Features :: resetPasswords ()),
'canRegister' => Features :: enabled ( Features :: registration ()),
'status' => $request -> session () -> get ( 'status' ),
]));
Fortify :: registerView ( fn () => Inertia :: render ( 'auth/Register' ));
Fortify :: twoFactorChallengeView ( fn () => Inertia :: render ( 'auth/TwoFactorChallenge' ));
// ... other views
}
private function configureRateLimiting () : void
{
// Login rate limiting: 5 attempts per minute
RateLimiter :: for ( 'login' , function ( Request $request ) {
$throttleKey = Str :: transliterate (
Str :: lower ( $request -> input ( Fortify :: username ())) . '|' . $request -> ip ()
);
return Limit :: perMinute ( 5 ) -> by ( $throttleKey );
});
// 2FA rate limiting: 5 attempts per minute
RateLimiter :: for ( 'two-factor' , function ( Request $request ) {
return Limit :: perMinute ( 5 ) -> by ( $request -> session () -> get ( 'login.id' ));
});
}
}
Rate limiting protects your application from brute force attacks by limiting login attempts to 5 per minute per user.
User Registration
New users can create accounts through the registration page.
< template >
< AuthBase
title = "Create an account"
description = "Enter your details below to create your account" >
< Form v-bind = " store . form () "
: reset-on-success = " [ 'password' , 'password_confirmation' ] "
v-slot = " { errors , processing } "
class = "flex flex-col gap-6" >
< div class = "grid gap-6" >
<!-- Name Field -->
< div class = "grid gap-2" >
< Label for = "name" > Name </ Label >
< Input
id = "name"
type = "text"
required
autofocus
autocomplete = "name"
name = "name"
placeholder = "Full name" />
< InputError : message = " errors . name " />
</ div >
<!-- Email Field -->
< div class = "grid gap-2" >
< Label for = "email" > Email address </ Label >
< Input
id = "email"
type = "email"
required
autocomplete = "email"
name = "email"
placeholder = "[email protected] " />
< InputError : message = " errors . email " />
</ div >
<!-- Password Field -->
< div class = "grid gap-2" >
< Label for = "password" > Password </ Label >
< Input
id = "password"
type = "password"
required
autocomplete = "new-password"
name = "password"
placeholder = "Password" />
< InputError : message = " errors . password " />
</ div >
<!-- Confirm Password -->
< div class = "grid gap-2" >
< Label for = "password_confirmation" > Confirm password </ Label >
< Input
id = "password_confirmation"
type = "password"
required
autocomplete = "new-password"
name = "password_confirmation"
placeholder = "Confirm password" />
< InputError : message = " errors . password_confirmation " />
</ div >
< Button type = "submit" class = "mt-2 w-full" : disabled = " processing " >
< Spinner v-if = " processing " />
Create account
</ Button >
</ div >
< div class = "text-center text-sm text-muted-foreground" >
Already have an account?
< TextLink : href = " login () " > Log in </ TextLink >
</ div >
</ Form >
</ AuthBase >
</ template >
User Creation Validation
The backend validates all registration data:
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules ;
public function create ( array $input ) : User
{
Validator :: make ( $input , [
'name' => [ 'required' , 'string' , 'max:255' ],
'email' => [
'required' ,
'string' ,
'email' ,
'max:255' ,
Rule :: unique ( User :: class ),
],
'password' => $this -> passwordRules (),
]) -> validate ();
return User :: create ([
'name' => $input [ 'name' ],
'email' => $input [ 'email' ],
'password' => $input [ 'password' ],
]);
}
}
Passwords are automatically hashed using bcrypt before being stored in the database.
User Login
The login page provides a clean, secure interface for users to access their accounts.
< template >
< AuthBase
title = "Log in to your account"
description = "Enter your email and password below to log in" >
< div v-if = " status " class = "mb-4 text-center text-sm font-medium text-green-600" >
{{ status }}
</ div >
< Form v-bind = " store . form () "
: reset-on-success = " [ 'password' ] "
v-slot = " { errors , processing } "
class = "flex flex-col gap-6" >
< div class = "grid gap-6" >
<!-- Email Field -->
< div class = "grid gap-2" >
< Label for = "email" > Email address </ Label >
< Input
id = "email"
type = "email"
name = "email"
required
autofocus
autocomplete = "email"
placeholder = "[email protected] " />
< InputError : message = " errors . email " />
</ div >
<!-- Password Field -->
< div class = "grid gap-2" >
< div class = "flex items-center justify-between" >
< Label for = "password" > Password </ Label >
< TextLink v-if = " canResetPassword " : href = " request () " class = "text-sm" >
Forgot password?
</ TextLink >
</ div >
< Input
id = "password"
type = "password"
name = "password"
required
autocomplete = "current-password"
placeholder = "Password" />
< InputError : message = " errors . password " />
</ div >
<!-- Remember Me -->
< div class = "flex items-center justify-between" >
< Label for = "remember" class = "flex items-center space-x-3" >
< Checkbox id = "remember" name = "remember" />
< span > Remember me </ span >
</ Label >
</ div >
< Button type = "submit" class = "mt-4 w-full" : disabled = " processing " >
< Spinner v-if = " processing " />
Log in
</ Button >
</ div >
< div class = "text-center text-sm text-muted-foreground" v-if = " canRegister " >
Don't have an account?
< TextLink : href = " register () " > Sign up </ TextLink >
</ div >
</ Form >
</ AuthBase >
</ template >
Login Features
Remember Me Keep users logged in across browser sessions
Forgot Password Link to password reset flow
Auto-focus Email field automatically focused
Status Messages Display success/error messages
Two-Factor Authentication (2FA)
MediaStream includes comprehensive 2FA support using TOTP (Time-based One-Time Password) authentication.
Enabling 2FA
Users can enable 2FA from their settings page:
< template >
< div class = "space-y-6" >
< HeadingSmall
title = "Two-Factor Authentication"
description = "Manage your two-factor authentication settings" />
<!-- 2FA Disabled State -->
< div v-if = " ! twoFactorEnabled " class = "flex flex-col items-start justify-start space-y-4" >
< Badge variant = "destructive" > Disabled </ Badge >
< p class = "text-muted-foreground" >
When you enable two-factor authentication, you will be
prompted for a secure pin during login. This pin can be
retrieved from a TOTP-supported application on your phone.
</ p >
< div >
< Button v-if = " hasSetupData " @ click = " showSetupModal = true " >
< ShieldCheck /> Continue Setup
</ Button >
< Form v-else v-bind = " enable . form () "
@ success = " showSetupModal = true "
# default = " { processing } " >
< Button type = "submit" : disabled = " processing " >
< ShieldCheck /> Enable 2FA
</ Button >
</ Form >
</ div >
</ div >
<!-- 2FA Enabled State -->
< div v-else class = "flex flex-col items-start justify-start space-y-4" >
< Badge variant = "default" > Enabled </ Badge >
< p class = "text-muted-foreground" >
With two-factor authentication enabled, you will be
prompted for a secure, random pin during login, which
you can retrieve from the TOTP-supported application on
your phone.
</ p >
< TwoFactorRecoveryCodes />
< Form v-bind = " disable . form () " # default = " { processing } " >
< Button variant = "destructive" type = "submit" : disabled = " processing " >
< ShieldBan /> Disable 2FA
</ Button >
</ Form >
</ div >
< TwoFactorSetupModal
v-model : isOpen = " showSetupModal "
: requiresConfirmation = " requiresConfirmation "
: twoFactorEnabled = " twoFactorEnabled " />
</ div >
</ template >
2FA Setup Process
Enable 2FA
User clicks “Enable 2FA” button
QR Code Generation
System generates a QR code and secret key
Scan QR Code
User scans QR code with authenticator app (Google Authenticator, Authy, etc.)
Verify Code
User enters the 6-digit code from their app
Recovery Codes
System displays one-time recovery codes
Save Recovery Codes
User saves recovery codes in a secure location
2FA Enabled
Two-factor authentication is now active
2FA Controller
class TwoFactorAuthenticationController extends Controller implements HasMiddleware
{
public static function middleware () : array
{
return Features :: optionEnabled ( Features :: twoFactorAuthentication (), 'confirmPassword' )
? [ new Middleware ( 'password.confirm' , only : [ 'show' ])]
: [];
}
public function show ( TwoFactorAuthenticationRequest $request ) : Response
{
$request -> ensureStateIsValid ();
return Inertia :: render ( 'settings/TwoFactor' , [
'twoFactorEnabled' => $request -> user () -> hasEnabledTwoFactorAuthentication (),
'requiresConfirmation' => Features :: optionEnabled (
Features :: twoFactorAuthentication (),
'confirm'
),
]);
}
}
The 2FA settings page can optionally require password confirmation before allowing changes, adding an extra layer of security.
Recovery Codes
When 2FA is enabled, users receive recovery codes they can use if they lose access to their authenticator app:
< TwoFactorRecoveryCodes />
Recovery codes should be saved in a secure location. Each code can only be used once.
Password Reset
Users can securely reset their passwords through email verification.
Password Reset Flow
Request Reset
User clicks “Forgot password?” on login page
Enter Email
User enters their email address
Receive Email
User receives password reset email with link
Click Link
User clicks the link in the email
New Password
User enters and confirms new password
Password Updated
Password is updated, user can log in
Security Features
Rate Limiting 5 login attempts per minute to prevent brute force
Password Hashing Bcrypt hashing for all passwords
CSRF Protection Built-in CSRF token validation
Session Management Secure session handling with Laravel
Email Verification Verify user email addresses
2FA Support TOTP-based two-factor authentication
Authentication Layouts
MediaStream uses Inertia.js with Vue for seamless authentication pages.
Auth Layout Component
< AuthBase : title = " title " : description = " description " >
<slot /> <!-- Form content goes here -->
</ AuthBase >
The platform includes multiple layout options:
AuthCardLayout : Centered card design
AuthSimpleLayout : Minimalist layout
AuthSplitLayout : Split-screen design
Best Practices
Encourage users to create strong passwords:
Minimum 8 characters (configurable)
Mix of uppercase, lowercase, numbers, and symbols
Use password strength indicators
Prevent common passwords
Encourage 2FA usage:
Explain benefits clearly
Make setup process simple
Provide clear instructions
Show recovery code importance
Consider making 2FA mandatory for admin users
Manage sessions securely:
Set appropriate session timeouts
Implement “logout from all devices”
Clear sessions on password change
Use secure session storage
Balance security with usability:
Clear error messages
Helpful validation feedback
Remember me functionality
Password visibility toggle
Auto-focus form fields
Troubleshooting
If users can’t log in:
Verify email and password are correct
Check if account is verified
Try password reset if forgotten
Check for rate limiting (wait a few minutes)
Clear browser cookies/cache
Try a different browser
If 2FA isn’t working:
Verify time sync on phone is correct
Try entering the code again
Use recovery codes if available
Check authenticator app is working
Contact support to disable 2FA
If password reset email doesn’t arrive:
Check spam/junk folder
Verify email address is correct
Wait a few minutes for delivery
Try requesting again
Check email server logs
If hitting rate limits:
Wait 1 minute before trying again
Ensure correct credentials
Don’t use automated tools
Clear browser cache
Contact support if issue persists
Next Steps
Series Management Start managing your video content
API Reference Explore the authentication API