PerlAuthenHandler returns HTTP_UNAUTHORIZED (401) but Apache sendsREDIRECT (302) and drops Set-Cooki

PerlAuthenHandler returns HTTP_UNAUTHORIZED (401) but Apache sendsREDIRECT (302) and drops Set-Cooki

am 28.05.2011 21:10:14 von Matisse Enzer

Using Apache/2.2.17 mod_perl/2.0.5.

We have a PerlAuthenHandler that (on failure to authenticate) sets two headers ('Set-Cookie' and 'WWW-Authenticate' and returns HTTP_UNAUTHORIZED. We also use $r->custom_response to set a URL as the response body.

What I expect Apache to send to the client is something like this:

HTTP/1.1 401 Authorization Required
Date: Sat, 28 May 2011 16:30:58 GMT
Server: Apache/2.2.17 (Unix) PHP/5.3.4
WWW-Authenticate: MySpecialAuthMethod
Content-Type: text/html; charset=iso-8859-1
Content-Language: en

with a response a body containing a URL that was set with $r->custom_response (see example below.)

But: The response that Apache actually sends is a 302, without the 'Set-Cookie' or 'WWW-Authenticate' headers.

Does setting a URL as the string (second argument) to custom_response force Apache to turn the response into a 302 redirect?


Here is an example of the authenticate subroutine I am using?



use Apache2::Const qw(:common :http :log);
sub authenticate {
my ($r) = @_;

my $handler = _load_handler($r);
return SERVER_ERROR unless blessed $handler;

my $auth_status
= $handler->validateCookieWithFunction( $handler->validatorFunctions );

if ( _status_is_success($auth_status) ) {
return OK;
}

# Everything works fine up to this point.


if ( $handler->shouldClearCookie($auth_status) ) {
my $empty_cookie = $handler->cookieWithNoValueAndExpiresNow();
$r->err_headers_out->add( 'Set-Cookie' => $empty_cookie );
$r->err_headers_out->add( 'WWW-Authenticate' => 'MySpecialAuthMethod' );
$r->log->warn(
"authenticate: Setting/clearing cookie: '$empty_cookie'");
}

my $uri = URI->new( $handler->getAuthURL );
$uri->query_form(
myKey => $handler->getMyKey,
path => $r->unparsed_uri,
);

$handler->DESTROY;

$r->log->warn(
"authenticate: No AuthCookie found. Returning HTTP_UNAUTHORIZED with response body: '$uri'"
);

$r->custom_response( HTTP_UNAUTHORIZED, $uri );
return HTTP_UNAUTHORIZED
}

# Apache actually returns a 302 with a Location: header of the $uri created above.
# The response does NOT have the two headers we created: 'Set-Cookie' nor 'WWW-Authenticate'

Re: PerlAuthenHandler returns HTTP_UNAUTHORIZED (401) but Apache sends REDIRECT (302) and drops Set-

am 28.05.2011 23:31:17 von torsten.foertsch

On Saturday, May 28, 2011 21:10:14 Matisse Enzer wrote:
> $r->custom_response( HTTP_UNAUTHORIZED, $uri );
> return HTTP_UNAUTHORIZED

Make sure $uri does not contain the hostport part. It must start with a
slash. The next lines are from modules/http/http_request.c:

/*
* Two types of custom redirects --- plain text, and URLs. Plain text h=
as
* a leading '"', so the URL code, here, is triggered on its absence
*/

if (custom_response && custom_response[0] !=3D '"') {

if (ap_is_url(custom_response)) {
/*
* The URL isn't local, so lets drop through the rest of this
* apache code, and continue with the usual REDIRECT handler.
* But note that the client will ultimately see the wrong
* status...
*/
r->status =3D HTTP_MOVED_TEMPORARILY;
apr_table_setn(r->headers_out, "Location", custom_response);
}
else if (custom_response[0] == '/') {
[...]
r->method_number =3D M_GET;
ap_internal_redirect(custom_response, r);
return;

I think you want to enter the "else if" branch.

=46urther, make sure the document that is redirected to ends in a
Apache2::Const::OK.

Torsten Förtsch

=2D-=20
Need professional modperl support? Hire me! (http://foertsch.name)

Like fantasy? http://kabatinte.net

Re: PerlAuthenHandler returns HTTP_UNAUTHORIZED (401) but Apache sendsREDIRECT (302) and drops Set-C

am 29.05.2011 00:10:03 von Matisse Enzer

Ahh, very interesting.

I actually did want to use a full url with scheme and host.

What we wanted was a response of type HTTP_UNAUTHORIZED with a Location =
header as well as the other headers I added.

But, perhaps that's not a reasonable thing to want, and we can provide a =
URI to a page on the same server.

-M

On May 28, 2011, at 2:31 PM, Torsten Förtsch wrote:

> On Saturday, May 28, 2011 21:10:14 Matisse Enzer wrote:
>> $r->custom_response( HTTP_UNAUTHORIZED, $uri );
>> return HTTP_UNAUTHORIZED
>=20
> Make sure $uri does not contain the hostport part. It must start with =
a
> slash. The next lines are from modules/http/http_request.c:
>=20
> /*
> * Two types of custom redirects --- plain text, and URLs. Plain =
text has
> * a leading '"', so the URL code, here, is triggered on its =
absence
> */
>=20
> if (custom_response && custom_response[0] !=3D '"') {
>=20
> if (ap_is_url(custom_response)) {
> /*
> * The URL isn't local, so lets drop through the rest of =
this
> * apache code, and continue with the usual REDIRECT =
handler.
> * But note that the client will ultimately see the wrong
> * status...
> */
> r->status =3D HTTP_MOVED_TEMPORARILY;
> apr_table_setn(r->headers_out, "Location", =
custom_response);
> }
> else if (custom_response[0] == '/') {
> [...]
> r->method_number =3D M_GET;
> ap_internal_redirect(custom_response, r);
> return;
>=20
> I think you want to enter the "else if" branch.
>=20
> Further, make sure the document that is redirected to ends in a
> Apache2::Const::OK.
>=20
> Torsten Förtsch
>=20
> --=20
> Need professional modperl support? Hire me! (http://foertsch.name)
>=20
> Like fantasy? http://kabatinte.net