Community Documentation

Redirecting anonymous users to the login page on Access Denied

Last updated December 7, 2007. Created by karldied on April 24, 2006.
Edited by add1sun, pwolanin, mfredrickson. Log in to edit this page.

This shows how to redirect anonymous users to a sign up/login page when they came across access denied (error 403) pages by using a PHP page. You may also want to check the LoginToboggan module as well for another solution.

Process

  1. Create a node of type page. You must have the PHP input filter enabled.
  2. In the body of the page insert:
    <?php
    global $user;
    if (
    $user->uid) { // this user is already logged in
    print "Access Denied: You do not have access to this page.";
    } else {
    drupal_set_message("Access Denied: Please Login");
    $dest = drupal_get_destination();
    drupal_goto('user/login', $dest); // this remembers where the user is coming from
    }
    ?>
  3. Submit the node (you should see the "Access Denied: You do not have access to this page." message
  4. Remember this node's ID number
  5. Goto admin/settings
  6. In the section about alternate 403 error pages, insert "node/XXXX" where XXX is your node's ID number
  7. Test it

If you would prefer, you can use this alternate code to force a redirect to the login page after 10 seconds (instead of immediately).

<?php
global $user;
if (
$user->uid) { // this user is already logged in
print "Access Denied: You do not have access to this page.";
} else {
$dest = drupal_get_destination();
$url = "http://www.youdomain.com/user/login?destination=$dest"
drupal_set_html_head('<meta http-equiv="refresh" content="10;URL=' . $url . '">');
}
?>

Comments

This didn't work for me

This didn't work for me because it creates an infinite loop of redirects when an anonymous user tries to go to a page like /node/add/blog. Instead I followed http://drupal.org/node/69007#comment-637218

You helped me!!

You helped me, Thanks alot!

This works fine in 5.1.2

This worked fine
sharma chelluri

Solution for drupal 5.x

I had troubles to use this code with drupal 5...
Here is the solution I used :

<?php global $user;  if ($user->uid == 0) {
  print
"TO ACCESS THIS PAGE, PLEASE LOG-IN";
 
drupal_get_destination();
 
$block = module_invoke('user', 'block', 'view', 0);
  print
$block['content'];
} else {
  print
"You don't have access to this page";
}
?>

this part is used to print the login block:

  $block = module_invoke('user', 'block', 'view', 0);
  print $block['content'];

-P-

typo

There's a missing ";" on:
$url = "http://www.youdomain.com/user/login?destination=$dest"

and $dest already contains the string "destination=" :)

tiny module version

Add the following to a custom module, replacing MODULENAME with the name of the module and DRUPALPATH with the drupal path you want people directed to. If you want to set different paths depending on the $user, then just add if/then statement to the page callback function (MODULENAME_403_redirect) to send different users to different pages.

For this to work, you have to set the 403 page under Administer > Site Configuration > Error Reporting

function MODULENAME_menu() {
  $items['403redirect'] = array(
    'page callback' => 'MODULENAME_403_redirect',
    'access callback' => 'MODULENAME_403_access',
    'type' => MENU_CALLBACK,
  );
  return $items;
}

function MODULENAME_403_redirect() {
  header('Location: '. url('DRUPALPATH', array('absolute' => TRUE)), TRUE, 302);
}

function MODULENAME_403_access() {
  return TRUE;
}

Preserving destinations, etc.

Building on that, you can preserve the destination and add some helpful conditional logic with something like this:

<?php
function MODULENAME_403_redirect() {
  global
$user;
 
 
//check for anonymous users
 
if ($user->uid == 0) {
   
$dest = $_REQUEST['destination'];
   
   
//checking for a redirect by drupal on logout to keep from setting a bogus "destination" parameter
   
if ($dest != variable_get('site_frontpage', 'node')){
     
header('Location: '. url("user", array('absolute' => TRUE, 'query' => 'destination=' . $dest)), TRUE, 302);
    }
   
   
//on logout, redirect back to login page
   
else {
     
header('Location: '. url("user", array('absolute' => TRUE)), TRUE, 302);
    }
  }
 
 
//user is already logged in so just give the standard error page content.
 
else {
   
drupal_set_title('403 Access Denied');
    return (
'You are not authorized to access this page.');
  }
}
?>

Also, just to be clear, you'll need to set the site's access denied page to whatever you list in the "page callback." :)

It worked for me. Thanks for

It worked for me. Thanks for the code !!

I like this version better

I like this version better than the other one I posted, it's the way open atrium handles it and I haven't had any problems with it.

<?php
/**
* Implementation of hook_menu()
*/
function MYMODULE_menu() {
 
$items = array();
 
$items['access-denied'] = array(
   
'title' => 'Access denied',
   
'page callback' => 'MYMODULE_403',
   
'page arguments' => array(),
   
'access callback' => TRUE,
   
'type' => MENU_CALLBACK,
  );
  return
$items;
}

function
MYMODULE_403() {
  global
$user;
  if (!
$user->uid && !user_access('access content')) {
   
// drupal_access_denied() sets the $_REQUEST['destination'] which will
    // prevent drupal_goto from behaving as expected. So we unset it.
   
unset($_REQUEST['destination']);
   
drupal_goto('user/login', 'destination='. $_REQUEST['q']);
  }
  else {
   
// Logged in user requests path like 'user/login?destination=dashboard' which
    // is a common case if user loses session but has 46 browser tabs open and
    // refreshes one such tab.  This will redirect that request properly to
    // avoid a 403.
   
if ($_REQUEST['q'] === 'user/login' && isset($_REQUEST['destination']) && $_REQUEST['destination'] !== 'user/login') {
     
drupal_goto($_REQUEST['q']);
    }
  }
  return
"<div class='access-denied'>". t('You are not authorized to access this page.') ."</div>";
}
?>

Also see the module...

Also see the module Redirect 403 to Login

Reference

Drupal’s online documentation is © 2000-2012 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License. Comments on documentation pages are used to improve content and then deleted.