? Pending

User tests: Successful: Unsuccessful:

avatar AndyGaskell
AndyGaskell
2 Oct 2020

This change makes the authorization header case insensitive.

In the IETF standsrds docs at https://tools.ietf.org/html/rfc2616#section-4.2 it states that "Field names are case-insensitive."

See issue...
Auth headers in Joomla 4 API should maybe be case insensitive #30871

This means, both...
curl --location --request GET 'http://MYDOMAIN//api/index.php/v1/content/article' --header 'Authorization: Bearer MY_API_TOKEN_HERE'
...and...
curl --location --request GET 'http://MYDOMAIN/api/index.php/v1/content/article' --header 'authorization: Bearer MY_API_TOKEN_HERE'
...both work.

Pull Request for Issue # .

Summary of Changes

This change makes the authorization header case insensitive in the API when using Bearer token.

Testing Instructions

  1. Set up a test site at http://localhost/joomla/joomla_4_beta_4

  2. Get a Joomla API Token, from, for example https://localhost/joomla/joomla_4_beta_4/administrator/index.php?option=com_users&view=users

  3. Do an uppercase test...
    curl --location --request GET 'http://MYDOMAIN//api/index.php/v1/content/article' --header 'Authorization: Bearer MY_API_TOKEN_HERE'

  4. Do a lowercases test...
    curl --location --request GET 'http://MYDOMAIN/api/index.php/v1/content/article' --header 'authorization: Bearer MY_API_TOKEN_HERE'

Actual result BEFORE applying this Pull Request

Uppercase test gets a good json response of article content
Lowercase gets an gets a 406 response

Expected result AFTER applying this Pull Request

Uppercase test gets a good json response of article content
Lowercase test gets a good json response of article content

Documentation Changes Required

None

avatar AndyGaskell AndyGaskell - open - 2 Oct 2020
avatar AndyGaskell AndyGaskell - change - 2 Oct 2020
Status New Pending
avatar joomla-cms-bot joomla-cms-bot - change - 2 Oct 2020
Category Front End Plugins
avatar AndyGaskell AndyGaskell - change - 2 Oct 2020
The description was changed
avatar AndyGaskell AndyGaskell - edited - 2 Oct 2020
avatar AndyGaskell
AndyGaskell - comment - 2 Oct 2020

I checked if it effects, Basic Auth in the same way...
https://github.com/joomla/joomla-cms/blob/4.0-dev/plugins/api-authentication/basic/basic.php
...but it does not, so that's good.

avatar AndyGaskell AndyGaskell - change - 2 Oct 2020
The description was changed
avatar AndyGaskell AndyGaskell - edited - 2 Oct 2020
avatar AndyGaskell AndyGaskell - change - 2 Oct 2020
The description was changed
avatar AndyGaskell AndyGaskell - edited - 2 Oct 2020
avatar AndyGaskell
AndyGaskell - comment - 2 Oct 2020

Not really related to the PR directly, but perhaps a comment for future google-ers.

In the most popular flutter http package, http.dart, see https://pub.dev/packages/http the headers are always passed in lowercase. So before this change, any flutter API client code using http.dart was not able to use the Joomla 4 API bearer API token option.

This is how I came across this, working on a basic example Flutter App at https://github.com/AndyGaskell/joomla4api_basic_flutter_app

avatar ceford
ceford - comment - 4 Oct 2020

There is a problem! For me the curl test works without the patch with both upper and lower case Authentication. Looking at the code, on line 91, $authHeader is not empty and so the case conversion is never called. But then on line 103 a header is compared with 'Bearer'.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/30882.

avatar zero-24
zero-24 - comment - 4 Oct 2020

Can you be a bit more specific? That was not changed by that patch so should be an issue before too right?

avatar zero-24
zero-24 - comment - 4 Oct 2020

Ah you mean line 103 that was not shown to my diff ;) https://github.com/joomla/joomla-cms/pull/30882/files#diff-cca9165cd01f0d3d0fa6b27485dab967L103

Can you take a look into that @AndyGaskell ?

avatar AndyGaskell
AndyGaskell - comment - 4 Oct 2020

Thanks @zero-24 and @ceford for reviewing the PR.

I'll look into this today.

@ceford could you please add some details of what web server set-up you have? I would guess $authHeader is getting set on line 87 when you run this, rather than on line 94 when I run this. I'm thinking perhaps this bug is only exhibited when authHeader is empty and apache2handleris used. Perhaps $this->app->input->server->get('HTTP_AUTHORIZATION', '', 'string'); gets the header values in a case insensitive way, so side-steps the problem.

My web-server set-up is...

  • phpversion: 7.4.3
  • server: Apache/2.4.41 (Ubuntu)
  • sapi_name: apache2handler

I'm just reading through the symphony issue mentioned in the code comment on line 90...
// Apache specific fixes. See https://github.com/symfony/symfony/issues/19693

avatar ceford
ceford - comment - 4 Oct 2020

I am working on a Macbook Pro. My settings:

PHP Version: 7.4.2
Web Server: Apache/2.4.41 (Unix) PHP/7.4.2
WebServer to PHP Interface: apache2handler
Joomla! Version: Joomla! 4.0.0-beta5-dev Development [ Mañana ] 15-September-2020 19:15 GMT

Is that enough?

avatar AndyGaskell
AndyGaskell - comment - 4 Oct 2020

Thanks for the info @ceford that's really useful. It's really pretty much the same as what I'm using, so my theory about variation in behaviour being due to some difference in web server settings or platform are probably off the mark.

I'll try some experiments to recreate this in other ways, to see if I can get figure out what's going on.

Hope it's less rainy in Edinburgh than here in Aberdeen today :)

avatar AndyGaskell
AndyGaskell - comment - 4 Oct 2020

I tried it on my laptop here, to test on a different system, and it behaved in the same way as my other tests.

My laptop has...

  • PHP Version: 7.2.22-1+ubuntu16.04.1+deb.sury.org+1
  • Web Server: Apache/2.4.18 (Ubuntu)
  • WebServer to PHP Interface: apache2handler
  • Joomla! Version: Joomla! 4.0.0-beta4 Beta [ Mañana ] 15-September-2020 13:46 GMT

I tried to see if there was any difference in header case implementation in OSX Apache v Linux Apache, but I found no docs or discussion that indicated any difference.

I'll check with 4.0.0-beta5-dev, perhaps there is a small difference between that and 4.0.0-beta4 that I've been using.

avatar zero-24
zero-24 - comment - 4 Oct 2020

@AndyGaskell i would say we have to lovercase Authorization when using the HTTP_AUTHORIZATION header too.

$authHeader = $this->app->input->server->get('HTTP_AUTHORIZATION', '', 'string');

As it seems @ceford uses the HTTP_AUTHORIZATION header?

@ceford can you show us the command you are using?

avatar AndyGaskell
AndyGaskell - comment - 4 Oct 2020

I just tried it with the latest code from master and the result was the same as previous tests. To do this I installed 4.0.0-beta4 Beta then over-wrote the files with 4.0-dev from git.

@zero-24 Thanks for your thoughts, I don't really fully understand what happens, but I was thinking that...
$authHeader = $this->app->input->server->get('HTTP_AUTHORIZATION', '', 'string');
...gets the value regardless of case. In my tests, authHeader is always empty, after the call on line 87, so it goes into the if (empty($authHeader) logic on line 91.

I'm wasn't very familiar with the HTTP_AUTHORIZATION element of the _SERVER array, it is not mentioned on https://www.php.net/manual/en/reserved.variables.server.php but there is a mention of it on https://tools.ietf.org/html/rfc3875 . I was wondering if this logic was used with a FastCGI web server implementation, and not in Apache. There was some discussion to this effect on symfony/symfony#19693

avatar zero-24
zero-24 - comment - 4 Oct 2020

I'm wasn't very familiar with the HTTP_AUTHORIZATION element of the _SERVER array,

Yes thats the reason i asked for that way that @ceford used to call the api so we test the same thing :)

avatar ceford
ceford - comment - 5 Oct 2020

These are the two commands I used for testing, with the token obscured:

ceford@cliff ~ % curl --location --request GET 'http://localhost/j4b4/api/index.php/v1/content/article' --header 'authorization: Bearer xxx'
ceford@cliff ~ % curl --location --request GET 'http://localhost/j4b4/api/index.php/v1/content/article' --header 'Authorization: Bearer xxx'

Also I checked the content of $authheader and found it the same in both cases:
Line 89 $authheader: 'Bearer xxx'

If I change authorization to xuthorization then $authheader is empty and I get a forbidden message.

I searched for HTTP_AUTHORIZATION and found this in .htaccess:
# PHP FastCGI fix for HTTP Authorization, required for the API application
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
There is also a mention in libraries/vendor/laminas/laminas-diactoros/src/function/normalize-server.php - I have no idea what that is used for.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/30882.
avatar AndyGaskell
AndyGaskell - comment - 5 Oct 2020

Hi @ceford

Thanks for the extra details, I think that makes sense now. I guess the difference in what we're seeing is probably because you have the .htaccess in place, where as I just have it still called htaccess.txt.

If you rename .htaccess to htaccess.txt then run the the lowercase curl command, what do you get back?

Looking in git, that...
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
...line has been in the htaccess file's core SEF Section for over 10 years.

avatar AndyGaskell
AndyGaskell - comment - 5 Oct 2020

Just checked this here, if I rename my htaccess.txt to .htaccess then the code reads the header in...
$authHeader = $this->app->input->server->get('HTTP_AUTHORIZATION', '', 'string');
...in uppercase and lowercase.

So I guess the...
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
...line in htaccess casts the header variable into the $_SERVER super global variable in a case-insensitive way.

So, my feeling is that this is a bug, but only one you see if you don't rename the htaccess file.

avatar ceford ceford - test_item - 5 Oct 2020 - Tested successfully
avatar ceford
ceford - comment - 5 Oct 2020

I have tested this item successfully on f946721

With .htaccess out of the way I found my code had not cleanly removed the patch. With the original restored and the patch applied I can confirm that both Authorization and authorization now work.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/30882.

avatar degobbis degobbis - test_item - 17 Oct 2020 - Tested successfully
avatar degobbis
degobbis - comment - 17 Oct 2020

I have tested this item successfully on f946721

I think the differences in the test results come from the operating systems. Linux is a case sensitive system, while Windows and MacOS are case insensitive by default.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/30882.

avatar zero-24
zero-24 - comment - 17 Oct 2020

Thanks merging.

avatar zero-24 zero-24 - close - 17 Oct 2020
avatar zero-24 zero-24 - merge - 17 Oct 2020
avatar zero-24 zero-24 - change - 17 Oct 2020
Status Pending Fixed in Code Base
Closed_Date 0000-00-00 00:00:00 2020-10-17 13:55:00
Closed_By zero-24
Labels Added: ?

Add a Comment

Login with GitHub to post a comment