Creating a complete login workflow
The Login module provides the logic for a user authentication mechanism, but it's up to you to build a form to ask the user for his credentials, or to implement any kind of interface for a user to authenticate in your web app.
We'll analyze step by step the example provided in the Cherrycake documentation examples repository, in the module called LoginGuide
.
See this complete login workflow working in the Cherrycake documentation examples site.
First we'll create our module in /src/LoginGuide/LoginGuide.class.php
:
See how we've already added the HtmlDocument and Login dependencies.
Now we'll define an action that will show a welcome page when the user visits the /login-guide
URL:
Notice that the page shows the message You are logged in
or You are not logged in
. To determine whether the current user is logged in, we use the Login::isLogged method.
Now we'll add another action that will show a login form in the /login-guide/login-page
URL:
And we'll add a button right next to the You are not logged in
message, that will link to this login page:
See how, instead of linking directly to /login-guide/login-page
, we've used the Actions::getAction and the Request::buildUrl methods in chain to obtain the URL for the action that triggers the login page, as you've learned in the Actions guide.
So now, when we access the /login-guide page, this appears:
And when we click the Login button, the /login-guide/login-page
appears:
Clicking the
Login
button does nothing because we haven't yet set theaction
property of the form HTML element.
Now let's create an action that will be triggered when the Login
button is clicked. This action will use the Login module to check the received email
and password
, and act accordingly afterwards.
We'll call this action loginGuideDoLogin
:
We've set the
isSensibleToBruteForceAttacks
parameter to true when creating the Action to improve the resistance of this request to brute force attacks. We've also set theisSecurityCsrf
parameter to true when creating the Request, which adds protection against Cross-Site Request Forgery-type attacks to this request.
Now we need to modify the login form in the loginPage
method to make it request this loginGuideDoLogin
action URL whenever its posted. We've already seen how to retrieve the URL of an action above. In this case, we'll do it like this: $e->Actions->getAction("loginGuideDoLogin")->request->buildUrl();
And this is how it looks when implemented in the form:
And here's how the doLogin
method looks:
Note we've used the Login::doLogin method to check the passed email and password. If the login failed, we show a simple error page. If it was successful, we redirect the user to the login home using Output::setResponse with a RESPONSE_REDIRECT_FOUND code.
To login with the example users in the Cherrycake documentation examples skeleton database, you can use the following email/password combinations:
Douglas Engelbart
Email:
doug@berkeley.edu
Password:
TheMotherOfAllDemos413
John Horton Conway
Email:
johnny@princeton.org
Password:
lavidaloca
Frank Abagnale
Email:
frank.abagnale@united.com
Password:
catch_me_?_you_can
Carl Sagan
Email:
carl@cosmos.org
Password:
palebluedot34
Richard Feynmann
Email:
ricky@mit.edu
Password:
137
Now, when you login with a correct email and password, you'll get redirected to the Login guide home, and the message You are logged in
will be shown.
What if we wanted to show the user name there? Something like You are logged in as <user name>
. Well, since the Login module does all the work of retrieving the logged user for you, as long as you have the Login module as a dependency in your modules, you'll be able to access the logged User
object at any time via $e->Login->user
. This is how we would modify the home
method in our example to include the user name:
Adding a logout button
Let's add a logout button now. First, we'll create a new action to perform the logout operation, we'll call it loginGuideLogout
, and it will be triggered with the /login-guide/logout
URL:
Now, just like we did before, we add a logout button in the home
method that will appear along the Your are logged in as ...
message. This time, to get the logout URL we use $e->Actions->getAction("loginGuideLogout")->request->buildUrl();
And now we implement the logout
method like this:
This calls the Login::logoutUser method and then redirects them to the login home page.
Encrypting user passwords
You're in charge of adding new users to your database and storing their credentials in the fields you've specified when creating your User class.
The Login module uses by default a very secure salted password hashing mechanism which implements a Password-Based Key Derivation Function method, a Key stretching algorithm. This method is compliant with the PBKDF2 test vectors specified in the RFC 6070, and is based on the implementation by Taylor Hornby from Defuse.ca.
To generate a password hash to be stored in the database, use the Login::encryptPassword method, like this:
Last updated