Creating a login on the frontend
Frontend login can be found in many WordPress websites, including small blogs. Usually, we place the login form in the sidebar of the website. In web applications, user interfaces are complex and different compared to normal websites. Hence, we are going to implement the full page login screen as we did with registration. First, we need to update our controller with another case for login as shown in the following code:
switch ( $control_action ) { // Other cases case 'login': do_action( 'wpwa_login_user' ); break; }
This action will be executed once the user enters /user/login
in the browser URL to display the login form. The design form for login will be located in the templates
directory as a separate template named login.php
. Here is the implementation of the login form design with the necessary error messages:
<?php get_header(); ?> <div id='custom_panel'> <?php if (count($errors) > 0) { foreach ($errors as $error) { echo "<p class='frm_error'>$error</p>"; } } if( isset( $success_message ) && $success_message != ""){ echo "<p class='frm_success'>$success_message</p>"; } ?> <form method='post' action='<?php echo site_url(); ?>/user/login' id='login_form' name='login_form'> <ul> <li> <label class='frm_label' for='username'>Username</label> <input class='frm_field' type='text' name='username' value='<?php echo isset( $username ) ? $username : ''; ?>' /> </li> <li> <label class='frm_label' for='password'>Password</label> <input class='frm_field' type='password' name='password' /> </li> <li> <label class='frm_label' > </label> <input type='submit' name='submit' value='Login' /> </li> </ul> </form> </div> <?php get_footer(); ?>
Similar to the registration template, we have the header, error messages, HTML form, and footer in this template. We have to point the action of this form to /user/login
. The remaining code is self-explanatory, and hence I am not going to give detailed explanations. You can take a look at the preview of our login screen with the following screenshot:
Next, we need to implement the form submission handler for login functionality. Before that, we need to update our plugin constructor with the following code to define another custom action for login:
add_action( 'wpwa_login_user', array( $this, 'login_user' ) );
Once the user requests /user/login
from the browser, the controller will execute the do_action( 'wpwa_login_user' )
function to load the login form on the frontend.
Displaying a login form
We are going to use the same function to handle both template inclusion and form submission for login, as we did earlier with registration. So, let's look at the initial code of the login_user
function for including the template:
public function login_user() { if ( !is_user_logged_in() ) { include dirname(__FILE__) . '/templates/login.php'; } else { wp_redirect(home_url()); } exit; }
First, we need to check whether a user has already logged in to the system. Based on the result, we redirect the user to the login template or home page for the moment. Once the whole system is implemented, we will be redirecting the logged-in users to their own admin area.
Now we can take a look at the implementation of the login to finalize our process. Let's take a look at the form submission handling part of the login_user
function:
if ( $_POST ) { $errors = array(); $username = isset ( $_POST['username'] ) ? $_POST['username'] : ''; $password = isset ( $_POST['password'] ) ? $_POST['password'] : ''; if ( empty( $username ) ) array_push( $errors, 'Please enter a username.' ); if ( empty( $password ) ) array_push( $errors, 'Please enter password.' ); if(count($errors) > 0){ include dirname(__FILE__) . '/templates/login.php'; exit; } $credentials = array(); $credentials['user_login'] = $username; $credentials['user_login'] = sanitize_user( $credentials['user_login'] ); $credentials['user_password'] = $password; $credentials['remember'] = false; // Rest of the code }
As usual, we need to validate the post data and generate necessary errors to be shown on the frontend. Once validations are successfully completed, we assign all the form data into an array after sanitizing the values. The username and password are contained in the credentials
array with the user_login
and user_password
keys. Remember that the key defines whether to remember the password or not. Since we don't have a remember checkbox in our form, it will be set to false
. Next, we need to execute the WordPress login function in order to log the user into the system as shown in the following code:
$user = wp_signon( $credentials, false ); if ( is_wp_error( $user ) ) array_push( $errors, $user->get_error_message() ); else wp_redirect( home_url() );
WordPress handles user authentication through the wp_signon
function. We have to pass all the credentials generated in the previous code with an additional second parameter of true
or false
to define whether to use a secure cookie. We can set it to false
for this example. The wp_signon
function will return an object of the WP_User
or WP_Error
class based on the result. Once a user is successfully authenticated, redirection will be made to the home page of the site. Now we should have the ability to authenticate users from the login form on the frontend.
Do you think we implemented the process properly? Take a moment to think carefully about our requirements and try to figure out what we have missed.
Actually, we didn't check the activation status on login. Therefore, any user will be able to log in to the system without activating their account. Now let's fix this issue by intercepting the authentication process with another built-in action named authenticate
, as shown in the following code:
public function authenticate_user( $user, $username, $password ) { if ( !in_array( 'administrator', (array) $user->roles ) ) { $active_status = ''; $active_status = get_user_meta( $user->data->ID, 'activation_status', true ); if ( 'inactive' == $active_status ) { $user = new WP_Error( 'denied', __('<strong>ERROR</strong>: Please activate your account.' ) ); } } return $user; }
This function will be called in the authentication action by passing the user
object, username
, and password
as default parameters. All the user types of our application need to be activated except for the administrator accounts. Therefore, we check the roles of the authenticated user to figure out whether he/she is the admin. Then, we can check the activation status of other user types before authenticating. In case the authenticated user is in inactive status, we can return the WP_Error
object and prevent authentication from being successful.
Last but not least, we have to include the authenticate action in the controller as shown in the following code to make it work:
add_filter( 'authenticate', array( $this, 'authenticate_user' ), 30, 3 );
Now, we have a simple and useful user registration and login system ready to be implemented on the frontend of web applications. Make sure to check login and registration-related plugins from the official repository to gain knowledge of complex requirements in real-world scenarios.