Page 1 of 1

header('Location: ') problems

Posted: Fri Aug 31, 2007 10:52 am
by davisaggie
I am building an authentication module (code is below) and need some help getting header('Location: ') to work.

The goal for this module is to have login forms on different subdomains all use the same authentication module. If the authentication succeeds, the user will be directed to an appropriate protected section, otherwise they will be sent back to the login page they came from.

Problem 1:

header("Location: ".$_SERVER['REMOTE_ADDR']); results in a 404 error.

Is there a better way to redirect someone to the page they came from?

Problem 2:
After a successful login attempt has been made I generate a new session id for the person and store some information in the session variables, then use a switch statement to redirect the user to the correct page. At the next page for right now all I try to do is print out the information stored in the session array, but there does not seem to be anything there.

how can I propagate the session information using header('Location: admin/index.php'); for example?


Thanks.

Here's the code:

Code: Select all

<?php 
require_once('details.php');
require_once("../phpclass/securesession.class.php");
$clean_user = '';
$clean_pass = '';
session_start();
mysql_connect( "localhost", USER, PASS) or die("Cannot connect to MySQL Server");
mysql_select_db(DBNAME) or die("Cannot select database ".mysql_error());

$clean_user = mysql_real_escape_string($_POST['userid']);
$clean_pass = mysql_real_escape_string($_POST['pass']);

$user_query = '';
$user_query = "Select UserNum, UserID, Email, First, Last, Type, Location From user_auth ".
              "where UserID = '$clean_user' And Password = password('$pass')";
$user_result = '';
$user_result = mysql_query($user_query);
if (!$user_result){ 
	die("<br><b> $PHP_SELF </b>: ".mysql_error());}
else if (!mysql_num_rows($user_result)>0) {
	$_POST['login_failed'] = true;
	header("Location: ".$_SERVER['REMOTE_ADDR']);
}
else{
 	$ss = new SecureSession();
    $ss->check_browser = true;
    $ss->check_ip_blocks = 2;
    $ss->secure_word = 'SALT_';
    $ss->regenerate_id = true;
    $ss->Open();
    $_SESSION['logged_in'] = true;
	list($unum, $uid, $email, $first, $last, $type, $loc) = $user_result;
	$_SESSION['unum'] = $unum;
	$_SESSION['uid'] = $uid;
	$_SESSION['email'] = $email;
	$_SESSION['first'] = $first;
	$_SESSION['last'] = $last;
	$_SESSION['type'] = $type;
	$_SESSION['loc'] = $loc;
	switch($type){
		case 'GROWER':
		case 'grower':
		case 'Grower':	header('Location: grower/index.php');
			        break;
		case 'EDITOR':
		case 'editor':
		case 'Editor': header('Location: edit/index.php');
					   break;
		default: header('Location: auth/index.php');
                             break;		
	}
}
?>
The code on admin/index.php

Code: Select all

<h1> Welcome <?php echo($_SESSION['first'].' '.$_SESSION['last']); ?> </h1>

Posted: Fri Aug 31, 2007 10:58 am
by mcog_esteban
About
Problem2:
From http://pt2.php.net/manual/en/function.header.php
Note: Session ID is not passed with Location header even if session.use_trans_sid is enabled. It must by passed manually using SID constant.

Posted: Fri Aug 31, 2007 11:02 am
by onion2k
Regarding problem #1 - $_SERVER['REMOTE_ADDR'] is the user's IP address. I think you want $_SERVER['HTTP_REFERER']. Except you don't because that won't work all the time because it's optional whether the user's browser sends it.

Posted: Fri Aug 31, 2007 11:11 am
by timvw
davisaggie wrote: The goal for this module is to have login forms on different subdomains all use the same authentication module. If the authentication succeeds, the user will be directed to an appropriate protected section, otherwise they will be sent back to the login page they came from.
header("Location: ".$_SERVER['REMOTE_ADDR']); results in a 404 error.
You're not redirecting them to the page they came from at all. You're redirecting them to the machine (their own pc or a proxy) that made the request...

In most common implementations i've seen of such a 'common authentication service' pass in a variable (post/get) with the name 'return_success' and 'return_failure'. Depending on the result of the authentication they are then redirected to one of these two values...
davisaggie wrote: Problem 2: After a successful login attempt has been made I generate a new session id for the person and store some information in the session variables, then use a switch statement to redirect the user to the correct page. At the next page for right now all I try to do is print out the information stored in the session array, but there does not seem to be anything there.
It's not entirely clear how you determine the validation was succesful at the 'authentication service' to start with? The authentication service should probably add a 'token' to the return_success url. Then the code at return_success should verifiy if this token was really issued by the 'authentication service'. And then you can regenerate the session_id and do whatever you like more... (In this setup the 'authorzation service' is not required to be in the same domain as the depending services..)
$user_query = "Select UserNum, UserID, Email, First, Last, Type, Location From user_auth ".
"where UserID = '$clean_user' And Password = password('$pass')";
I believe you made a mistake here, should be $clean_pass ;)

Posted: Fri Aug 31, 2007 1:11 pm
by davisaggie
thanks for the tip about trying to redirect to $_SERVER['REMOTE_ADDR'] instead of $_SERVER['HTTP_REFERER']. That change fixed the first problem I was having.

reading through timvw's comments I see I didn't post the most current version of my module... oops :oops: it is below. I do plan on using some of timvw's suggestions in the future, but for now I am just trying to get the basic functionality of my module working before some of the extra security features are added.
About
Problem2:
From http://pt2.php.net/manual/en/function.header.php
Note: Session ID is not passed with Location header even if session.use_trans_sid is enabled. It must by passed manually using SID constant.
I read through the documentation better about the header function but still have a couple questions....
1) would it be better to use http_redirect() instead?
2) What is an SID constant, and how would I pass it?

Code: Select all

<?php 
require_once('details.php');
require_once("../phpclass/securesession.class.php");
$clean_user = '';
$clean_pass = '';
session_start();
mysql_connect( "localhost", USER, PASS) or die("Cannot connect to MySQL Server");
mysql_select_db(DBNAME) or die("Cannot select database ".mysql_error());

$clean_user = mysql_real_escape_string($_POST['userid']);
$clean_pass = mysql_real_escape_string(trim($_POST['pass']));

$user_query = '';
$user_query = "Select UserNum, UserID, Email, First, Last, Type, Location From user_auth ".
              "where UserID = '$clean_user' And Password = md5('$clean_pass')";
$user_result = '';
$user_result = mysql_query($user_query);
if (!$user_result){ 
	die("<br><b> $PHP_SELF </b>: ".mysql_error());}
else if (!mysql_num_rows($user_result)>0) {
	$_POST['login_failed'] = true;
	header("Location: ".$_SERVER['HTTP_REFERER']);
}
else{
 	$ss = new SecureSession();
    $ss->check_browser = true;
    $ss->check_ip_blocks = 2;
    $ss->secure_word = 'SALT_';
    $ss->regenerate_id = true;
    $ss->Open();
    $_SESSION['logged_in'] = true;
    list($unum, $uid, $email, $first, $last, $type, $loc) = mysql_fetch_row($user_result);
    /*die('uid: '.$uid.'</br>'.'name: '.$first.' '.$last.'</br>'.'type: '.$type);*/
	$_SESSION['unum'] = $unum;
	$_SESSION['uid'] = $uid;
	$_SESSION['email'] = $email;
	$_SESSION['first'] = $first;
	$_SESSION['last'] = $last;
	$_SESSION['type'] = $type;
	$_SESSION['loc'] = $loc;
	switch($type){
		case 'GROWER':  header('Location: grower/index.php'); break;
		case 'grower':  header('Location: grower/index.php'); break;
		case 'Grower':	header('Location: grower/index.php');
			        break;
		case 'EDITOR':
		case 'editor':
		case 'Editor': header('Location: edit/index.php');
					   break;
		default: header('Location: admin/index.php');	
	}
}
?>

Posted: Fri Aug 31, 2007 4:32 pm
by davisaggie
Never mind question 2, I figured out about SID and how to send them. I still would like to know if using

http_redirect()

is better then

header('Location: ')

thanks,
Mike

Posted: Sat Sep 01, 2007 3:28 am
by timvw
http_redirect make it easier to do it right...

(Where your use of the location-header is not compliant, since you use relative urls, and yes we've seen postings about browsers that had/have problems with that....)

Posted: Sat Sep 01, 2007 5:24 am
by Kieran Huggins
http_redirect() is in a PECL extension, whereas header() is part of the core.

I would go with header() every time since you can count on it being there. Besides, it's not that different anyway.

Posted: Sat Sep 01, 2007 11:33 am
by timvw
I forgot to mention a thing... Use session_write_close if you depend on session variables being set before you issue the header ;)