CakePHP PSR7 Middleware Authentication

Introduction and background

Let’s start with some background story on this topic. One of the parts of the CakePHP framework I like the less is the authentication and authorization. There are a few reasons why. For example the authentication and authorization. Firstly both authentication and authorization have been married through the AuthComponent, secondly the component is an ugly monolith that is coupled to the controller layer of the MVC pattern.

While CakePHP 3 is an awesome framework it carries some of the older parts of the framework along to ensure backward compatibility which is, in my personal opinion, good. Software development should be an evolution and not a revolution. Also a soft migration path should be provided if possible. So the requirement for a new implementation was to stay backward compatible to some degree.

The new implementation

https://github.com/cakephp/authentication

I’ve been working from time to time late night to finish a new authentication system for the CakePHP 3 framework based on a PSR7 conform middleware. Which is the place where authentication should happen in my opinion. The request object should carry all information you need to identify an user. Also you want to identify an user or a service early in the stack.

The authentication has been completely refactored and was moved into a new namespace/authentication and the code‘s folder structure was reorganised as well. But the biggest change is probably the better split of the logic, a more fancy term is separation of concerns, of the authentication code. The code has been split into authenticators and identifiers. Basically the authenticator just looks for the credentials in the request and passes them to a collection of identifiers that will use the credentials to identify the identity against different sources. So for example you can check the same credentials against an users table using the CakePHP ORM and LDAP at the same time.

The configuration stays almost the same as it was before just that you have to split it for the authenticators and identifiers. Also hooking the authentication in your app is now happening in the middleware, no longer the controller. But these two things are the most dramatic changes on the surface you’ll be confronted with.

New features

Besides keeping the existing authenticators, HTTP Digest, HTTP Basic and Form there is now Token and Session as well. Token is a high level implementation that allows you to use a token from the requests query parameters or a HTTP header. Extending this to use JWT should be trivial.

Current status and roadmap

The current status of the plugin is that it is ready to be used – technically. What I expect from you, the community, is ideas for improvements and additions. And despite the good unit test coverage of more than 92% I expect bugs to be encountered as usual.

The roadmap for the plugin is to release 1.0.0 along with the official release of CakePHP 3.4. The plugin itself is right now in beta and will make it’s path to a final release depending on your feedback. So if everything goes well this means the plugin should be tagged 1.0.0 the latest by the end of January 2017.

The long term plan is that the plugin will be integrated into the framework itself. The goal is to get it into CakePHP 3.5 early to mid next year.

Where is the code? How do I install it?

Check the official repository of the plugin and install it via composer as usual.

Pay attention to the version constraints! Until CakePHP 3.4 is released it will require the 3.next branch!

The readme.md of the project contains some basic information on how to get started with the new implementation and provides information on how to migrate from the AuthComponent as well.

CakePHP3: When to use Elements, Helpers or View Cells?

This has been asked on Stackoverflow and I decided to turn my long answer in a Blog post as well. This article will explain when to use the different parts of views the best. This might be opinionated but it is based on writing clean and re-usable code.

Elements

Use it when you need to repeat presentation related stuff, usually HTML, a lot. For example I have a project in which three tables use records of an addresses table. The form part of all of these three that contains the address data is an element. There is no logic at all in this and I think if it is just a very simply if that wraps an element call or something similar you don’t need to come up with a helper for that, it’s just to basic. Elements are basically “dumb” snippets that repeat through the site.

Helpers

Use it to encapsulate view logik, don’t put HTML in it if possible or other presentation related things. For example let it do something and depending on the result you can use an element of that result type to render the data: `return $this->_view->render(‘items/’ . $type . ‘_item’);`

You might say now “But the Form- and HtmlHelper contain HTML…” well, they do but look at their code how they deal with it. If you look a the HtmlHelper for example you’ll see a property $_defaultConfig[1]:

These are the template strings that are used to generate the HTML output. This separtes the markup pretty nice from the actual code that generates the final output. Take a look at the FormHelper as well, it’s using widgets to render more complex output. See this section “Adding Custom Widgets“[3] of the official documentation.

So this works fine with element like pieces of markup. By a rule of thumb I would say if your markup is longer than what you see there make it an element and call it from within the helper or make it a widget.

View Cells

Think of view cells as “Mini MVC” stacks that have a view and can load multiple models. They’re IMHO similar to AngularJS directives if you’re familiar with them. See this article for an example [2]. I really suggest you to read it, it explains them and their use cases in detail.

I haven’t done much with them yet but they can be used to replace requestAction() calls for example. You won’t “pollute” your controller with methods that are not intended to be access by a request. Taken from the linked article above:

One of the most ill-used features of CakePHP is View::requestAction(). Developers frequently use this all over their applications, causing convoluted cases where you need to figure out if you are within a web request or an internal action request, cluttering controllers. You also need to invoke a new CakePHP request, which can add some unneeded overhead.

Disclaimer

The above reflects my personal view on these things, there is no ultimate and final rule how you have to use these three things. The goal is always clean and re-useable code and proper separation of concerns. How you archive that is up to you, you’ve got the tools.

[1]: http://api.cakephp.org/3.0/source-class-Cake.View.Helper.HtmlHelper.html#54
[2]: http://josediazgonzalez.com/2014/03/20/view-cells/
[3]: http://book.cakephp.org/3.0/en/views/helpers/form.html#adding-custom-widgets

Working with CakePHP 3.0 Entity objects vs CakePHP 2.0 arrays

CakePHP3 finds will now return a ResultSet object that contains entity objects, one per records. You’ll have to work with these objects now instead of arrays. This is the official description of them:

  • Cake\ORM\ResultSet – A collection of results that gives powerful tools for manipulating data in aggregate.
  • Cake\ORM\Entity – Represents a single row result. Makes accessing data and serializing to various formats a snap.

Further down on that page there is even more info about that. Take a look at the ResultSet API. You’ll see that it implements Iterator, you can use it like an array because of that but it’s an object.

Let’s start with the example UsersController.

The UsersTable, formerly known as a Model.

In your App/View/Products/index.ctp put this:

If you add a

in the loop it will show you the Entity object. I’m not pasting the whole long debug output here, skipping a few fields.

As you can see you’re getting an object back not an array any longer. To access the values or “fields” of your entity object just access it as a property of the object, the magic getter will get you the value of it from the protected _properties property of the Entity object.

Now try adding this into the foreach loop.

Output:

Not all fields were converted, fields that contain an object stay an object. Calling toArray() here will convert the object into an array in the case you really want to continue using arrays instead of object. I would not recommend to do so because your’re simply throwing the new features and possibilities objects make possible away!