> ## Documentation Index
> Fetch the complete documentation index at: https://docs-dev-docs-event-stream-action-templates.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Add Login to Your Laravel Application

> This guide demonstrates how to integrate Auth0 with a new or existing Laravel application using the Auth0 Laravel SDK.

export const QuickstartButtons = ({githubLink, lang = "en"}) => {
  const translations = {
    en: {
      viewOnGithub: "View On GitHub",
      loginAndDownload: "Download Sample"
    },
    "fr-ca": {
      viewOnGithub: "Afficher sur GitHub",
      loginAndDownload: "Télécharger un exemple"
    },
    "ja-jp": {
      viewOnGithub: "Githubで表示",
      loginAndDownload: "サンプルをダウンロード"
    }
  };
  const text = translations[lang] || translations.en;
  const parseGithubUrl = url => {
    try {
      const urlObj = new URL(url);
      const pathParts = urlObj.pathname.split("/").filter(Boolean);
      if (pathParts.length >= 4 && pathParts[2] === "tree") {
        const repoName = pathParts[1];
        const branch = pathParts[3];
        const path = pathParts.slice(4).join("/") || undefined;
        return {
          repo: repoName,
          branch,
          path
        };
      }
      console.warn("Could not parse GitHub URL:", url);
      return null;
    } catch (error) {
      console.error("Error parsing GitHub URL:", error);
      return null;
    }
  };
  const handleDownload = async () => {
    const params = parseGithubUrl(githubLink);
    if (!params) {
      console.error("Invalid GitHub URL format");
      return;
    }
    try {
      await window.Auth0DocsUI?.getSample(params);
    } catch (error) {
      console.error("Failed to download sample:", error);
    }
  };
  return <div className="quickstart_buttons flex flex-wrap gap-3 mb-4">
      <a href={githubLink} target="_blank" rel="noopener noreferrer" className="no_external_icon quickstart_button inline-flex items-center justify-center px-6 py-3 text-sm font-medium rounded-[18px] bg-black dark:bg-white !text-white dark:!text-black hover:bg-gray-800 dark:hover:bg-gray-100 transition-colors">
        {text.viewOnGithub}
      </a>
      <button onClick={handleDownload} type="button" className="no_external_icon quickstart_button inline-flex items-center justify-center px-6 py-3 text-sm font-medium rounded-[18px] border border-gray-300 dark:border-[#454545] bg-white dark:bg-[#272728] !text-black dark:!text-white hover:bg-gray-50 dark:hover:bg-neutral-800 transition-colors">
        {text.loginAndDownload}
      </button>
    </div>;
};

export const CreateInteractiveApp = ({placeholderText = 'Auth0', appType = 'regular_web', allowedCallbackUrls = ['localhost:3000'], allowedLogoutUrls = ['localhost:3000'], allowedOriginUrls = ['localhost:3000']}) => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [storeReady, setStoreReady] = useState(false);
  const [displayForm, setDisplayForm] = useState(true);
  useEffect(() => {
    const init = () => setStoreReady(true);
    if (window.rootStore) {
      window.rootStore.clientStore.setSelectedClient(null);
      window.rootStore.clientStore.setSelectedClientSecret(undefined);
      init();
    } else {
      window.addEventListener('adu:storeReady', init);
    }
    return () => {
      window.removeEventListener('adu:storeReady', init);
    };
  }, []);
  useEffect(() => {
    if (!storeReady) return;
    const disposer = autorun(() => {
      const rootStore = window.rootStore;
      setIsAuthenticated(rootStore.sessionStore.isAuthenticated);
    });
    return () => {
      disposer();
    };
  }, [storeReady]);
  if (!storeReady || typeof window === 'undefined' || !displayForm) {
    return <></>;
  }
  const login = () => {
    const baseUrl = window.rootStore.config.apiBaseUrl;
    const returnTo = encodeURIComponent(window.location.href);
    window.location.href = `${baseUrl}/auth/user/login?returnTo=${returnTo}`;
  };
  const Card = ({className = '', children}) => {
    return <div className={`
          flex border rounded-2xl
          border-gray-950/10 dark:border-white/10
          py-3.5 px-4 gap-2
          text-sm text-gray-900 dark:text-gray-200
          ${className}
        `}>
        {children}
      </div>;
  };
  const Button = ({children, ...props}) => {
    return <button className="bg-[--button-primary] text-[--foreground-inverse] px-[1.125rem] py-1.5 rounded-lg font-medium" {...props}>
        {children}
      </button>;
  };
  const CreateApplicationForm = () => {
    const [name, setName] = useState('');
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState('');
    const handleSubmit = async () => {
      if (!name.trim()) {
        setError('Application name is required');
        return;
      }
      setIsLoading(true);
      setError(null);
      try {
        await window.rootStore.clientStore.createClient({
          name: name.trim(),
          app_type: appType,
          callbacks: allowedCallbackUrls,
          allowed_logout_urls: allowedLogoutUrls,
          web_origins: allowedOriginUrls,
          client_metadata: {
            created_by: 'quickstart-docs-app-creation-component'
          }
        });
        setDisplayForm(false);
      } catch (err) {
        console.error('Error creating client:', err);
        const errorMessage = err instanceof Error ? err.message : 'Failed to create application';
        setError(errorMessage);
      } finally {
        setIsLoading(false);
      }
    };
    return <Card className="flex-col items-start p-4 gap-3.75">
        <span className="font-medium text-gray-900 dark:text-gray-200">
          Create Auth0 App
        </span>
        <div className="w-full flex gap-2">
          <input id="app-name" name={name} className="
              w-full max-w-[448px] h-11 py-2 px-4 
              border rounded-lg border-gray-950/10 dark:border-white/10 
              text-gray-900 dark:text-gray-200
              focus:outline-none dark:focus:outline-none
            " placeholder={`My ${placeholderText} App`} value={name} onChange={e => setName(e.target.value)} />
          <Button onClick={handleSubmit}>
            {isLoading ? 'Creating...' : 'Create'}
          </Button>
        </div>
        {error && <p className="text-red-500">{error}</p>}
      </Card>;
  };
  const SignInForm = () => {
    return <Card className="items-center">
        <Button onClick={login}>Log in</Button> <span>to create the app</span>
      </Card>;
  };
  return isAuthenticated ? <CreateApplicationForm /> : <SignInForm />;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

<QuickstartButtons githubLink="https://github.com/auth0-samples/laravel/tree/7.x/sample" />

export const envSnippet = `AUTH0_DOMAIN={yourDomain}
AUTH0_CLIENT_ID={yourClientId}
AUTH0_CLIENT_SECRET={yourClientSecret}`;

<Accordion title="Use AI to integrate Auth0" icon="microchip-ai" iconType="solid" defaultOpen>
  If you use an AI coding assistant like Claude Code, Cursor, or GitHub Copilot, you can add Auth0 authentication automatically in minutes using [agent skills](https://agentskills.io/home).

  **Install:**

  ```bash theme={null}
  npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-laravel
  ```

  **Then ask your AI assistant:**

  ```text theme={null}
  Add Auth0 authentication to my Laravel app
  ```

  Your AI assistant will automatically create your Auth0 application, fetch credentials, install `auth0/login`, configure environment variables, and register authentication routes. [Full agent skills documentation →](/docs/quickstart/agent-skills)
</Accordion>

<Note>
  **Prerequisites:** Before you begin, ensure you have the following installed:

  * **[PHP](https://www.php.net/downloads.php)** 8.2 or newer
  * **[Composer](https://getcomposer.org/download/)** 2.x
  * **[Laravel](https://laravel.com/docs/installation)** 11, 12, or 13

  Verify installation: `php --version && composer --version`
</Note>

## Get Started

This quickstart demonstrates how to add Auth0 authentication to a Laravel application. You'll configure secure login, logout, protected routes, and user profile access using the [Auth0 Laravel SDK](https://github.com/auth0/laravel-auth0).

<Steps>
  <Step title="Create a new Laravel project" stepNumber={1}>
    If you already have a Laravel application, skip to Step 2.

    Create a new Laravel project:

    ```bash theme={null}
    composer create-project laravel/laravel auth0-laravel-app
    ```

    Open the project directory:

    ```bash theme={null}
    cd auth0-laravel-app
    ```
  </Step>

  <Step title="Install the Auth0 Laravel SDK" stepNumber={2}>
    Run the following command in your project directory to install the [Auth0 Laravel SDK](https://github.com/auth0/laravel-auth0):

    ```bash theme={null}
    composer require auth0/login:^7 --update-with-all-dependencies
    ```

    Then publish the SDK configuration file:

    ```bash theme={null}
    php artisan vendor:publish --tag auth0
    ```
  </Step>

  <Step title="Configure Auth0 credentials" stepNumber={3}>
    You need to create an Auth0 application and add your credentials to the project. Choose one of the following methods:

    <Tabs>
      <Tab title="Quick Setup (recommended)">
        Create an Auth0 App and copy the pre-filled `.env` credentials with the right configuration values.

        <CreateInteractiveApp placeholderText="Laravel" appType="regular_web" allowedCallbackUrls={["http://localhost:8000/callback"]} allowedLogoutUrls={["http://localhost:8000"]} />

        Add these values to your project's `.env` file:

        <AuthCodeBlock children={envSnippet} language="shellscript" filename=".env" />
      </Tab>

      <Tab title="CLI">
        Run the following command in your project's root directory to create an Auth0 app and generate a `.env` file:

        <CodeGroup>
          ```bash Mac theme={null}
          # Install Auth0 CLI (if not already installed)
          brew tap auth0/auth0-cli && brew install auth0

          # Set up Auth0 app and generate .env file
          auth0 qs setup --app --type regular --framework laravel --build-tool composer --name "My Laravel App" --port 8000
          ```

          ```powershell Windows theme={null}
          # Install Auth0 CLI (if not already installed)
          scoop bucket add auth0 https://github.com/auth0/scoop-auth0-cli.git
          scoop install auth0

          # Set up Auth0 app and generate .env file
          auth0 qs setup --app --type regular --framework laravel --build-tool composer --name "My Laravel App" --port 8000
          ```
        </CodeGroup>

        <Note>
          This command will:

          1. Check if you're authenticated (and prompt for login if needed)
          2. Create an Auth0 Regular Web Application configured for `http://localhost:8000`
          3. Generate a `.env` file with your Auth0 credentials
        </Note>
      </Tab>

      <Tab title="Dashboard">
        1. Go to the [Auth0 Dashboard](https://manage.auth0.com/) → **Applications > Applications**
        2. Click **Create Application**, enter a name, select **Regular Web Application**, and click **Create**
        3. Go to the **Settings** tab and copy the **Domain**, **Client ID**, and **Client Secret**

        Configure the following URLs in the **Settings** tab of your application:

        | Field                 | Value                            |
        | --------------------- | -------------------------------- |
        | Allowed Callback URLs | `http://localhost:8000/callback` |
        | Allowed Logout URLs   | `http://localhost:8000`          |

        Click **Save Changes**.

        Then add your credentials to your project's `.env` file:

        ```bash .env theme={null}
        AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
        AUTH0_CLIENT_ID=YOUR_AUTH0_CLIENT_ID
        AUTH0_CLIENT_SECRET=YOUR_AUTH0_CLIENT_SECRET
        ```

        <Warning>
          Never commit your `AUTH0_CLIENT_SECRET` to version control. Keep it in `.env` and ensure `.env` is in your `.gitignore`.
        </Warning>
      </Tab>
    </Tabs>
  </Step>

  <Step title="Add authentication routes" stepNumber={4}>
    The Auth0 SDK automatically registers the following routes for your application — no additional route configuration is required:

    | Route       | Purpose                                   |
    | ----------- | ----------------------------------------- |
    | `/login`    | Initiates the Auth0 login flow            |
    | `/logout`   | Logs out the user and redirects to Auth0  |
    | `/callback` | Handles the Auth0 authentication callback |

    <Note>
      If your application uses Laravel Breeze, Fortify, or Jetstream, the SDK's `/login`, `/logout`, and `/callback` routes may conflict with routes registered by those packages. See the [SDK README](https://github.com/auth0/laravel-auth0) for instructions on manual route registration.
    </Note>

    Update `routes/web.php` to add your home route:

    ```php routes/web.php lines theme={null}
    <?php

    use Illuminate\Support\Facades\Route;

    Route::get('/', function () {
        if (! auth()->check()) {
            return response('You are not logged in. <a href="/login">Log in</a>');
        }

        $user = auth()->user();
        $name = $user->name ?? 'User';
        $email = $user->email ?? '';

        return response("Hello {$name}! Your email address is {$email}.");
    });
    ```
  </Step>

  <Step title="Protect routes with middleware" stepNumber={5}>
    Use Laravel's `auth` middleware to require authentication on any route. You can also enforce specific [permissions](https://auth0.com/docs/manage-users/access-control/rbac) using the `can` middleware:

    ```php routes/web.php lines theme={null}
    <?php

    use Illuminate\Support\Facades\Route;

    // Requires any authenticated user
    Route::get('/private', function () {
        return response('Welcome! You are logged in.');
    })->middleware('auth');

    // Requires authentication AND the 'read:messages' permission
    Route::get('/scope', function () {
        return response('You have the read:messages permission.');
    })->middleware('auth')->can('read:messages');
    ```

    <Info>
      Permissions are defined in your Auth0 API settings and assigned to users via roles. See [Role-Based Access Control](https://auth0.com/docs/manage-users/access-control/rbac) for details.
    </Info>
  </Step>

  <Step title="Run your application" stepNumber={6}>
    ```bash theme={null}
    php artisan serve
    ```

    <Info>
      Your application runs at [http://localhost:8000](http://localhost:8000). If port 8000 is already in use, run `php artisan serve --port=8001` and update your Auth0 application's **Allowed Callback URLs** and **Allowed Logout URLs** to use the new port.
    </Info>
  </Step>
</Steps>

<Check>
  **Checkpoint**

  Open [http://localhost:8000](http://localhost:8000) in your browser. Try these routes to verify your integration:

  * [http://localhost:8000/login](http://localhost:8000/login) — triggers the Auth0 login flow
  * [http://localhost:8000/private](http://localhost:8000/private) — redirects to login if unauthenticated; shows a welcome message when logged in
  * [http://localhost:8000/logout](http://localhost:8000/logout) — logs out and returns to the home page
</Check>

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Callback URL mismatch error">
    **Cause:** The callback URL sent to Auth0 doesn't match any URL in your application's **Allowed Callback URLs** list.

    **Fix:**

    1. Go to the [Auth0 Dashboard](https://manage.auth0.com/) → **Applications > Applications** → your app → **Settings**
    2. Add `http://localhost:8000/callback` to **Allowed Callback URLs**
    3. Click **Save Changes**

    Ensure there are no trailing slashes and that the port matches your running server.
  </Accordion>

  <Accordion title="Invalid state / CSRF error after login">
    **Cause:** Session or cookie misconfiguration — the Laravel session isn't persisting state between the login redirect and callback.

    **Fix:**

    1. Ensure your `SESSION_DRIVER` in `.env` is set to `file`, `database`, or `redis` (not `array`)
    2. Clear the config and cache:

    ```bash theme={null}
    php artisan config:clear && php artisan cache:clear
    ```

    3. Restart your development server
  </Accordion>

  <Accordion title="AUTH0_DOMAIN not set or credentials not loading">
    **Cause:** The SDK cannot find your Auth0 credentials.

    **Fix:** Ensure one of the following exists in your project root:

    * A `.env` file with `AUTH0_DOMAIN`, `AUTH0_CLIENT_ID`, and `AUTH0_CLIENT_SECRET`
    * A `.auth0.app.json` file generated by the Auth0 CLI

    After updating `.env`, clear the config cache:

    ```bash theme={null}
    php artisan config:clear
    ```
  </Accordion>

  <Accordion title="404 on /login, /logout, or /callback">
    **Cause:** The SDK's routes aren't registered, usually because the service provider didn't load.

    **Fix:**

    1. Confirm you ran `php artisan vendor:publish --tag auth0`
    2. Verify package auto-discovery is enabled (check `composer.json` for `"dont-discover": []`)
    3. Run `php artisan route:list | grep auth0` to confirm the routes are registered
    4. If routes are missing, manually register the service provider. In Laravel 11+, add it to `bootstrap/providers.php`:

    ```php bootstrap/providers.php theme={null}
    return [
        App\Providers\AppServiceProvider::class,
        Auth0\Laravel\Auth0ServiceProvider::class,
    ];
    ```
  </Accordion>
</AccordionGroup>

***

## Advanced Usage

<AccordionGroup>
  <Accordion title="Management API — update user metadata">
    You can update user information using the [Auth0 Management API](https://github.com/auth0/laravel-auth0/blob/main/docs/Management.md). All Management API endpoints are accessible via the SDK's `Auth0::management()` method.

    **Before making Management API calls**, authorize your application to access the Management API:

    1. Go to the [Auth0 Dashboard](https://manage.auth0.com/) → **Applications > APIs** → **Auth0 Management API**
    2. Select the **Machine to Machine Applications** tab
    3. Authorize your Laravel application and grant the `read:users` and `update:users` scopes

    ```php routes/web.php lines theme={null}
    <?php

    use Auth0\Laravel\Facade\Auth0;
    use Illuminate\Support\Facades\Route;

    Route::get('/colors', function () {
        $colors = ['red', 'blue', 'green', 'black', 'white', 'yellow', 'purple', 'orange'];

        $users = Auth0::management()->users();

        // Update the authenticated user's metadata with a random favorite color
        $users->update(
            id: auth()->id(),
            body: [
                'user_metadata' => [
                    'color' => $colors[random_int(0, count($colors) - 1)],
                ],
            ]
        );

        // Retrieve and display the updated metadata
        $metadata = Auth0::json($users->get(auth()->id()));
        $color = $metadata['user_metadata']['color'] ?? 'unknown';
        $name = auth()->user()->name;

        return response("Hello {$name}! Your favorite color is {$color}.");
    })->middleware('auth');
    ```

    A full reference of all Management API methods is available in the [SDK documentation](https://github.com/auth0/laravel-auth0/blob/main/docs/Management.md).
  </Accordion>

  <Accordion title="Custom user models and repositories">
    The SDK supports custom user models and repositories, letting you store and retrieve users from your own database while keeping Auth0 as the identity provider.

    See [User Repositories and Models](https://github.com/auth0/laravel-auth0/blob/main/docs/Users.md) for the full implementation guide.
  </Accordion>

  <Accordion title="Listening to SDK events">
    The SDK raises events at key points in the authentication lifecycle — on login, logout, token refresh, and more — allowing you to fully customize behavior without modifying core SDK code.

    See [Hooking Events](https://github.com/auth0/laravel-auth0/blob/main/docs/Events.md) for a full list of events and implementation examples.
  </Accordion>

  <Accordion title="Role-Based Access Control (RBAC)">
    Use Auth0 RBAC to assign permissions to users via roles, then enforce them in Laravel using the `can` middleware:

    ```php routes/web.php theme={null}
    <?php

    use Illuminate\Support\Facades\Route;

    Route::get('/admin', function () {
        return response('Admin area.');
    })->middleware('auth')->can('admin:dashboard');
    ```

    To set up RBAC:

    1. Go to the [Auth0 Dashboard](https://manage.auth0.com/) → **Applications > APIs** → your API → **Permissions**
    2. Add the permissions your application needs (e.g., `admin:dashboard`, `read:messages`)
    3. Go to **User Management > Roles**, create a role, and assign permissions to it
    4. Assign the role to users from their profile page

    See [Role-Based Access Control](https://auth0.com/docs/manage-users/access-control/rbac) for the full guide.
  </Accordion>
</AccordionGroup>

***

## Next Steps

Now that you have authentication working in your Laravel application, explore more Auth0 features:

* [Auth0 Dashboard](https://manage.auth0.com/) — Configure and manage your Auth0 tenant and applications
* [laravel-auth0 SDK](https://github.com/auth0/laravel-auth0) — Full SDK documentation and advanced integrations
* [Role-Based Access Control](https://auth0.com/docs/manage-users/access-control/rbac) — Assign permissions to users with roles
* [Auth0 Marketplace](https://marketplace.auth0.com/) — Discover integrations to extend Auth0's functionality
