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. You can use this guide with both The 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:^v0.0.1-alpha

To simplify URLs handling we install the bramus/router

composer require bramus/router

To install Ory CLI follow this guide

Why do I Need the Ory CLI?

Ory CLI provides a convenient way to configure and manage projects. Additionally, the CLI contains Ory Proxy - a reverse proxy that rewrites cookies to match the domain your application is currently on.

Ory Proxy is a reverse proxy deployed in front of your application. The Proxy mirrors Ory endpoints on the same domain as the application you're running and rewrites cookies to match the domain your application is currently on.

As a result, the origin of the cookies is set correctly to the domain you run the app on instead of

<your-project-slug>.projects.oryapis.com

This behavior is necessary to avoid issues with the browser CORS policy.

By using the Proxy, you can easily connect the application you're developing locally to The Ory Network and consume the APIs without the hassle of additional configuration and without the need to self-host any of the Ory Components.

Ory Proxy mirrors Ory's APIs

tip

To learn more about the Ory Proxy, read the dedicated section of the Ory CLI documentation.

Create an Entry Page

This is a working example of basic index.php script which 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.

// Copyright © 2022 Ory Corp
// SPDX-License-Identifier: Apache-2.0

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

error_reporting(E_ERROR | E_PARSE);

$proxyPort = getenv("PROXY_PORT");
if ($proxyPort == "") $proxyPort = "4000";

$app = new App;
// register a new Ory client with the URL set to the Ory CLI Proxy
// we can also read the URL from the env or a config file
$config = Ory\Client\Configuration::getDefaultConfiguration()->setHost(sprintf("http://localhost:%s/.ory", $proxyPort));
$app->ory = new Ory\Client\Api\FrontendApi(new GuzzleHttp\Client(), $config);

$router = new \Bramus\Router\Router();
$router->before('GET', '/', $app->validateSession());
$router->get('/', $app->printDashboard());
$router->run();
?>

Validate and login

Next we will create handler which will check with your Ory project if the user has a valid session. Notice here that we are taking the current request cookies and passing them along to the Ory client.

If the session is not valid the request is redirected to the Ory project for login. At this point we have not set up any custom UI management and thus will be shown the Ory Account Experience login page.

For the last part we need to add the Dashboard handler (the page we would like to protect) which will render an HTML with the session data.

This is accomplished by the simple App class stored in the app.php file:

// Copyright © 2022 Ory Corp
// SPDX-License-Identifier: Apache-2.0

<?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>
';
}
}
?>

Run your app

Start your HTTP server and access the proxy URL

php -S 127.0.0.1:3000
# This is a public Ory Network Project.
# Don’t submit any personally identifiable information in requests made with this project.
# Sign up to Ory Network at
#
# https://console.ory.sh/registration
#
# and create a free Ory Network Project to see your own configuration embedded in code samples.
export ORY_SDK_URL=https://{project.slug}.projects.oryapis.com
ory proxy http://localhost:3000

To access the PHP app through the ORY proxy 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 Proxy or 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\V0alpha2Api(new GuzzleHttp\Client(), $config);