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