B4J Question Set HTTP Request Header with HttpUtils2

JMB

Active Member
Licensed User
Longtime User
Hi there,

I am trying to secure a Web Service which currently has no security on it by using Basic HTTP Authentication and am a little bit confused as to how I would call the service in B4J.

I was reading the thread in the B4A section of the forum about setting headers, as per the title of this post.

Could I ask for a more complete example of how to set the headers for Basic HTTP Authentication? I am a little confused between using:

B4X:
job1.GetRequest.SetHeader()

and setting the username and password via Job.username and Job.password. If I do it that way, how do I then set the header?

Thank you for your help.

Jonathan
 

JMB

Active Member
Licensed User
Longtime User
Thanks Erel.

Does the HttpJob Library therefore take care of all the encoding required for transmitting the username and password as base64 encoded?

Jonathan
 
Upvote 0

JMB

Active Member
Licensed User
Longtime User
I have tried using this and don't seem to be getting anywhere.

Here is my code
B4X:
job1.Username = "admin"
job1.Password = "admin@123"
job1.PostString("http://www.***/authenticate1.php","")

When I call the page through a browser, it asks for the username and password as one would expect and logs in when the correct information is passed.

Using the same username and password in the code returns an Unauthorized error.

Any help would be gratefully appreciated.

Jonathan
 
Upvote 0

JMB

Active Member
Licensed User
Longtime User
My code on the php page looks like this:

B4X:
<?php

// Status flag:
$LoginSuccessful = false;

// Check username and password:
if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])){

    $Username = $_SERVER['PHP_AUTH_USER'];
    $Password = $_SERVER['PHP_AUTH_PW'];

    if ($Username == 'admin' && $Password == 'admin@123'){
        $LoginSuccessful = true;
    }
}

// Login passed successful?
if (!$LoginSuccessful){

    /*
    ** The user gets here if:
    **
    ** 1. The user entered incorrect login data (three times)
    **     --> User will see the error message from below
    **
    ** 2. Or the user requested the page for the first time
    **     --> Then the 401 headers apply and the "login box" will
    **         be shown
    */

    // The text inside the realm section will be visible for the
    // user in the login box
    header('WWW-Authenticate: Basic realm="Secret page"');
    header('HTTP/1.0 401 Unauthorized');

    print "Login failed!\n";

}
else {

    // The user entered the correct login data, put
    // your confidential data in here:

    print 'you reached the secret page!';
}

Is there something that I should be doing that I am missing in the PHP code?

JB
 
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
for my particular case i solved using this code:


B4X:
    Dim userPwd As String = "user:password"
  
    Dim su As StringUtils
    Dim byt() As Byte = userPwd.GetBytes("UTF8")
    Dim suUserPwd As String = su.EncodeBase64(byt)
  
    http.Download("http://IPToServer/firstPage/SecondPage")
    http.GetRequest.SetHeader("Authorization:","Basic "&suUserPwd)

Some insight:
-HTTP Autorization:
https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side

-Instead of Post i used Download that according to documentation is equal to a get.
-setHeader should be AFTER and not BEFORE the download call (it should be too for POST)
https://www.b4x.com/android/forum/threads/set-http-request-header-with-httputils2.39413/#content
 
Upvote 0

JMB

Active Member
Licensed User
Longtime User
Thank you Enrique. Your input is much appreciated.

I am still having no success.

Here is the code based on what you posted.

B4X:
    Dim userPwd As String = "user:password"
    Dim su As StringUtils
    Dim byt() As Byte = userPwd.GetBytes("UTF8")
    Dim suUserPwd As String = su.EncodeBase64(byt)
    job1.Download("http://IPToServer//authenticate2.php")
    job1.GetRequest.SetHeader("Authorization:","Basic " & suUserPwd)

and the code in the authenticate2.php file is

B4X:
<?php

// Status flag:
$LoginSuccessful = false;

// Check username and password:
if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])){

    $Username = $_SERVER['PHP_AUTH_USER'];
    $Password = $_SERVER['PHP_AUTH_PW'];

    if ($Username == 'user' && $Password == 'password'){
        $LoginSuccessful = true;
    }
}

// Login passed successful?
if (!$LoginSuccessful){
    header('WWW-Authenticate: Basic realm="Secret page"');
    header('HTTP/1.0 401 Unauthorized');

    print "Login failed!\n";

}
else {

    print 'You reached the secret page!';
}

and it still won't work.

I also tried

B4X:
    job1.Username = "user"
    job1.Password = "password"
    job1.PostString("http://IPOfServer/authenticate2.php","")

And that doesn't work either.

No idea what I am doing wrong, as I managed to get Erel's site working using:

B4X:
    job2.Username = "xxx"
    job2.Password = "xxx"
    job2.PostString("http://www.b4x.com/android/vv18/print.php", "a=b")

:(
 
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Upvote 0

JMB

Active Member
Licensed User
Longtime User
This is what I get back...

Waiting for debugger to connect...
Program started.
User-Agent: okhttp/3.5.0
Accept-Encoding: gzip
Connection: close
Host: www.********.co.uk
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
Login failed!
JobName = Job1, Success = false
Error: Unauthorized
 
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
and for the other side? i mean the php side, what are the values that Echo is logging?

My inquiry is that even when you already have the user and password send to the server your php code is not visualizing it.
 
Upvote 0

JMB

Active Member
Licensed User
Longtime User
Thanks for your continued help with this.

I contacted my Host provider as there appear to be problems with passing authorisation information with servers that are CGI/FastCGI enabled.

They set up a script on my host as follows:
B4X:
<?php$_h = getallheaders();print_r($_h);print_r($_SERVER);?>
I got this back from them after running that code:
B4X:
[REDIRECT_STATUS] => 200 
[REDIRECT_HANDLER] => hs-php55-script 
[REDIRECT_HTTP_AUTHORIZATION] =>

And his comment was this:

"You can see the HTTP_AUTHORIZATION / AUTHORIZATION header is passed in $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] due to the nature of FastCGI PHP required under shared hosting."

Does that mean that a different header has to be passed to the page?

JMB
 
Upvote 0

JMB

Active Member
Licensed User
Longtime User
I am communicating with my host provider to try and figure out why username and password don't seem to be getting to my authentication page

Even sending them using a simple PHP script doesn't work.

Weird.
 
Upvote 0

JMB

Active Member
Licensed User
Longtime User
Ok, I have managed to sort this out. It was due to the fact that REDIRECT_HTTP_AUTHORIZATION is being used on the host. This is connected to shared hosting with FastCGI PHP.

Here is the code that finally gave success:

B4X:
<?php

if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches)) {
  
    list($name, $password) = explode(':', base64_decode($matches[1]));
    $_SERVER['PHP_AUTH_USER'] = strip_tags($name);
    $_SERVER['PHP_AUTH_PW'] = strip_tags($password);
}

// Status flag:
$LoginSuccessful = false;

// Check username and password:
if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])){
    $Username = $_SERVER['PHP_AUTH_USER'];
    $Password = $_SERVER['PHP_AUTH_PW'];

    if ($Username == 'user' && $Password == 'pass'){
        $LoginSuccessful = true;
    }
}

// Login passed successful?
if (!$LoginSuccessful){

    header('WWW-Authenticate: Basic realm="Secret page"');
    header('HTTP/1.0 401 Unauthorized');

    print "Login unsuccessful";
}
else {

     // Correct login data received
    print 'Login successful';
}
?>
and here is a test php script to check that it works:
B4X:
<?php

$username  = "user";
$password = "pass";

$url = "http://www.*******/authenticate.php";

$context = stream_context_create(array(
    'http' => array(
        'header'  => "Authorization: Basic " . base64_encode("$username:$password")
    )
));
$data = file_get_contents($url, false, $context);
print_r($data);
?>

Hope this helps someone.

Thanks very much for your help, Enrique.

JMB
 
Last edited:
Upvote 0
Top