Yohan Blake Yohan Blake - 1 year ago 82
PHP Question

Using wordpress authentication while checking is user is an administrator

I am trying to use wordpress authentication for an admin site I am creating using PHP. I only want users with the role Administrator to be able to login to this site. This is what I have:

if ( in_array( 'administrator', (array) $user->roles ) ) {
echo "<script type='text/javascript'>alert('User is an admin!')</script>";
if( !wp_authenticate($user, $pass) ){
echo "<script type='text/javascript'>alert('Wrong password!')</script>";
}elseif(!wp_authenticate($user, $pass) ){
echo "<script type='text/javascript'>alert('Correct password!')</script>";
echo "<script type='text/javascript'>alert('You're not an admin!')</script>";

And this is how I query the db to get the user ID:

$link = mysqli_connect($host, $username,$password ,$db );
$q1 = " SELECT ID FROM wp_users WHERE
$stmt = mysqli_prepare($link, $q1);

mysqli_stmt_bind_param($stmt, "s", $email);
mysqli_stmt_bind_result($stmt, $id);
//echo $id;
$user = get_userdata( $id );


I get the alert "User is an admin" and then it shows a blank page. What am I doing wrong?

Answer Source

First: This question is related to Check if user is an admin by username or email only

Second: the logic in your first block is very strange... this is what is should resemble

Use WordPress Login Workflow

You should always use the built in WordPress login form and authentication workflow. It is not that hard to use and rolling your own login page makes your application very insecure unless you do it exactly right

To use the default WordPress login flow, put something like this in your Dashboard's common PHP file

require_once 'path/to/wp-load.php';
// Before every page load
if ( ! is_user_logged_in() ) {
    // Not logged in at all... redirect to WP Login Page
    exit(); // Exit to be safe
} elseif ( ! in_array( 'administrator', wp_get_current_user()->roles ) ) {
    wp_logout(); // Destroy their login session
    wp_die('You must be an administrator'); // Die with a nice error page

Let me explain this workflow:

First we import wp-load.php. This is somewhat frowned upon as well and there might be a lighter way of doing this, but for now it should work well

Now, say a user loads https://example.com/my-admin/index.php, your common.php will first check if the user is logged in. If not then it will call auth_redirect() and exit which will redirect the user to https://example.com/wp-login.php?return_url=https%3A%2F%2Fexample.com%2Fmy-admin%2Findex.php

The user will login using the wp-login page and then they will be redirected back to https://example.com/my-admin/index.php, where your common.php will now recognize is_logged_in() as true... so we step to the next elseif where it will check if the user is an administrator. If not then it will kill their authentication session and fail with a wp_die We kill the auth session so that if they reload the page they will be brought back to the login page to enter credentials for an admin and not repeatedly shown the wp_die page, you can tweak this however you wish as this might not be the desired behavior (perhaps redirect to /wp-admin/... or provide a link in the wp_die for the regular /wp-admin/)

if they do have the Administrator role, then execution of the request will continue and the dashboard will be accessible.

Please note that for this to work you will need to have your dashboard running on the same domain as your WordPress install... or else the cookies won't transfer over.

Roll your own login page. This is bad practice

It is hard to do... this example doesn't include Nonces, honeypots, or any other security features that you will get with the standard login form (either with default core or from additional plugins)

// Your login.php page

// Really, no really, this should just be done with WordPress's default login page with an auth_redirect()
// Really this is not recommended, it's really bad practice, and much less secure
// You've been warned

// If they provided a username and password, then check them
if ( isset( $_POST['username'] ) && isset( $_POST['password'] ) ) {
  $username = $_POST['username']
  $username = $_POST['password']
  // Check the username and password with WordPress to see if they are for any user
  $user = wp_authenticate( $username, $password );
  $error = '';
  if ( is_a( $user, 'WP_User' ) ) {
      // Verify that the user is an admin
      if ( in_array( 'administrator', (array) $user->roles ) ) {
          // Redirect them to the dashboard
      } else {
          $error = "Correct password, but not an Admin : (";
  } else {
      $error = "Wrong password :(";
// The Login Page
  <title> My Login </title>
  <form action="login.php" method="POST">
    <?php if ( $error ): ?>
       <div class="error"><?php echo $error; ?></div>
    <?php endif; ?>
      <input type="text" name="username" placeholder="username" required />
      <input type="password" name="password" placeholder="password" required />

Before you load any other page besides your login page you should have this code

if ( ! is_user_logged_in() || ! in_array( 'administrator', wp_get_current_user()->roles ) ) {
// now you can do your stuff