cedaro / satispress

Expose installed WordPress plugins and themes as Composer packages.
500 stars 49 forks source link

Invalid credentials and Basic Auth not disabling. #105

Closed theleedyer closed 3 years ago

theleedyer commented 4 years ago

Hi, I feel like I've exhausted all options in an attempt to get this to work.

Running composer update, or composer require prompts me to add credentials. Using the api as username and 'satispress' as password fails everytime. Disabling basic auth using the filter hook still prompts for credentials.

debug mode is disabled.

[Composer\Downloader\TransportException]
Invalid credentials for 'https://www.domain.co.uk/satispress/packages.json', aborting.

bradyvercher commented 4 years ago

I'm not sure what to recommend other than trying to step through the code to try to figure out where the issue is occurring. These two methods handle authentication, so you could try debugging those. Let me know what you find out!

bradyvercher commented 4 years ago

Hi @lee4815, did you ever discover what was causing this issue?

theleedyer commented 4 years ago

Hi @bradyvercher, sadly no. Thank you for the suggestion though. I'm temporarily returning 1 in authenicate() until I get time to go through it fully.

assemblerdigital commented 4 years ago

I'm having a similar issue - no idea why I can't authenticate. This is on a clean install of bedrock, with no other modules activated other than satispress - although there's obviously some modules installed, otherwise there's no point to satispress at all.

This is the URL I am calling:

https://Bdu2egJQhZOA5tMIVTWNKY2QohzF2IYu:satispress@my.website.com/satispress/packages.json

Debugging the issues shows that the request simply doesn't have the "authorization" header in it, nor does it have the PHP_AUTH_PW or PHP_AUTH_USER headers. There is something in the request object that is refusing to play nice with basic auth details presented in the url, nor does it work with details being passing in via auth.json file. Is it possible that Satispress is incompatible with Bedrock?

assemblerdigital commented 4 years ago

Further to this, I can't get this to authenticate via composer at all, even when I return true/1 in check_scheme and authenticate methods. If I include an auth.json, it just says Invalid Credentials. If I don't include one, it asks me for a username/password, and of course none of the api keys work.

assemblerdigital commented 4 years ago

Update: Apparently ModSecurity interferes with the operation of SatisPress, which was preventing it from working at all, regardless of whether I stubbed out the authentication methods. With ModSecurity disabled, and a clean slate install of standard Wordpress though, I still had to stub the methods out - it does connect though, finally.

For the record, I'm hosting this SatisPress install on a bog standard cPanel account, by no means should this be considered a highly-customised hosting situation.

assemblerdigital commented 4 years ago

https://forums.cpanel.net/threads/apache-strips-out-custom-header.624799/

I am running suEXEC - it's entirely possibly that this explains the problem, the authentication headers are just being stripped. I don't have time to dig into this any more right now, but it certainly sounds like an avenue to explore!

lkraav commented 4 years ago

On cPanel setups, I've always had to config passing auth headers to FPM daemon manually:

# BEGIN REST API authentication
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
</IfModule>
# END REST API authentication
theleedyer commented 4 years ago

Hi @assemblerdigital thank you for sharing all this. I'm going to look again this week. My WordPress install is using bedrock, on a Digital Ocean droplet managed with Runcloud.

minemindmedia commented 4 years ago

Hi -- I love Satispress but all of a sudden, it's not authenticating for me either. I was using it successfully just a few weeks ago and now NONE of my projects will let me run composer update without sending out the following error:

[Composer\Downloader\TransportException]                                                            
  Invalid credentials for 'https://satispress.mydomain.com/satispress/packages.json', aborting.

I've checked my credentials, created new API keys to try and the whole 9 yards but still no luck on any project I attempt to update composer.

Hmm....

minemindmedia commented 4 years ago

Hi -- I love Satispress but all of a sudden, it's not authenticating for me either. I was using it successfully just a few weeks ago and now NONE of my projects will let me run composer update without sending out the following error:

[Composer\Downloader\TransportException]                                                            
  Invalid credentials for 'https://satispress.mydomain.com/satispress/packages.json', aborting.

I've checked my credentials, created new API keys to try and the whole 9 yards but still no luck on any project I attempt to update composer.

Hmm....

So it appears to fail when attempting to use any of the WPML.org plugins in Satispress. After I removed them all from my installation, I was then able to run composer update successfully again.

assemblerdigital commented 4 years ago

Yeah this whole codepath for authentication seems a little bit environment-dependent. I haven't looked into it enough to think through how else it might be done though, so I could be talking out my arse.

bradyvercher commented 4 years ago

@minemindmedia If you could send me a copy of WPML, I can take a look to see why it might be interfering with authentication.

@assemblerdigital SatisPress uses HTTP headers for authentication, which should be about as independent of the environment as you can get. Unfortunately, I think some environments do strip the Authorization header, which affects pretty much any plugin that handles authentication similarly. This issue has a few possible solutions, including the recommendation by @lkraav.

koengabriels commented 4 years ago

We are experiencing an issue that might be related, when running composer update we are no longer prompted for authentication and the response is a 500 internal server error.

[04-Dec-2019 06:22:03 UTC] PHP Fatal error:  Uncaught SatisPress\Exception\AuthenticationException: Authentication is required for this resource. in /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Exception/AuthenticationException.php:81
Stack trace:
#0 /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Authentication/UnauthorizedServer.php(48): SatisPress\Exception\AuthenticationException::forAuthenticationRequired()
#1 /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Provider/Authentication.php(114): SatisPress\Authentication\UnauthorizedServer->authenticate(Object(SatisPress\HTTP\Request))
#2 /sites/plugins.appsaloon.be/files/wp-includes/class-wp-hook.php(286): SatisPress\Provider\Authentication->determine_current_user(false)
#3 /sites/plugins.appsaloon.be/files/wp-includes/plugin.php(208): WP_Hook->apply_filters(false, Array)
#4 /sites/plugins.appsaloon.be/files/wp-includes/user.php(2698): apply_filters('determine_curre...', false)
#5 /sites/plugins.appsaloon.be/files/wp-inclu in /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Exception/AuthenticationException.php on line 81
[04-Dec-2019 06:22:03 UTC] PHP Fatal error:  Uncaught SatisPress\Exception\AuthenticationException: Authentication is required for this resource. in /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Exception/AuthenticationException.php:81
Stack trace:
#0 /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Authentication/UnauthorizedServer.php(48): SatisPress\Exception\AuthenticationException::forAuthenticationRequired()
#1 /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Provider/Authentication.php(114): SatisPress\Authentication\UnauthorizedServer->authenticate(Object(SatisPress\HTTP\Request))
#2 /sites/plugins.appsaloon.be/files/wp-includes/class-wp-hook.php(286): SatisPress\Provider\Authentication->determine_current_user(false)
#3 /sites/plugins.appsaloon.be/files/wp-includes/plugin.php(208): WP_Hook->apply_filters(false, Array)
#4 /sites/plugins.appsaloon.be/files/wp-includes/user.php(2698): apply_filters('determine_curre...', false)
#5 /sites/plugins.appsaloon.be/files/wp-inclu in /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Exception/AuthenticationException.php on line 81
[04-Dec-2019 06:22:04 UTC] PHP Fatal error:  Uncaught SatisPress\Exception\AuthenticationException: Authentication is required for this resource. in /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Exception/AuthenticationException.php:81
Stack trace:
#0 /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Authentication/UnauthorizedServer.php(48): SatisPress\Exception\AuthenticationException::forAuthenticationRequired()
#1 /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Provider/Authentication.php(114): SatisPress\Authentication\UnauthorizedServer->authenticate(Object(SatisPress\HTTP\Request))
#2 /sites/plugins.appsaloon.be/files/wp-includes/class-wp-hook.php(286): SatisPress\Provider\Authentication->determine_current_user(false)
#3 /sites/plugins.appsaloon.be/files/wp-includes/plugin.php(208): WP_Hook->apply_filters(false, Array)
#4 /sites/plugins.appsaloon.be/files/wp-includes/user.php(2698): apply_filters('determine_curre...', false)
#5 /sites/plugins.appsaloon.be/files/wp-inclu in /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Exception/AuthenticationException.php on line 81

I didn't create a separate issue yet as we moved our installation from a Apache server to a nginx server and updated Satispress on the new installation when this started happening. So it's a bit unclear wether or not the environment isn't set up properly or it's an actual satispress issue.

bradyvercher commented 4 years ago

@koengabriels When you're running WordPress in debug mode (WP_DEBUG is enabled), you'll see that exception. If you disable debug mode, you should see the login prompt.

koengabriels commented 4 years ago

@koengabriels When you're running WordPress in debug mode (WP_DEBUG is enabled), you'll see that exception. If you disable debug mode, you should see the login prompt.

@bradyvercher thank you! Solves the problem indeed.

banditrider commented 4 years ago

For the ones using Bedrock and can't get this to work, here's what worked for me:

Edit: Whitelisting the Toolset Views Lite plugin provided by WPML did lead to a server error when trying to access the package.json. Undoing this also fixed the server error.

bradyvercher commented 4 years ago

@banditrider Do you recall what the server error was that you were receiving or why that particular plugin was causing it?

banditrider commented 4 years ago

@bradyvercher Just tested it out again, our hosting's log is not very informative, that's what I could get from the domlog when enabling that particular plugin for satispress:

GET /satispress/packages.json HTTP/1.1" 500 2729 "-" "Composer/1.9.1 (Darwin; 18.7.0; PHP 7.1.32)

(Can't get the WP debug logs because of the issue with WP_DEBUG)

bradyvercher commented 4 years ago

@banditrider That looks like an entry from an access log, which usually wouldn't contain a helpful error message. Do you have an error log on your server that you can reference?

As for WP_DEBUG, you should be able to enable that and access the packages.json endpoint in your browser while you're logged in to WordPress to see the actual error message (or have it logged to debug.log). Only unauthenticated requests should see that authentication exception.

banditrider commented 4 years ago

Thx, yea, unfortunately, the error logs were empty. However, I followed your suggestion and I remember now, I've seen the issue somewhere else before: Composer doesn't seem to be able to handle the version string in the format used for that plugin:

Fatal error: Uncaught UnexpectedValueException: Invalid version string "2.9.4-lite" in [..]/vendor/composer/semver/src/VersionParser.php:172
Stack trace: #0 [...]/web/app/plugins/satispress/src/ComposerVersionParser.php(51): Composer\Semver\VersionParser->normalize('2.9.4-lite', '2.9.4-lite') #1 [...]/web/app/plugins/satispress/src/Transformer/ComposerRepositoryTransformer.php(130): SatisPress\ComposerVersionParser->normalize('2.9.4-lite') #2 [...]/web/app/plugins/satispress/src/Transformer/ComposerRepositoryTransformer.php(96): SatisPress\Transformer\ComposerRepositoryTransformer->transform_item(Object(SatisPress\PackageType\BasePackage)) #3 [...]/web/app/plugins/satispress/src/Route/Composer.php(71): SatisPress\Transformer\ComposerRepositoryTransformer->transform(Object(SatisPress\Repository\FilteredRepository)) 
bradyvercher commented 4 years ago

Ugh, that is a bummer. It might be possible to account for non-standard versions like that on a limited basis, though. You can try replacing the version parser in the DI container with a custom implementation to strip -lite from the end of version strings. Dropping something like this in a custom plugin should do it:

<?php
add_action( 'satispress_compose', function( $plugin, $container ) {
    $container['version.parser'] = new class implements \SatisPress\VersionParser {
        public function normalize( string $version, string $full_version = null ): string {
            $parser = new \Composer\Semver\VersionParser();

            $version = preg_replace( '/(.*)-lite$/', '$1', $version );

            return $parser->normalize( $version, $full_version );
        }
    };
}, 10, 2 );

I'm not opposed to adding a rule like that to SatisPress itself. If you'd like to test and report back whether or not it works in a new issue, that'd be great. Thanks!

BrianHenryIE commented 4 years ago

We are experiencing an issue that might be related, when running composer update we are no longer prompted for authentication and the response is a 500 internal server error.


[04-Dec-2019 06:22:03 UTC] PHP Fatal error:  Uncaught SatisPress\Exception\AuthenticationException: Authentication is required for this resource. in /sites/plugins.appsaloon.be/files/wp-content/plugins/satispress-0.5.0/src/Exception/AuthenticationException.php:81

@koengabriels When you're running WordPress in debug mode (`WP_DEBUG` is enabled), you'll see that exception. If you disable debug mode, you should see the login prompt.

I just spent an hour or two trying to handle that exception (actual solution was in @lkraav's comment).

I run all my sites with WP_DEBUG enabled (and fix the errors!). Can you educate me what's going on here? I was going to PR with a friendly error message but now I'm not sure that's possible.

bradyvercher commented 4 years ago

@BrianHenryIE SatisPress requests are handled by a custom handler. Exceptions generated in SatisPress are caught and converted into a generic response to prevent any sensitive data from being exposed publicly.

However, when the site is in debug mode, the exception is displayed instead for debugging purposes. Unfortunately, that means that the authentication challenge header isn't sent, so the browser nor Composer will display a prompt to enter credentials.

You could probably add a check for the Authorization header in the UnauthorizedServer and throw a different exception with more information if it's missing.

Displaying an admin notice on the settings screen might be a nice touch as well if the server is stripping Authorization headers.

bradyvercher commented 4 years ago

To alleviate the issues encountered here, I prevented authentication exceptions from being thrown when debug mode is enabled so that the challenge headers could be sent and allow the login prompts to be displayed.

I also started a health check feature to test for issues with missing Authorization headers, but I don't have access to a server where this is a problem. If anyone that was experiencing the error can test #124 and confirm whether or not an admin notice is being displayed on the Satispress Settings screen, that would be great.

eartisan-uk commented 4 years ago

@bradyvercher What is the expected admin notice? I tried it and it's displaying "SatisPress is missing required dependencies. Learn more.". Is that the desired outcome?

bradyvercher commented 4 years ago

@eartisan-uk Were you trying to test the PR or just install SatisPress? The message you're seeing is because you downloaded the source, which doesn't contain dependencies. You need to download the latest release asset (the file named satispress-{version}.zip). If you're trying to test the PR, then you would need to use git and run composer install to get the dependencies.

eartisan-uk commented 4 years ago

@bradyvercher Apologies for my mistake. I used the git to install the 'feature/health-check' to that branch and updated composer to get the dependencies. I then tried multiple times without any luck. I guess I'm not doing something correctly as I'm very late to the party so I'll wait until a permanent fix comes out. Cheers!

theleedyer commented 4 years ago

For the ones using Bedrock and can't get this to work, here's what worked for me:

* I was using development mode to be able to manually install plugins the Wordpress way, so I had to fix the issue with WP_DEBUG mentioned above: I switched to staging mode (because of default: no-index), then I adjusted the _config/application.php_ to allow for auto-updates and manual installation.

* In _web/.htaccess_ I needed to replace the line `RewriteRule ^index\.php$ ...` with `RewriteRule ^index\.php$ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]` as mentioned above.

* I had no issues with WPML in my installation though I've seen it reported a couple of times during my research.

Edit: Whitelisting the Toolset Views Lite plugin provided by WPML did lead to a server error when trying to access the package.json. Undoing this also fixed the server error.

Returning to this issue, this solution resolved if for me.

visata commented 3 years ago

I was using the server with WHM/cPanel and had the missing header issue. Initially, I added these rewrites to my .htaccess but it didn't have any effect.

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
</IfModule>

It only worked after I enabled PHP-FPM on the domain. Here are the instructions if you are using WHM:

Software -> MultiPHP Manager then find your domain to enable PHP-FPM

image

bradyvercher commented 3 years ago

The latest release contains a health check feature that attempts to determine if the Authorization header gets stripped. If authentication fails, it'll display an admin notice with a link to the documentation. Aside from that, I'm not sure there's much else that can be done. If anyone still has problems or additional suggestions, feel free to chime in.