Skip to main content

Integrate authentication into PHP

This guide shows how to create a simple PHP application and secure it with authentication powered by Ory. The guide provides the setup for using Ory Network, but the code can be used with both Ory Network and self-hosted Ory software.

This guide is perfect for you if:

  1. You have PHP installed.
  2. You want to build an app using PHP.
  3. You want to give access to your application to signed-in users only.

Before you start, watch this video to see the user flow you're going to implement:

info

You can find the code of the sample application here.

Create PHP app

First we create a new PHP project:

mkdir your-project
cd your-project
touch index.php

Install dependencies

To interact with Ory's APIs we install the Ory SDK:

composer require ory/client

To simplify URLs handling we install the bramus/router

composer require bramus/router

Create a new Ory project

  1. Create an Ory account at https://console.ory.sh
  2. Create a new project at https://console.ory.sh/projects/create
  3. Go to your project settings
https://console.ory.sh/projects/<id>/settings

Project settings tab

  1. Note down your project credentials (ID, slug, endpoint)
https://console.ory.sh/projects/<id>/settings

Project credentials

Install Ory CLI

To install Ory CLI follow this guide

Why do I need the Ory CLI

The Ory security model uses HTTP cookies to manage sessions, tokens, and cookies. Because of browser security measures like CORS, Ory APIs must be exposed on the same domain as your application. In the case of this example the application runs on your local machine. The cookie domain is localhost.

Use either localhost or 127.0.0.1 consistently. Although technically they refer to the same machine, browsers treat

them as different cookie domains. :::

Ory CLI provides a convenient way to configure and manage projects. Additionally, the CLI provides Ory Tunnel - a tool that ensures cookies match the domain your application is currently on.

To make Ory APIs and your application available on the same domain, Ory Tunnel mirrors Ory endpoints and rewrites cookies to match the correct domain. As a result, the domain of the cookies is set correctly to the domain you run the app on instead of <your-project-slug>.projects.oryapis.com.

By using the Tunnel, you can easily connect the application you're developing locally to Ory Network and consume the APIs without additional configuration or self-hosting any Ory services.

To learn more about the Ory Tunnel, read the

Create an Entry Page

Create a new file called index.php and paste the following code:

./index.php
<?php
require 'vendor/autoload.php';
require_once 'app.php';

error_reporting(E_ERROR | E_PARSE);

$tunnelPort = getenv("TUNNEL_PORT");
if ($tunnelPort == "")
$tunnelPort = "4000";

$app = new App;
// Configure Ory client to use tunnel port 4000
$config = Ory\Client\Configuration::getDefaultConfiguration()->setHost(sprintf("http://localhost:%s", $tunnelPort));
$app->ory = new Ory\Client\Api\FrontendApi(new GuzzleHttp\Client(), $config);
// Pass tunnel URL to the App class for redirects
$app->tunnelUrl = sprintf("http://localhost:%s", $tunnelPort);
$router = new \Bramus\Router\Router();
$router->before('GET', '/', $app->validateSession());
$router->get('/', $app->printDashboard());
$router->run();
?>

This entry script creates an Ory client, registers new route for our Dashboard and makes use of Before Route Middlewares to validate if the user is allowed to view the Dashboard.

We are yet to create an App class, let's do that now.

Validate and login

Create a new file called app.php and paste the following code:

app.php
<?php

class App
{
// save the session to display it on the dashboard
private ?Ory\Client\Model\Session $session;
public ?Ory\Client\Api\FrontendApi $ory;

public function validateSession()
{
$cookies = "";
// set the cookies on the ory client
foreach ($_COOKIE as $key => $value) {
$cookies .= "$key=$value;";
}

try {
// check if we have a session
$session = $this->ory->toSession("", $cookies);
if (! $session["active"]) throw new Exception('Session expired');
} catch (Exception $e) {
error_log('Exception when calling toSession: ' . $e->getMessage());
// this will initialize a new login flow and Kratos will redirect the user to the login UI
header("Location: /.ory/self-service/login/browser", true, 303);
die();
}
$this->session = $session;
}

public function printDashboard()
{
echo '
<html lang="en">
<head>
<title>Ory Network secured Go web app</title>
</head>
<body>
<h1>Dashboard</h1>
<hr />
<h2>Your Session Data:</h2>
<pre><code>', json_encode($this->session, JSON_PRETTY_PRINT), '</code></pre>
</body>
</html>
';
}
}
?>

Create a handler that checks with your Ory project to determine if the user has a valid session. We take the current request cookies and pass them to the Ory client.

This file validates the session and redirects to the login page if the session is invalid. If the session is not valid, the request is redirected to the Ory project for login. At this stage, we have not set up any custom UI management, so the Ory Account Experience login page will be displayed.

Finally, we added the Dashboard handler (the page we want to protect), which will render HTML with the session data.

Run your app

Start your HTTP server and access the tunnel URL

php -S 127.0.0.1:3000

Next open a new terminal window and start the Ory Tunnel. Upon first start, the Ory Tunnel will ask you to log into your Ory Console account.

ory tunnel --project <PROJECT_ID> http://localhost:3000

To access the PHP app through the Ory Tunnel, open http://localhost:4000 in your browser. You are presented with Ory's Sign In page. Let's click on sign up and create your first user.

Go to production

You can use many different approaches to go to production with your application. You can deploy it on Kubernetes, AWS, a VM, a RaspberryPi - the choice is yours! To connect the application to your Ory project, the app and Ory APIs must be available under the same common domain, for example https://ory.example.com and https://www.example.com.

You can easily connect Ory to your subdomain. To do that, add a Custom Domain to your Ory Network project.

With the custom domain set up, you don't need to use Ory Tunnel to interact with Ory APIs. Instead, use the configured custom domain in your SDK calls:

$config = Ory\Client\Configuration::getDefaultConfiguration()->setHost("https://ory.example.org"));
$ory = new Ory\Client\Api\FrontendApi(new GuzzleHttp\Client(), $config);