Skip to content

End to end authentication flow

Greg Bowler edited this page Aug 14, 2020 · 22 revisions

This section describes each step of the authentication flow in detail. All code examples are referencing the PHP implementation of the client library.

Consumer application

The consumer application is the software that is being developed that requires authentication to be provided by Authwave. This could be any server-side web application such as a blog, e-commerce website, email service, etc.

For a consumer application to be able to communicate with Authwave, it needs to be configured within the Authwave host (typically www.authwave.com, unless self-hosting Authwave).

From the Authwave host configuration, you will create an Application with at least one Deployment. A Deployment is required for each host that will be service a consumer application. Your application in production, any staging varieties and a local development copy are all separate Deployments.

Each deployment is configured to have its own:

  1. Client key - a randomly generated set of alphanumeric characters, unique to the application.
  2. Client host - the hostname where the consumer application is hosted from.
  3. Login host - the hostname where the Authwave provider is hosted.

Typically the login host will be the client host prefixed with account.. For example, a website with client host of www.example.com could have a login host of account.example.com, but this can be configured to however the developer chooses.

Authwave then needs to be installed on the server. For PHP applications this is done by installing using Composer. In the future, other languages are planned to be officially supported.

Authentication action

When the consumer application is ready to authenticate a user, a new instance of the Authwave Client must be instantiated:

$authwave = new \Authwave\Authenticator("your-client-key", $currentUriPath, "account.example.com");

The first parameter is the Application Deployment's client key. The second parameter is the current URI's path. In PHP, this can usually be obtained with $_SERVER["REQUEST_URI"]. The third parameter is the hostname of where the provider is hosted.

By default, PHP has global access to session variables and response headers. In languages that do not have global access to these, or in PHP frameworks that encapsulate that functionality, it is required to pass more parameters to the Authenticator: a fourth parameter of a session handler and a fifth parameter of a redirect handler.

Constructing the Authenticator object firstly sets all properties on the object, then calls the completeAuth() function which will handle any authentication flow that is currently in progress. More on this later.

Once the Authenticator object is constructed, we can call $authwave->isLoggedIn() to obtain a boolean indicating whether there is currently an authenticated user on the session.

The login() function

The action that triggers authentication depends on what application is being developed, but it usually consists of submitting a form or following a link.

Once the consumer application reacts to the user action, we can simply call the login() function to begin the Authentication flow. This is the only action the consumer application needs to make, as the rest is handled on the Authwave server.

if($userRequestedLogin) {
	$authwave->login();
}

Within the login function, the following takes place:

  1. The login function can receive a predefined Token object as its only parameter. If there is no Token provided, we generate a new one. A Token is the encryption/decryption mechanism used to transfer authentication details. More on this later.
  2. A new SessionData object is created to store the Token. The SessionData object is then stored onto the session.
  3. Finally, the user agent is redirected to the Authwave provider. The redirect URI contains encryption details in the query string.

What is a Token?

Under normal circumstances, a new Token should be created each time login occurs. A Token is constructed with the client key, and generates two InitVector objects - one private and one public. It's possible to pass pre-constructed InitVector objects in the Token's constructor, but under normal circumstances these will be generated automatically.

A token has a function generateRequestCipher(), which takes an arbitrary message as an optional parameter. A request cipher is a string containing the private IV and optional message, encrypted with the client key using the AES128 cipher method. If a message is supplied, it will be concatenated onto the private IV using the pipe character (|). The initialisation vector used in the AES128 cipher generation is the public IV.

What is an InitVector?

An InitVector is a representation of cryptographically secure pseudo-random bytes, represented as a hex string. There must be no way to predetermine the bytes represented by an InitVector.

During the authentication process, we generate two InitVector objects. One private and one public. The private IV is stored in the session on the consumer application's server. The public IV is sent to the provider application's server.

What is a SessionData object?

SessionData is a simple Data Transfer Object with no functionality of its own. It simply constructs with Token and an optional ResponseData parameters, and provides getter functions for these two properties. The purpose of the SessionData object is to provide an easy interface for passing around in session storage.

The redirect URI

A URI is a common object in any web project. In PHP, any URI object used will be an instance of the Psr\Http\Message interface (PSR-7).

Within the client library, an AbstractProviderUri class is used to define the common functionality of normalising URIs (ensuring the correct scheme is present, that there is a hostname present and that only non-standard ports are present), and building the query string parts. This allows there to be simple classes representing the different URIs in the system, including the LoginUri, LogoutUri, ProfileUri and AdminUri.

The LoginUri is used to send the user agent to the Authwave provider with the cipher as the first step of the authentication process. It is constructed with the current Token, the current path and the hostname of the provider as its parameters.

The AbstractProviderUri class provides the buildQuery function, which contains the following key value pairs:

  • c: The request cipher (base64 encoded).
  • i: The public initilisation vector (represented in hex).
  • p: The current path (represented in hex).
Clone this wiki locally