Skip to main content

Auto-Registration

Overview

The Auto-Registration feature enables automatic account creation for users from pre-approved email domains. Instead of requiring manual user invitation or admin approval, eligible users can self-register by verifying their email address through a secure, signed link. This is particularly useful for:
  • Allowing employees from your company domain to self-register
  • Opening registration to partner organization domains
  • Providing controlled public access based on email domain

Key Features

  • Domain-based eligibility: Only emails from configured domains can register
  • Role assignment: Automatically assign roles based on email domain
  • Email verification: Secure, time-limited signed URLs (24-hour expiration)
  • Session protection: Prevents email hijacking during registration
  • Duplicate prevention: Blocks registration if user already exists

Configuration

Adding Allowed Domains

Configure auto-registration domains in config/auth.php:
'auto_registration_domains' => [
    'example.com' => App\Enums\Role::USER->value,
    'partner.com' => App\Enums\Role::CLIENT->value,
    'agency.com' => App\Enums\Role::ADMIN->value,
],
Configuration structure:
  • Key: Email domain (e.g., 'example.com')
  • Value: Role to assign (e.g., App\Enums\Role::USER->value)

Environment-Specific Configuration

For environment-specific domains, you can use .env variables:
// config/auth.php
'auto_registration_domains' => [
    env('AUTO_REG_DOMAIN_1') => App\Enums\Role::USER->value,
    // Or build dynamically:
    ...collect(explode(',', env('AUTO_REG_DOMAINS', '')))
        ->filter()
        ->mapWithKeys(fn($domain) => [$domain => App\Enums\Role::USER->value])
        ->toArray(),
],
# .env
AUTO_REG_DOMAIN_1=example.com
AUTO_REG_DOMAINS=partner1.com,partner2.com,partner3.com

User Flow

1. Initial Request

User attempts to login with an email that doesn’t exist:
POST /login/{method}/init
Body: { email: "[email protected]" }
If the domain is eligible, instead of showing an error, the system triggers the auto-registration flow.

2. Pending State

The user is redirected to: They see a “Check your email” message explaining that a verification link has been sent.

3. Email Verification

The user receives an email with a signed URL that expires in 24 hours:
GET /register/[email protected]&expires=1234567890&signature=abc123...
The signed URL ensures:
  • The link cannot be tampered with
  • The link expires after 24 hours
  • Only the intended recipient can use it

4. Registration Form

When clicking the link, the user sees a registration form pre-filled with their email, where they can enter:
  • First name
  • Last name

5. Account Creation

Upon form submission:
  • User account is created
  • Role is automatically assigned based on domain configuration
  • User is logged in immediately
  • Redirected to the dashboard

API Reference

AutoRegistration Service

The Inly\Core\Services\AutoRegistration\AutoRegistration service provides the following methods:

isEligible(?string $email): bool

Check if an email is eligible for auto-registration.
use Inly\Core\Services\AutoRegistration\AutoRegistration;

$autoReg = app(AutoRegistration::class);

if ($autoReg->isEligible('[email protected]')) {
    // Email is eligible
}
Returns: true if email is eligible and user doesn’t already exist

getState(?string $email): ?array

Get auto-registration state for an email address.
$state = $autoReg->getState('[email protected]');

// Returns:
// [
//     'domain' => 'example.com',
//     'role' => 'user'
// ]
// or null if not eligible
Returns: Array with domain and role, or null if not eligible

invite(string $email): void

Send an auto-registration invitation email.
$autoReg->invite('[email protected]');
Throws: InvalidArgumentException if email is not eligible

userExists(string $email): bool

Check if a user already exists with the given email (case-insensitive).
if ($autoReg->userExists('[email protected]')) {
    // User already exists
}

Routes

The following routes are available in routes/guest.php:
MethodURINameController Method
GET/registerauto-registration.pendingshow()
GET/register/createauto-registration.createcreate()
POST/register/createauto-registration.storestore()

Security Features

1. Signed URLs

Registration links use Laravel’s signed URLs with:
  • 24-hour expiration
  • Cryptographic signatures
  • Tamper detection

2. Session-Based Email Storage

The email is stored in the session during the create() step, not passed as a form input. This prevents attackers from:
  • Modifying the email during form submission
  • Creating accounts for arbitrary email addresses

3. Domain Whitelist

Only explicitly configured domains in config/auth.php can register. There’s no wildcard or “open registration” mode.

4. Duplicate Prevention

The system checks for existing users (case-insensitive) before allowing registration at multiple points in the flow.

5. CSRF Protection

All POST requests are protected by Laravel’s CSRF middleware.

Integration Points

Triggering Auto-Registration from Login

When a user attempts to login with a non-existent email, check eligibility and redirect:
use Inly\Core\Services\AutoRegistration\AutoRegistration;

public function init(Request $request)
{
    $email = $request->input('email');
    $autoReg = app(AutoRegistration::class);
    
    if ($autoReg->isEligible($email)) {
        // Send invitation email
        $autoReg->invite($email);
        
        // Redirect to pending page
        return redirect()->route('auto-registration.pending', ['email' => $email]);
    }
    
    // Handle normal login flow
}

Custom Registration Workflows

You can extend the auto-registration flow by listening to events or adding middleware:
// app/Providers/AppServiceProvider.php
use Illuminate\Support\Facades\Event;
use Illuminate\Auth\Events\Registered;

Event::listen(Registered::class, function ($event) {
    // Custom logic after auto-registration
    // e.g., send welcome email, create workspace, etc.
});

Frontend Components

The auto-registration flow uses the following Inertia pages:
  • auth/auto-registration-pending: Shows “check your email” message
  • auth/auto-registration: Shows registration form
These should be created in your resources/js/Pages/ directory.

Validation Rules

The registration form validates:
FieldRules
first_namerequired, string, max:255
last_namerequired, string, max:255
Email is not validated in the form as it’s stored in the session and verified earlier in the flow.

Localization

All user-facing messages support localization. Key translation strings include:
  • "Auto-registration is not allowed."
  • "This registration link has expired or is invalid."
  • "Please sign in instead"
  • "Check your email"
  • "Create account"
  • "Your email is eligible for public registration."
  • "Registration for :app"

Troubleshooting

”Auto-registration is not allowed” Error

Cause: The email domain is not configured in config/auth.php Solution: Add the domain to auto_registration_domains:
'auto_registration_domains' => [
    'newdomain.com' => App\Enums\Role::USER->value,
],
Cause: The signed URL has expired (>24 hours old) or signature is invalid Solution: Request a new registration link

User Already Exists Error

Cause: A user with that email already exists in the system Solution: User should use the login flow instead

Email Not Sending

Cause: Mail configuration issue Solution:
  1. Check config/mail.php settings
  2. Verify environment variables (MAIL_MAILER, MAIL_HOST, etc.)
  3. Test with php artisan tinker:
    app(\Inly\Core\Services\AutoRegistration\AutoRegistration::class)
        ->invite('[email protected]');
    

Best Practices

  1. Use role enums: Always use App\Enums\Role values for role assignment
  2. Monitor registrations: Log auto-registrations for security auditing
  3. Set appropriate roles: Don’t give admin roles via auto-registration
  4. Document allowed domains: Maintain documentation of why each domain is allowed
  5. Regular review: Periodically review and clean up auto_registration_domains configuration
  6. Test thoroughly: Test the full flow when adding new domains

Example: Complete Integration

Here’s a complete example of integrating auto-registration into a custom authentication flow:
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Inly\Core\Services\AutoRegistration\AutoRegistration;

class CustomAuthController extends Controller
{
    public function handleLogin(Request $request)
    {
        $email = $request->validate(['email' => 'required|email'])['email'];
        
        // Check if user exists
        if (! User::where('email', $email)->exists()) {
            $autoReg = app(AutoRegistration::class);
            
            // Check auto-registration eligibility
            if ($autoReg->isEligible($email)) {
                // Send invite email
                $autoReg->invite($email);
                
                // Show pending page
                return redirect()
                    ->route('auto-registration.pending', ['email' => $email])
                    ->with('info', __('Check your email to complete registration'));
            }
            
            // Email not found and not eligible
            return back()->withErrors([
                'email' => __('No account found with this email address'),
            ]);
        }
        
        // Continue with normal authentication flow
        // ...
    }
}

See Also