php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75272 Status code is always forced to 401 when setting the WWW-Authenticate header
Submitted: 2017-09-28 05:57 UTC Modified: 2021-03-04 12:51 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: ramsey@php.net Assigned:
Status: Suspended Package: *Web Server problem
PHP Version: master-Git-2017-09-28 (Git) OS:
Private report: No CVE-ID: None
 [2017-09-28 05:57 UTC] ramsey@php.net
Description:
------------
When attempting to implement Bearer tokens[1] for OAuth 2, I discovered an issue where PHP is always forcing the HTTP response status code to 401 when setting the WWW-Authenticate header. As a result, I am unable to follow the Bearer token RFC or the HTTP Authentication RFC[2].

In RFC 6750, section 3 states:

> If the protected resource request does not include authentication
> credentials or does not contain an access token that enables access
> to the protected resource, the resource server MUST include the HTTP
> "WWW-Authenticate" response header field; it MAY include it in
> response to other conditions as well.

It goes on to describe conditions that would result in 401, 403, and other 4xx responses, each of which may include a WWW-Authenticate header.

In RFC 7235, section 4.1 states:

> A server generating a 401 (Unauthorized) response MUST send a
> WWW-Authenticate header field containing at least one challenge.  A
> server MAY generate a WWW-Authenticate header field in other response
> messages to indicate that supplying credentials (or different
> credentials) might affect the response.

Admittedly, earlier RFCs (2616 and 2617) were ambiguous on this point, leading many implementations to force WWW-Authenticate to 401 responses only, and it appears PHP is one of these cases.

In main/SAPI.c[3], around lines 829-830, we see the following:

    } else if (!strcasecmp(header_line, "WWW-Authenticate")) {
        sapi_update_response_code(401);

I think these are the lines that force all responses setting WWW-Authenticate header to have the 401 status code.



[1]: https://tools.ietf.org/html/rfc6750
[2]: https://tools.ietf.org/html/rfc7235
[3]: https://github.com/php/php-src/blob/a51cb393b1accc29200e8f57ef867a6a47b2564f/main/SAPI.c#L829-L830


Test script:
---------------
<?php
header('HTTP/1.1 403 Forbidden');
header('WWW-Authenticate: Bearer realm="Foo"');

Expected result:
----------------
HTTP/1.1 403 Forbidden
Connection: close
Content-type: text/html; charset=UTF-8
Date: Thu, 28 Sep 2017 05:55:32 +0000
Host: localhost:8000
WWW-Authenticate: Bearer realm="Foo"
X-Powered-By: PHP/7.1.3

Actual result:
--------------
HTTP/1.1 401 Unauthorized
Connection: close
Content-type: text/html; charset=UTF-8
Date: Thu, 28 Sep 2017 05:55:32 +0000
Host: localhost:8000
WWW-Authenticate: Bearer realm="Foo"
X-Powered-By: PHP/7.1.3

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-09-28 06:29 UTC] mike@php.net
-Summary: Status code is always forced to 401 when setting the WWW-Authenticate header +Summary: Random memory corruption with strings -Operating System: +Operating System: Debian Jessie -PHP Version: master-Git-2017-09-28 (Git) +PHP Version: 7.0.0
 [2017-09-28 06:29 UTC] mike@php.net
Workaround:

header("WWW-Authenticate: ...", true, 403);

or setting the response code after the header.

I agree, though, that it might be an option to change the default behavior to check whether another response code has already been set (IIRC just like we already do for 30X response codes).
 [2017-09-28 06:34 UTC] mike@php.net
-Summary: Random memory corruption with strings +Summary: Status code is always forced to 401 when setting the WWW-Authenticate header -Operating System: Debian Jessie +Operating System: -PHP Version: 7.0.0 +PHP Version: master-Git-2017-09-28 (Git)
 [2017-09-28 06:34 UTC] mike@php.net
Dammit, FF autofill gone mad, sorry.
 [2017-09-28 18:01 UTC] ramsey@php.net
Tests for expected behavior related to this issue have been added in this pull request: https://github.com/php/php-src/pull/2787
 [2021-03-04 12:51 UTC] cmb@php.net
-Status: Open +Status: Suspended
 [2021-03-04 12:51 UTC] cmb@php.net
According to comments in the PR, changing this would need an RFC.
So anybody who is interested in this change, please pursue the RFC
process[1].  For the time being, I'm suspending this ticket.

[1] <https://wiki.php.net/rfc/howto>
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 06:01:30 2024 UTC