You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Matisse Enzer <me...@apple.com> on 2011/05/28 21:10:14 UTC

PerlAuthenHandler returns HTTP_UNAUTHORIZED (401) but Apache sends REDIRECT (302) and drops Set-Cookie and WWW-Authenticate header

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-Cookie and WWW-Authenticate header

Posted by Matisse Enzer <me...@apple.com>.
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
> 
> 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 has
>     * a leading '"', so the URL code, here, is triggered on its absence
>     */
> 
>    if (custom_response && custom_response[0] != '"') {
> 
>        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 = HTTP_MOVED_TEMPORARILY;
>            apr_table_setn(r->headers_out, "Location", custom_response);
>        }
>        else if (custom_response[0] == '/') {
> [...]
>            r->method_number = M_GET;
>            ap_internal_redirect(custom_response, r);
>            return;
> 
> I think you want to enter the "else if" branch.
> 
> Further, make sure the document that is redirected to ends in a
> Apache2::Const::OK.
> 
> Torsten Förtsch
> 
> -- 
> Need professional modperl support? Hire me! (http://foertsch.name)
> 
> Like fantasy? http://kabatinte.net


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

Posted by Torsten Förtsch <to...@gmx.net>.
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 has
     * a leading '"', so the URL code, here, is triggered on its absence
     */

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

        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 = HTTP_MOVED_TEMPORARILY;
            apr_table_setn(r->headers_out, "Location", custom_response);
        }
        else if (custom_response[0] == '/') {
[...]
            r->method_number = M_GET;
            ap_internal_redirect(custom_response, r);
            return;

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

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

Torsten Förtsch

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

Like fantasy? http://kabatinte.net