This example shows the power of PHP: it is very easy to get started writing code that runs on the web server, and even though PHP is a terrible language, people choose it because it’s so convenient. The convenience makes it particularly useful for small tasks, but unfortunately, as we will see later, some people use PHP for large projects.
<!DOCTYPE html> <html><body>
<h2>You opened this page at:</h2>
var d = new Date(<?php echo time()*1000;?>);
var text = d.toLocaleTimeString() + " on " + d.toLocaleDateString();
var textnode = document.createTextNode(text);
var timenode = document.getElementById("time");
Figure 1 Timedemo web site source code after adding PHP.
Without the PHP, Date() is called with no arguments, and returns the current time according to the web browser, i.e. according to the laptop’s system clock. With the PHP, Date() is called with "milliseconds since 1970 according to the server’s clock”. The PHP Hypertext Processor will pass through the HTML unmodified, until it detects the <?php … ?> tag, which it will replace with the output of the PHP program.
The timedemo web site is protected with HTTP Basic Authentication. A username and password is required to access it. Let’s review how HTTP Basic Authentication works. We looked at a diagram from dailysecurity.net. But suppose we don’t want the timedemo web site to know which users are allowed to access it, or their passwords. In fact we want the authentication checking to be completely separate, on a different server. Let’s discuss how OAuth2 authentication works. We looked at a diagram, from websequencediagrams.com.
A customer has requested that Quoin develop an authentication service. We decided to use OAuth2. The authorization server will be in Java using the Spring framework. And the web sites requiring authentication will be written (by customer employees) in PHP using the CodeIgniter framework.
Let’s glance over the CodeIgniter framework to see how support for OAuth2 can be added to a PHP application that was developed using CodeIgniter. And let’s make a sample web site, using PHP and CodeIgniter, which requires OAuth2 authentication. We can add a small hook to the main Controller which will, for every request, call an “authenticate_if_needed” function. We can separate our work into the “phpauthdemo” module which is the example app, and the “authentication” module which can be reused in the customer’s app. And since the Java-based authentication server is not ready yet, we will implement our own authentication server in PHP, as the “authserverstub” module. Writing both sides of the protocol does make it easier to understand what’s going on, and to discover potential issues.
The authserverstub can take some shortcuts, such as accepting any username provided that the password “opensesame” is entered, and using transparent reusable strings for the authentication codes, instead of opaque values which can only be used once. OAuth2 allows us to use tokens in whatever format we like. We decided to use JSON Web Tokens. We decided to sign the tokens so that they can be verified for acceptance without needing to ask the authorization server if they’re good. For signing and verification we use the Halite PHP library, which is on top of libsodium. The keys are stored in JSON Web Key format. The phpauthdemo and authserverstub are running on CentOS virtual machines on the presenter’s MacBook. When a page of the phpauthdemo is accessed that requires authentication, the user is redirected to the login screen on the other virtual machine, and then redirected back after a successful login.
Figure 2: PHPautodemo Web App
To support OAuth2 authentication in your web app, you need:
- Authentication server
- Account with credentials
- Agreement with the authentication server on some details
At a minimum, your web app must:
- Store access tokens for each user
- Redirect to the login page if the user doesn't have an access token
- Receive authentication codes and trade them for access tokens
- Present the access token to the protected resource
Ideally, your web app should also:
- Store refresh tokens
- Use refresh tokens to get new access tokens
- validate access tokens
- For single page apps, detect and replace an expired access tokens
- FUSE for macOS
- JSON Web Tokens
- JWT Claim Registry
- JWK Generator
- CodeIgniter Web Framework