Authentication plugin: install & use

As expected, ‘localhost:8765’ can’t still be visited without logging in. Haven’t searched yet, but there will be something to have done higher up in the controller-tree.

The Authentication configuration is all done in src\Application.php just as the Middleware starts up:

https://discourse.cakephp.org/t/authenticationmiddleware-overview-of-version-2-0/7516/2

I’ll leave that one on the to-do list, first I want the authenticatation to work.

‘allowUnauthenticated’ in the beforeFilter-function of the UsersController has to be extended with ‘add’ to make it possible to access the page for adding users.

Surprise 1: Tooltips use the system language, expected them to be in English…
Surprise 2: After succesfully adding users, can’t log-in, ‘invalid username or password’.

Because not using the hashing-mechanism yet, phpMyAdmin shows me the users are present and I’m not making typo’s.

To be able to update my password, I have to be logged in, which I can’t …

But I will enable hashing.

After adding the given code to src/Model/Entity/User.php (and truncate the users-tabel), I’m able to add users and log-in, see the page at localhost:8765, edit records etc.

After log-in, I’m looking at the view of the users-table. Think I’m getting in the scope of authorization … That will be another post.

After adding the logout-function to the users-controller, the basics of authenticatation are working.
I can login and logout, when I’m not logged-in, I’m not able to do things for which I have to be authenticated (edit, delete).

Having this in place, you’re going to look for things that should be available, like an indicator that I’m logged in, the forgotten password button. After that, integration with other login-systems? That’s more a functional extension of the ‘Further Reading’ I’m missing I think.

Trying to find out how to access ‘localhost:8765’ without having to log in.

The post Allowing a specific page in CakePHP shows the way to go, but it’s 3 code.

‘Rebuilding’ it to something like used in the table-controller to get access to ‘index’ and ‘view’, it would be:

class PagesController extends AppController
{

public function beforeFilter(\Cake\Event\EventInterface $event)
{
parent::beforeFilter($event);

// Make page 'home' not require a logged in user.
$this->Authentication->allowUnauthenticated(['home']);
}

But that doesn’t work.

Wonders me why searching with ‘allowUnauthenticated’ doesn’t give any hits, especially not within the cookbook.

What code will work?

Trying to find a solution, next page I visit is CMS Tutorial - Authentication. Whatever I wil read on this page, my expectation is that it builds on Quick Start - 2.x CakePHP Authentication, links between those two pages would be nice I think.

Reading there are some differences which make me wonder:

  • The earlier in this topic mentioned composer-command;
  • The QuickStart adds

public function bootstrap(): void
{
parent::bootstrap();

$this->addPlugin('Authentication');

}

to Application.php, the Tutorial doesn’t?

  • The QuickStart uses ‘allowUnauthenticated’, the Tutorial ‘addUnauthenticatedActions’. Somewhere in the cookbook will be the details, I hope.

But nothing about allowing unauthenticated access to a page :frowning:

Digging some deeper in the cookbook, I get to the AuthComponent :

This just sends me back to the place where I started , the Quick Start Authentication.

(Leaves me wondering what’s the use of describing a deprecated 3.8-component in the 4.x - cookbook?)

Your $this->Authentication->allowUnauthenticated(['view', 'index']); call looks correct.

But you don’t show how or when you are loading the Component for that. Here is an example from one of my Cake4.x apps that is working.

 //set global allowed actions
 $this->loadComponent('Authentication.Authentication');
 $this->Authentication->allowUnauthenticated(['register', 'logout', 'forgot-password', 'welcome']);

This is in my AppController::initialize().

The difference between these two:

  • allow… will set the list of actions that can be visited without authentication
  • add… will add more entries to that list

So it’s meant to be used like putting the ‘allow’ for example in the ‘AppController’, and putting the ‘add’ in for example a ‘Table1Controller’?

But what puzzles me the most, where do you collect this knowlegde? Where can I find this info, am I missing a part of the docs, am I searching in the wrong way? I’m glad you give an awnser, but this sort of basic knowledge I want to be able to retrieve by myself.

This ‘part’ of the authentication, the controllers that are related to the tables, is working as expected, no problem here.

I don’t know how/can’t find a way to let the PagesController show pages unauthenticated. For example, I have to log-in to get access to the ‘home.php’ on ‘localhost:8765’. I want to show this page without having to log-in.

The ‘allowUnauthenticated’ given in the examples are related to the functions in a controller. There has to be a way to state pages instead of functions. Whether it’s another call (‘allowUnauthenticatedPages’ or something like that) or another variable (like ‘allowUnauthenticated([page.home]’).

I can find code to get his done, but it’s cake 3x code, using the deprecated AuthComponent. I assume there is a substitute statement. But what? Where to find?

I found this that might be a pathway to your solution. But I don’t understand how to implement it.

https://book.cakephp.org/authentication/2/en/authenticators.html#url-checkers

I don’t know how other folks get up to speed, but I spend quite a bit of time tracking back to the core code (a process my IDE makes very easy). The doc blocks in the code often gives me insight on how to proceed. The API documentation provides the same thing but I find it hard to navigate. When I’m coding, I typically have all the method-hinting of the objects of interest and can quickly find and see exactly the docblocks and code of interest. In the case of the new Authentication, I’m not even sure where the API docs are.

It’s not unusual for me to drop debug-and-die commands in the core code to work my way to a solution.

Are these ideal approaches? Probably not.

Ah! I think this is your answer.

The action in Pages is display add this to your list and it should work. It does for me.

$this->Authentication->allowUnauthenticated(['display', 'register', 'logout', 'forgot-password', 'welcome']);

1 Like

Yes! That’s it, thanks.

Seems the logical solution after all. The ‘allowUnauthenticated’ uses a list of actions, so ‘just’ pick the wanted function defined within a controller.

In some use case it will be necessary to be able to see some pages with and some pages without authentication. Now all pages won’t need authentication. But that’s something to explore when needed.

I tagged this post ‘Site Feedback’, my aim was to find out how to get the basics of authentication working with ‘just’ the presented docs. Looking into the code, inserting debug-command commands etc. , that’s a bridge too far for me right now. I’m not mastering the basics of CakePHP, I first want to get the ‘feel’ of how things work (like for example the ‘allowUnauthenticated’).

So finally I got the basics working. After all, the needed info is somewhere in the docs (except API-docs, no v4 available?), but it takes time and help of the forum-members to get things up-and-running. I wonder if this is just me, or if this is a more general CakePHP-issue.

I’ve always assumed it was my learning style. I do best with a global perspective first. Then I have a scene to fit all the details into. But the cake docs are presented in (what I think of as) a more traditional rule-list form.

Rule-lists are the least effective way for me to learn anything. This is the reason I drew the UMLs. But I haven’t decided how much detail they should have to be a useful and maintainable part of the documentation. Less detail than I have included so for I’m sure.

Recapitulation/Recipe (for use after a fresh install of CakePHP 4.0.5):

  1. Install plugin.
    composer require cakephp/authentication:^2.0
    Installs plugin authentication in ‘./vendor/cakephp/authentication’.

  2. Load the plugin.
    Edit ‘./src/Application.php’.
    Add use of authentication.
    Expand function ‘bootstrap’.
    Add function ‘getAuthenticationService’.
    Expand function ‘middleware’.

  3. Load the authentication component.
    Edit ‘./src/Controller/AppController.php’.
    Expand function ‘initialize’.

  4. Make it possible to access pages without having to log in (for example home.php on localhost:8765).
    Edit ‘./src/Controller/PagesController.php’.
    Add function ‘beforeFilter’. The action to allowUnauthenticated is ‘display’.

  5. Make it possible to ‘index’ and ‘view’ of TableX without having to log in.
    Edit ‘./src/Controller/TableXController.php’.
    Add function ‘beforeFilter’.

  6. Add a Users-table (email, password) to the database .

  7. Generate MVC Users
    Do the ‘cake bake all users’.

  8. Create login- en logout-function.
    Edit ‘./src/Controller/UsersController.php’.
    Add function ‘beforeFilter’ to make it possible to login and add a new user withouth having to be logged in.
    Add function ‘login’ .
    Add function ‘logout’.

  9. Create the login-page.
    Add the code below the sentence ‘Add the template logic for your login action’ on the CMS Tutorial - Authentication page to a new file ‘./templates/Users/login.php’.

  10. Enable password hasher.
    Edit ‘.scr/Model/Entity/User.php’.
    Add use of PasswordHasher.
    Add function _setPassword.

2 Likes

When asking end-users to review a prototype with authentication configured this way, there is no need to give any extra written or spoken explanation how to use the prototype regarding the authentication. They are prompted to login when needed, everybody is entitled to add a user.

Except for at least one thing, how to logout (another will be the forgotton password). I added a logout-button which is only visible when logged in. Don’t know if it’s the proper way, it works:

Added to the app_controller:

public function beforeFilter(\Cake\Event\EventInterface $event)
{
parent::beforeFilter($event);

$result = $this->Authentication->getResult();
$this->set(‘result’, $result);
}

Added to ‘templates/layout/default.php’:

 <? php if($result->getStatus() == "SUCCESS"):
 $this->Html->link('Logout', '/users/logout', ['class' => 'button float-right'])
 endif; ?>