inertia start
Features

Authentication & Security

Secure, robust, and feature-rich authentication system.

Inertia Start includes a robust authentication system built on Laravel’s battle-tested authentication, with a tailored flow and carefully crafted interactions optimized for Inertia.js.

Try the sign-in flow

Walk through the login and registration screens in the live demo.

Features

Account Creation

Inertia Start adds an extra verification layer to the account creation process to prevent spam.

Upon receiving a registration request, the system does not immediately create a User entity. Instead, it creates a temporary Registration entity (automatically expiring after 15 minutes) to hold the request while the email is verified. The pending registration is non-blocking, meaning that multiple registration requests for the same email address can be made at the same time. The User entity is only created after the one-time validation code is entered.

This mechanism effectively mitigates spam and prevents malicious actors from locking up email addresses before validation.

Authentication Methods

  • Email & Password: Classic login with password reset functionality.
  • Magic Links: One-time, temporary secure links to log in without a password.
  • Passkeys: Passwordless login with a passkey saved on the user's device or password manager (when I_S_ENABLE_PASSKEYS is enabled).
  • External Providers: Log in or sign up with an existing account from Google, GitHub, or any other Laravel Socialite provider (see External auth providers).

Last used login method

The login page displays a Last used badge on the method the user last logged in with.

The method is remembered after every successful login, or after completing a registration: with a password, a magic link, a passkey, or an external provider.

It is stored in a first-party cookie that only contains the method identifier: password, magic_link, passkey, or the driver name of an external provider (for example google). Unknown values and providers that are no longer enabled are ignored.

The cookie name and lifetime (one year by default) can be changed in config/inertia-start.php:

config/inertia-start.php
'last_login_method_cookie' => [
    'name' => 'last_login_method',
    'minutes' => 60 * 24 * 365,
],

Security

  • Email Verification: Enforce email verification at account creation and when changing email addresses.
  • Two-Factor Authentication (2FA) (built on Laragear TwoFactor): Users can enable 2FA using TOTP apps (Google Authenticator, Authy, etc.) to further protect their account.
  • New Login Alerts: Users receive an email after a new login by default and can control it from their notification preferences.
  • Rate Limited Requests: Sensitive actions are protected against brute-force attacks.
  • Activity Logs: Important actions are logged, and suspicious activity is monitored. Super admins receive email notifications when rate-limited requests are abused.

Rate limiting / Request throttling

Sensitive actions are rate-limited. Below is the default configuration:

ActionConfiguration
Login5 attempts / 1 minute (per same IP)
10 attempts / 5 minutes (per same email account)
Registration4 attempts / 5 minutes (per same IP)
4 attempts / 1 hour (per same email)
Resend Registration Code3 attempts / 15 minutes
Password Reset Request4 attempts / 5 minutes (per same IP)
4 attempts / 1 hour (per same email account)
Request Email Modification2 attempts / 12 hours
Resend Email Modification Code3 attempts / 1 hour

To customize these limits, search for Helpers::throttle calls within the application codebase.

Configuration

To enable user accounts, use the I_S_ENABLE_ACCOUNTS environment variable:

.env
I_S_ENABLE_ACCOUNTS=true

Authentication settings can be configured in config/auth.php (more information in the Laravel Documentation).

Two-factor authentication configuration is located in config/two-factor.php (more information here).

External auth providers

External authentication is powered by Laravel Socialite. Enable providers by adding their Socialite driver names to I_S_AUTH_PROVIDERS as a comma-separated list (for example google,github). Only enabled providers are displayed on the login and registration pages, and the routes of any other provider return a 404 response.

Only enable providers that verify email addresses

When a provider returns an email address that already belongs to an account, Inertia Start links the provider account to that user and logs them in. Email addresses flagged as unverified by the provider are refused (using the email_verified value returned by the google, linkedin-openid and slack-openid drivers), and the github, bitbucket and x drivers only return verified addresses. Other drivers, such as facebook, gitlab, twitch, or community providers, return email addresses without a verification flag: only enable them if you trust the provider to verify email addresses, otherwise someone could access an existing account by using its email address with the provider.

Google

For Google, configure the following environment variables:

.env
I_S_AUTH_PROVIDERS=google
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=

In your Google OAuth client, add {APP_URL}/auth/provider/google/callback as an authorized redirect URI, replacing {APP_URL} with the public URL configured for your application. For example:

https://example.com/auth/provider/google/callback

Google authentication uses the openid, email, and profile scopes. Socialite's Google driver requests these scopes by default, so no custom scope configuration is required. See Google's OpenID Connect documentation for details.

Other providers

To enable additional providers, add each provider to I_S_AUTH_PROVIDERS and configure its credentials in config/services.php, using the same callback URL pattern ({APP_URL}/auth/provider/{provider}/callback). For example, for GitHub:

.env
I_S_AUTH_PROVIDERS=google,github
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
config/services.php
'github' => [
    'client_id' => env('GITHUB_CLIENT_ID'),
    'client_secret' => env('GITHUB_CLIENT_SECRET'),
    'redirect' => rtrim((string) env('APP_URL', 'http://localhost'), '/').'/auth/provider/github/callback',
],

Every provider listed in I_S_AUTH_PROVIDERS is displayed, even when its credentials are missing. Configure a provider in config/services.php before adding it to the list.

Refer to the Socialite configuration documentation for the supported first-party providers and configuration structure. Community-maintained drivers are available from Socialite Providers: install the provider package and register its event listener as described in its documentation, then add its driver name to I_S_AUTH_PROVIDERS.

Button labels and icons

Provider buttons are rendered by resources/js/components/OAuthProviderButton.vue:

  • Label: the provider name is translated from the oauth_providers key in lang/{locale}/messages.php (Google and GitHub are included). When no translation exists, the driver name is converted to a headline (for example x becomes X).
  • Icon: Google and GitHub icons are included. Other providers display a generic login icon until you add their SVG to the component.

Authentication flow

  • Existing accounts: the user is found from a previously linked provider account, or else from the email address returned by the provider. Provider accounts are linked on first use and stored in the oauth_accounts table (App\Models\OAuthAccount model, available through the oauthAccounts() relationship on the User model). A user can link one account per provider, and a provider account can only be linked to a single user.
  • New accounts: when no account matches, a new user is created with the name and email address returned by the provider. The email address is marked as verified and the account has no password: the user can create one later from their account settings, or log in with magic links. The account creation is recorded in the activity logs and the provider's driver name is stored as the registered_via value of the analytics context.
  • Registration disabled: when I_S_ENABLE_ACCOUNTS is false, existing users can still log in with a provider, but no new account is created.
  • Terms acceptance: when I_S_ACCOUNT_MUST_ACCEPT_TERMS is true, new users accept the terms after returning from the provider, whether they started from the login or the registration page. They are shown a registration step displaying their provider email address as read-only, and their account is only created once they accept the terms.
  • Two-factor authentication: users who enabled 2FA must enter a code from their authentication app after returning from the provider, before being logged in.
  • Unverified email addresses: when the provider flags the email address as unverified, no account is linked or created, and the user is redirected to the login page with a message asking them to verify their email address with the provider. Users whose account is already linked to the provider can still log in, because they are matched by their provider user identifier.
  • Errors: if the provider authentication fails, or if the provider does not return a user identifier and a valid email address, the user is redirected to the login page with an error message.

The following routes are registered for external authentication:

RouteDescription
GET /auth/provider/{provider}/redirectRedirect to the provider to log in.
GET /auth/provider/{provider}/callbackHandle the provider callback.
GET / POST /auth/provider/{provider}/challengeTwo-factor authentication challenge.
POST /signup/provider/{provider}/redirectRedirect to the provider from the registration page.
GET / POST /signup/provider/{provider}Terms acceptance step for new accounts.

On this page