Get your free and exclusive +30-page Authentication Analytics Whitepaper

Laravel Passkeys: How to Implement Passkeys in PHP Laravel

This tutorial shows PHP developers how to integrate passkeys into a PHP Laravel app. Besides passkey authentication, session management is also implemented.

Blog-Post-Author

Lukas

Created: November 14, 2023

Updated: March 25, 2026

passkeys-php-laravel
PasskeysCheatsheet Icon

Looking for a dev-focused passkey reference? Download our Passkeys Cheat Sheet. Trusted by dev teams at Ally, Stanford CS & more.

Get Cheat Sheet
Key Facts
  • The Corbado PHP SDK (corbado/php-sdk) is installed via Composer and uses validateToken() to verify short-term session cookies in the Laravel backend.
  • The setShortSessionCookie option in Corbado web-js must be set to true to automatically generate a JWT session cookie upon successful passkey login.
  • The Relying Party ID must be the bare domain only (no protocol, no port, no path). For local development this is localhost.
  • Two Composer packages are required: corbado/php-sdk for session validation and symfony/cache for the JWKS cache via FilesystemAdapter.
  • The mountAuthUI method injects Corbado's authentication component into any HTML div, handling both passkey sign-up and login without custom form logic.

1. Introduction: PHP Laravel Passkeys#

In this blog post, we’ll explore how to implement passkeys for secure authentication using Corbado. We'll cover the setup of the Corbado web-js package for the frontend part as well as the Corbado PHP SDK for the PHP backend part.

If you want to see the finished code, please have a look at our sample application GitHub repository.

The result looks as follows:

2. PHP Laravel Passkey Project Prerequisites#

This tutorial assumes basic familiarity with PHP Laravel, JavaScript and HTML. Also make sure to have PHP as well as composer installed and accessible from your shell. Lets dive in!

3. Repository Structure for PHP Laravel Passkey Project#

A Laravel project contains many files, but the important ones for us in this tutorial are the following:

... ├── .env # Contains all environment variables ├── app | ├── Http | | └── Controllers | | ├── ProfileController.php # Responsible to retrieve profile information in backend | | └── Controller.php | | | └── Providers | └── AppServiceProvider.php # Used to inject the Corbado project ID into all views ├── config | └── app.php # Make environment variables available ├── resources | └── views | ├── welcome.blade.php # The login page | └── profile.blade.php # The profile page └── routes └── web.php # The routes for our frontend pages
Slack Icon

Become part of our Passkeys Community for updates & support.

Join

4. Set Up Your PHP Laravel Project#

Let's start by creating our PHP Laravel app:

composer create-project laravel/laravel passkeys-example-app

In the installation guide steps, we select the following:

  • Would you like to install a startker kit? No starter kit
  • Which testing framework do your prefer? Choose according to your preference, we chose Pest
  • Would you like to initialize a git repository? Choose any option you like
  • Which database will your application use? We chose SQLite, although the database won't be used as part of this tutorial

That's already it for now.

5. Set Up Corbado Passkey Authentication#

To set up Corbado passkey authentication in your PHP Laravel project, follow the next steps.

5.1 Set Up Your Corbado Account and Project#

Visit the Corbado developer panel to sign up and create your account (you'll see the passkey sign-up in action here!).

After sign-up, a project wizard will guide you through the necessary steps to get everything up and running:

  1. Begin by selecting an appropriate name for your project.
  2. For the product selection, opt for "Corbado Complete".
  3. Register your community license and optionally join our Passkeys Community or subscribe to the Passkeys Substack.
  4. Select "DEV" as your environment.
  5. Choose "Corbado session management" to get a secure and efficient session management besides passkey authentication.
  6. Choose "Web app" as we're building a web application.
  7. Select "Vanilla JS" as your frontend framework.
  8. Provide the Application URL and Relying Party ID. The Application URL is the URL where you embed the Corbado UI component. In this example, we set it to http://localhost:8000. The Relying Party ID is the domain (no protocol, no port and no path) where passkeys should be bound to. Here, it's localhost (you can define both values als in the Settings > General > URLs of the Corbado developer panel).

Afterwards, you'll see the relevant html / javascript code snippets you need to integrate into the project. The subsequent sections of this article will explain them in detail.

As another step, we create an API secret which will be needed to request user data from the Corbado backend. Please create an API secret in Settings > Credentials > API secrets.

Afterwards, we need to also get the Frontend API and Backend API URLs which we can find in Settings > General.

Next, you need to go back to your terminal and should navigate to the root directory of the project:

cd passkeys-example-app

Open the .env file at the root of your project. Copy and paste the Project ID, API secret, Frontend API URL and Backend API URL (you can obtain it from the Corbado developer panel from Settings > General > Project info above into it. The .env file should look like this now:

# ... other settings CORBADO_PROJECT_ID=your-project-id CORBADO_API_SECRET=your-api-secret CORBADO_FRONTEND_API=your-frontend-api-url CORBADO_BACKEND_API=your-backend-api-url

5.2 Project Preparation#

First, install the Corbado PHP SDK:

composer require corbado/php-sdk

Next, head into the config/app.php file and add the following line right at the bottom of the returned array:

<?php return [ // leave all other config options as is 'CORBADO_PROJECT_ID' => env('CORBADO_PROJECT_ID', null), ]

That's it for the setup.

5.3 Create the Homepage to Handle Sign-ups and Logins#

Our Homepage will use the Corbado web-js package to handle passkey authentication.

We include the relevant assets in the head of the page and create a div with the id of corbado-auth. In a separate script tag, we'll be loading our Corbado project with our project id and set the setShortSessionCookie option to true, so a jwt session-cookie is created on login. Lastly, we'll inject the authentication UI in our div.

Head into the resources/views/welcome.blade.php file and replace the skeleton with the following code:

<!DOCTYPE html> <html> <head> <title>Authentication</title> <link rel="stylesheet" href="https://unpkg.com/@corbado/web-js@2.9.0/dist/bundle/index.css" /> <script src="https://unpkg.com/@corbado/web-js@2.9.0/dist/bundle/index.js"></script> </head> <body> <div id="corbado-auth"></div> <script type="module"> await Corbado.load({ projectId: "{{ config('app.CORBADO_PROJECT_ID') }}", setShortSessionCookie: true, darkMode: "off", }); async function onLoggedIn() { window.location.href = "/profile"; } const authElement = document.getElementById("corbado-auth"); //Element where you want to render CorbadoAuth UI Corbado.mountAuthUI(authElement, { onLoggedIn: onLoggedIn, }); </script> </body> </html>

The route for this page is already preconfigured by the skeleton project, so we can now see this page under http:localhost:8000.

To try it out, run your application with the following command:

php artisan serve

Note: The component will only work properly when the page is visited on localhost.

5.4 Create a Profile Route using the Corbado PHP SDK#

Create a ProfileController with the following command:

php artisan make:controller ProfileController

It will also need a cache for the jwks, which we'll install like this:

composer require symfony/cache

Our controller will make user information available to our template by using the Corbado PHP SDK.

Now, head into the created Controller file under app/Http/Controllers/ProfileController.php.

In the controller's constructor, we'll instantiate the PHP SDK:

<?php namespace App\Http\Controllers; use Corbado\Exceptions\AssertException; use Corbado\Exceptions\ConfigException; use Illuminate\Http\Request; use Corbado; use Symfony\Component\Cache\Adapter\FilesystemAdapter; class ProfileController extends Controller { protected $CorbadoSDK; /** * @throws ConfigException * @throws AssertException */ public function __construct() { $jwksCache = new FilesystemAdapter(); $config = new Corbado\Config(env("CORBADO_PROJECT_ID"), env("CORBADO_API_SECRET"), env("CORBADO_FRONTEND_API"), env("CORBADO_BACKEND_API")); $config->setJwksCachePool($jwksCache); $this->CorbadoSDK = new Corbado\SDK($config); } }

Now, add a showProfile method, that will make user information available to our template:

class ProfileController extends Controller { // .... public function showProfile(Request $request) { // Retrieve the short-term session value from the Cookie or // the Authorization header. $shortTermSessionValue = '<Your short-term session value>'; if ($shortTermSessionValue == '') { // If the short-term session value is empty (e.g. the cookie is not set or // expired), the user is not authenticated. Redirect to the login page. return redirect('/')->withErrors('Unable to retrieve user information.'); } try { $user = $this->CorbadoSDK->sessions()->validateToken($shortTermSessionValue); } catch (\Exception $e) { error_log($e); return redirect('/')->withErrors('Unable to retrieve user information.'); } return view('profile', ['user' => $user]); } }

Next, we'll create the template under resources/views/profile.blade.php.

It will render some user information and use the Corbado web-js package again to handle logout button functionality.

We add an event listener to the button that uses the Corbado.logout utility.

<!DOCTYPE html> <html> <head> <title>User Profile</title> <link rel="stylesheet" href="https://unpkg.com/@corbado/web-js@2.9.0/dist/bundle/index.css" /> <script src="https://unpkg.com/@corbado/web-js@2.9.0/dist/bundle/index.js"></script> </head> <body> <h1>User Profile</h1> @if (isset($user) && $user->isAuthenticated()) <p><strong>Id:</strong> {{ $user->getId() }}</p> <p><strong>Email:</strong> {{ $user->getEmail() }}</p> <button id="logoutButton">Logout</button> <!-- Add other user information as needed --> @else <p>No user information available.</p> <a href="/">Go back home</a> @endif <script type="module"> await Corbado.load({ projectId: "{{ config('app.CORBADO_PROJECT_ID') }}", setShortSessionCookie: true, }); document .getElementById("logoutButton") .addEventListener("click", async () => { await Corbado.logout(); window.location.href = "/"; }); </script> </body> </html>

Lastly, we'll crate the route for this view under routes/web.php.

The final route file should look like this:

<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\ProfileController; Route::get('/', function () { return view('welcome'); }); Route::get('/profile', [ProfileController::class, 'showProfile'])->name('profile');

That's already it, we now have a fully functioning profile page using information obtained in our PHP server and Corbado web-js for frontend functionality like a logout.

5.5 Run the PHP Laravel Application#

Finally, take a look at the result by running:

php artisan serve

After signup, you'll be redirected to the profile page. Here, you can logout and return to the homepage again.

6. Conclusion: PHP Laravel Passkeys#

This tutorial showed how easy it is to add passwordless authentication with passkeys to a PHP Laravel application using Corbado. Besides the passkey-first authentication, Corbado provides simple session management, that we used for a retrieval of basic user data. If you want to read more about how Corbado's session management please check the docs here.

Frequently Asked Questions#

How do I protect a Laravel route so only authenticated passkey users can access it?#

In the ProfileController, retrieve the short-term session cookie from the request and pass its value to $this->CorbadoSDK->sessions()->validateToken(). If the token is missing or invalid, redirect the user back to the login page; if valid, the returned user object exposes methods like getId() and getEmail() for use in your Blade template.

Why does the Corbado authentication component only work on localhost during development?#

Passkeys are cryptographically bound to a Relying Party ID, which must match the domain serving the page. During development the Relying Party ID is set to localhost and the Application URL to http://localhost:8000, so the component will not function correctly if accessed via a different hostname or IP address.

How does logout work in a Laravel app that uses Corbado passkey authentication?#

Logout is handled entirely on the frontend using the Corbado web-js package. You attach a click listener to a button that calls Corbado.logout() and then redirects the user to the homepage. No server-side session invalidation call is required in the Laravel backend for this flow.

What Corbado developer panel settings do I need before I can run passkey authentication in Laravel?#

You need four values from the Corbado developer panel: the Project ID, an API secret (created under Settings > Credentials > API secrets) and the Frontend API and Backend API URLs (found under Settings > General > Project info). These are stored in the Laravel .env file and referenced by the PHP SDK configuration.

Add passkeys to your app in <1 hour with our UI components, SDKs & guides.

Start Free Trial

Share this article


LinkedInTwitterFacebook