Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations John Tel on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Use header to auto-login (Basic HTTP Authentication) 1

Status
Not open for further replies.

Stretchwickster

Programmer
Apr 30, 2001
1,746
GB
I have a site which is password-protected via Basic HTTP Authentication. I would like to add a menu option in my Windows desktop application which automatically logs in so that the user is not prompted for login credentials if using this route.

I therefore wondered if it's possible to send username and password using the header function in a PHP script? I know it is possible to build the username and password into the URL but IE closed this route for security reasons.

Any advice would be much appreciated.

Clive
Runner_1Revised.gif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer." (Paul Ehrlich)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
Ok, I've found a way of doing this using cURL:
Code:
  // start the process
  $curl = curl_init($url);
  
  // tell cURL to fail if an error occurs
  curl_setopt($curl, CURLOPT_FAILONERROR, 1);
  // assign the returned data to a variable
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  // use POST
  curl_setopt($curl, CURLOPT_POST, 1);
  // specify a username and password for HTTP Authentication
  curl_setopt($curl, CURLOPT_USERPWD, 'username:password');
  
  // execute the transaction
  $r = curl_exec($curl);
  // close the connection
  curl_close($curl);
  
  // print the response
  echo $r;

Unfortunately, if from the resulting webpage I then navigate to another page using the site's main navigation, the HTTP Authentication prompt appears. Is there any way to mimic the behaviour of remaining logged in whilst the browser is open?

Clive
Runner_1Revised.gif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer." (Paul Ehrlich)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
try adding the
CURLOPT_UNRESTRICTED_AUTH
and
CURLOPT_FOLLOWLOCATION
directives. there could be some redirects mucking things up.
 
Thanks for the suggestions jpadie, but the problem still persists even with those options set.

Clive
Runner_1Revised.gif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer." (Paul Ehrlich)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
if you use a browser to visit the site, and look at the headers returned etc, can you see what is happening? is it that the clicked link is in another subdomain or something? if so you may be able to solve the problem by storing passwords and usernames in a .netrc file.
 
I've tried using "Live HTTP Headers" in Firefox, but all I see is a GET request followed by a "200 OK" response.

I'm guessing that using CURLOPT_USERPWD doesn't simulate a user entering the same username/password in the HTTP Authentication dialog. It seems like it satisfies the authentication server-side and doesn't actually let the browser know the username/password combination that has been entered so, when the user navigates to another page (without passing through the script containing the cURL code above), the browser asks for login credentials because it doesn't realise any were initially specified.

Clive
Runner_1Revised.gif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer." (Paul Ehrlich)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
have you included the CURLOPT_HTTPAUTH option?
Code:
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
 
Yes, I've currently got:
Code:
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
...and I just tried your suggestion, but the problem persists.

Clive
Runner_1Revised.gif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer." (Paul Ehrlich)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
I'm afraid I'm not permitted to.

Clive
Runner_1Revised.gif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer." (Paul Ehrlich)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
on re-reading your post, i think that the approach may be wrong (apologies for the red herring)

if i understand correctly, the first get is done by cURL and the fed to the browser. subsequent gets are performed directly by the browser.

this won't work in the way that you want because the browser does not know the username and password to pass in.

work arounds might be:

1. rewrite the link urls to incude the user name and password; or
2. rewrite the link urls to pass them all back to your server to perform cURL requests each time. a sort of proxy for example.
 
Thanks for your suggestions.

Suggestion 1 is a non-starter because urls including username and password don't work on newer versions of IE (due to security restrictions) without fiddling with the user's registry.

I have briefly tried suggestion 2 but it seemed to be getting a little over-complicated. Currently, I am passing a GET parameter, with the $url var above, to indicate to the particular page that it has been executed via cURL and needs to use a different url for each link on its page. Is there a method that is easier to implement than this?

Clive
Runner_1Revised.gif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer." (Paul Ehrlich)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
Whilst suggestion 2 above will work, I think that I am very likely to create many broken links using this technique so I've decided to write my own PHP authentication which will enable me to have full control over the process.

Many thanks for your help jpadie.

Clive
Runner_1Revised.gif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer." (Paul Ehrlich)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
Thanks for the kind offer, but I'm going to go the PHP auth route because it will improve a number of aspects. Thanks for your input into this problem.

Clive
Runner_1Revised.gif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer." (Paul Ehrlich)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
just for the sake of this post and future readers I will post a very simple (and crude) proxying system that I wrote last night. there are (many) imperfections: those to note particularly include:
1. the lack of support for rewriting url links in css declarations
2. the lack of support for imperfect href (etc) attributes: e.g. those missing the quotation marks etc.
3. i have never used a proxying system in anger before, and obviously never built one. there must surely be hundreds of layers of complexity that i have not catered for.

having said that, it does work...

Code:
<?php
$pathinfo = '';
handleRequest("[URL unfurl="true"]www.google.co.uk");[/URL]	//this is the default url for proxying

function rewriteLinks($output){
	//a VERY crude link rewriter
	$patterns = array (
		'/(<.*?href=)["\'](.*?)["\']/i',
		'/(<.*?action=)["\'](.*?)["\']/i',
		'/(<.*?src=)["\'](.*?)["\']/i');
	
	 
	foreach ($patterns as $pattern){
		$output = preg_replace_callback($pattern,'rewriteMe', $output);
	}
	return $output;
}

function rewriteMe($matches){
	//need the pathinfo to make partial links into absolute uri's
	//simpler to do it now than later
	global $pathinfo;
	$base = $pathinfo['scheme'].'://'.$pathinfo['host'];
	
	//$matches[2] contains the url and the query string
	//get rid of trailing spaces
	$encodeURL = trim($matches[2]);
	
	$curAddress = '[URL unfurl="true"]http://'.$_SERVER[/URL]['HTTP_HOST'].$_SERVER['PHP_SELF'];
	
	//test for absolute uri
	//and return an absolute version
	$lower = strtolower(substr($encodeURL, 0, 4));
	
	if ($lower === 'http'){
		return $matches[1]."\"$curAddress?proxy=$encodeURL\"";	
	} else {
		return $matches[1]."\"$curAddress?proxy=$base$encodeURL\"";	
	}
}

function parseIncomingProxyRequest($url=NULL){
	//this just returns the desired url
	
	if (isset($_GET['proxy'])){
		return (trim($_GET['proxy']));
	}else{
		return $url;
	}
}

function getPostVars(){
	//used to encode post variables and format them for the cURL request
	if ( count($_POST) >0 ){
		foreach ($_POST as $key=>$var){
			$return[] = urlencode(trim($key)) ."=" .urlencode(trim($var));
		}
	}
	if (empty($return)){
		return '';
	} else {
		return implode($return, '&');
	}
}

function handleRequest($url=NULL){
	//everything hangs from this function
	global $pathinfo;
	//get the url
	$url = parseIncomingProxyRequest($url);
	if (empty($url)){
		die ("no address to proxy");
	}
	//need the segmented url later
	$pathinfo = parse_url($url);
	//check for post
	$postData = getPostVars();
	//grab the page contents
	$pageContents = makeRequest($url, $postData);
	//rewrite the links
	$pageContents = rewriteLinks($pageContents, $pathinfo);
	//bash it out to the user
	echo $pageContents;
}

function makeRequest($url, $postData=null){
	//star the cURL session
	$ch = curl_init($url);

	$cookiejar = "cookiejar.txt";
	$cookiefile = "cookies.txt";
	
	//set options
	curl_setopt($ch, CURLOPT_FAILONERROR, 1);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);	//into varaible
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);	//follow redirects
	curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);	//send user information in case needed
	curl_setopt($ch, CURLOPT_USERPWD, 'username:password'); //parameters
	
	if (!empty($postData)){							//check for post data.  if present switch method to post and attach the posted data
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDs, $postData);
	}
	
	//handle cookies and make a windows fix
	//from php manual.
	//only neeeded if the file addresses for the cookie files at the top of this function are changed

    if (substr(PHP_OS, 0, 3) == 'WIN'){
		$cookies = str_replace('\\','/', getcwd().'/'.$cookies);
		curl_setopt($ch, CURLOPT_CRLF, TRUE);	//convert for windows
	}
	//set the cookie options
	curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiejar);
	curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile);
    

	//make the request
	$r = curl_exec($ch);
	
	//close the cURL instance
	curl_close($ch);
	
	//return the incoming web page
	return $r;
}
?>
 
I haven't tried it, but that looks fantastic - is Tek-Tips your full-time job?!! ;-)

Clive
Runner_1Revised.gif

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"To err is human, but to really foul things up you need a computer." (Paul Ehrlich)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the best answers from this forum see: faq102-5096
 
I wish it were. I work alone in rural France so Tek-Tips is like the coffee machine/water cooler for me. It's where i take "short breaks" from the law (my day job) and "interact" with other people (albeit asynchronously!). Occasionally I talk to the rabbits eating my lawn, just for a change ;-)

actually, i find the disciplines of coding and legal drafting very similar: it's all a logic flow of conditionals, statements/obligations and abstractions/definitions. switching out of law into coding for 20 minutes every now and then often helps unlock a knotty problem in the drafting. It is easy to write any old thing in a contract, and 99 times out of a hundred, it will work. What's difficult is getting the point down succinctly and elegantly. I feel the same way about coding.

sorry about the diatribe!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top