WP-API / Basic-Auth

Basic Authentication handler for the JSON API, used for development and debugging purposes
762 stars 281 forks source link

Basic Authentication not working with WP REST APIv2 #35

Open rubenhak opened 8 years ago

rubenhak commented 8 years ago

hi Everybody,

I'm trying to use basic authentication with WP REST API v2 plugin (https://github.com/WP-API/WP-API). But whatever i tried the api returns "Sorry, you are not allowed to ...". Error. I'm using Postman as a client and can see it that correctly set "Authorization" header in the request.

For example if i post here: http://mywebsite.com/wp-json/wp/v2/posts/ Body: { "title": "Hello Updated World!", "content_raw": "Howdy updated content.", "date": "2013-04-01T14:00:00+10:00" }

The response is: { "code": "rest_cannot_create", "message": "Sorry, you are not allowed to create new posts.", "data": { "status": 401 } }

I'd appreciate some help here.

Thanks, Ruben

kamalhussain commented 7 years ago

In my experience, basic authentication works only with https. I tried modifying .htaccess as explained above but it didn't help with http. However, it started working after I switched to https.

dambrogia commented 7 years ago

Since I just spent about 5 hours on this, I'll try and save someone the headache. I had 2 issues I ran into:

@eladm92 's issue of CGI renaming the headers. I had my CGI settings within my apache virtual host file. So I commented those lines out:

# AddHandler php7-fastcgi .php
# Action php7-fastcgi /cgi-bin/php.fastcgi

These might also be able to be set within .htaccess files as well depending on your configuration so keep that in mind.

The other problem I ran into was @ethanclevenger91 's problem of not being able to log in while I was logged into chrome. I tried testing it within an incognito browser after making eladm92's fix and everything worked fine.

I also use the basic-auth plugin, but that should be a given.

datesss commented 6 years ago

I haven't gotten in working trying the above fixes in this thread (using MAMP on a macbook pro) :-(

markestocapio commented 6 years ago

For future reference.

If you are using MAMP. The authorization header won't work in the "Individual PHP version for every host (cgi)" mode.

You need to set your PHP to use identical PHP for all hosts.

eazulay commented 6 years ago

Thanks yummish, your solution worked for me too. I was logged in to WordPress in Firefox and used the RESTClient Firefox plugin in another tab. As soon as I logged out of WordPress, the RESTClient's requests were being accepted.

eazulay commented 6 years ago

After I logged out of Wordpress my GET requests were accepted. However, all my POST requested came back with error 400 Bad Request - empty request. It turned out I needed to add this header: Content-Type: application/json

Now it all works as expected.

XP522038476 commented 6 years ago

@booberchi 我英文不好,我只能用中文写了,我被这个问题恶心到了,我已经研究了5天了任然一无所获,直到看到你提供的插件,我终于可以使用wp_rest_api来链接了,谢谢你,还有就是,这并不是耻辱,至少你帮助了很多人。I proved that this plug-in helped me, thank you booberchi =。=~~~

NickyBall commented 6 years ago

I fixed this issue by adding RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] directly to httpd-add.conf file in my web server configuration folder. Hope this help.

image

umyhacker commented 6 years ago

No Solution worked for me

yuonoda commented 6 years ago

Hey guys, this problem occurs in my environment using Nginx, so I cannot use .htaccess and have to configure conf.d. Does anyone know how to solve it on Nginx server ??

csimpi commented 6 years ago

Our project was in a GoDaddy host, in a day to another the Authorization header just disappeared. I was thinking I made some mistake during the last deployment. After 3 hours of struggling, google-ing, cursing turned out GoDaddy changed something in the server config that stipped the Authorization header. Our users can't use the website at all, and they are still just working on it. Terrible. So If somebody has any similar mysterious issue, very easy to debug it.

Create a test.php in the webroot folder with this script:

<?php
var_dump(apache_request_headers());
?>

Make sure you have these rules in your .htaccess file

    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Then send a request with any kind of REST tester, set the Authorization header as you wish, then check the result. If you can't find the Authorization header in the result and you have been added the required lines to your .htaccess file, the issue with the web server config that the .htaccess file can't override. Contact your host provider if necessary.

I hope this helps.

maartenvonkreijfelt commented 6 years ago

Hey guys I didn't get it done, seemed I used an old version of the plugin :( This one does work https://github.com/WP-API/Basic-Auth

frankiejarrett commented 6 years ago

@csimpi I can look into that for you (I work at GoDaddy), what’s your URL?

djabif commented 6 years ago

Hey guys, I created a tutorial (text+code) to explain how to perform basic wordpress authentication from an Ionic Framework App using the WP REST API. Feel free to download the code and ask me anything. https://ionicthemes.com/tutorials/about/ionic-wordpress-integration

csimpi commented 6 years ago

@fjarrett I sent you an email that I could find on your GitHub profile. Many thanks in advance :)

UPDATE: As Godaddy support works, he is disappeared, still nobody solved our problem, we had to move from Godaddy.

phantomlution commented 6 years ago

I find a solution. It seems that the auth plugin is not installed properly. You can download zip -> https://github.com/WP-API/Basic-Auth.git and then install it. It works for me. Related to this issue: https://github.com/WP-API/WP-API/issues/3002

zearg commented 5 years ago

I didn't need any .htaccess modifications. Just read this : https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/ I forgot to use an "X-WP-Nonce" in wp-json query request headers.

An example code :

In PHP :

wp_enqueue_script( 'test, plugin_dir_url( __FILE__ ) . 'js/test.js', array(), $this->version, false );
wp_localize_script( 'test, 'wpApiSettings', array(
    'root' => esc_url_raw( rest_url() ),
    'nonce' => wp_create_nonce( 'wp_rest' )
));

In JS :

        $.ajax( {
            url: wpApiSettings.root + 'wp/v2/users/me',
            method: 'POST',
            beforeSend: function ( xhr ) {
                xhr.setRequestHeader( 'X-WP-Nonce', wpApiSettings.nonce );
            },
            data:{
                'title' : 'Hello Moon'
            }
        } ).done( function ( response ) {
            console.log( response );
        } );

In this example, you can't request directly the WP API in URL. You have to do this with nonce request headers and auth cookies, in JS on a page or with curl in PHP Code (don't forget auth cookies !)

Hope that'll help

huynhnhathoangit commented 5 years ago

Hey guys, after some time i finally found the fix (at least for me), It was a .htaccess issue.

The original .htaccess looked like this:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

I changed it to the following

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteBase /
RewriteRule ^index\.php$ - [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

The HTTP_AUTHORIZATION rule has to come before the other rules, this is because the L flag exists, the L flag means (last - stop processing rules), because of this it would never come to that rule if it was after the original wordpress rules,

Hope this helps anyone else!

Must login to thank you! it works for me!!!

image

megin1989 commented 5 years ago

Hello guys, this problem occurs in Nginx. Does anyone know how to solve it on Nginx server ? Please help me.

MatzeKitt commented 5 years ago

I always had the same problem using a local MAMP. While looking for the issue I could find out that if you use SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1, you receive the token in $_SERVER['HTTP_AUTHORIZATION'] or $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], which are ignored by the Basic-Auth plugin.

To fix this, I added the following inside the json_basic_auth_handler (before verifying that $user is empty, currently line 16):

        // get authorization header
        // needs .htaccess adjustments:
        // SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
        if ( isset( $_SERVER['HTTP_AUTHORIZATION'] ) ) {
            $authorization = \sanitize_text_field( \wp_unslash( $_SERVER['HTTP_AUTHORIZATION'] ) );
        }
        else if ( isset( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) ) {
            $authorization = \sanitize_text_field( \wp_unslash( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) );
        }

        if ( ! empty( $authorization ) ) {
            // phpcs:disable WordPress.VIP.ValidatedSanitizedInput.MissingUnslash, WordPress.VIP.ValidatedSanitizedInput.InputNotSanitized, WordPress.VIP.ValidatedSanitizedInput.InputNotValidated
            list( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) = explode( ':', base64_decode( substr( $authorization, 6 ) ) );
            // phpcs:enable
        }

This way I decode username and password, split it by the : and add it as $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'], which are then processed by the plugin.

lanbau commented 5 years ago

Hey guys,

I had the same 401 problem and used the .htaccess rewrite solution above.

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

I fixed my issue as i found out that this does not work with WordPress sites with 2 factor authentication plugin enabled.

After disabling the plugin, everything works as expected!

I also observed that upgrading WordPress versions, the modified htaccess is updated by WordPress core which causes this plugin to fail again.

Hope there is a native fix in future.

Spec

Praful commented 5 years ago

I've been going around in circles chasing this issue for a WordPress instance hosted by 1&1. I couldn't figure out why this was working on my local docker WordPress instance but not on the hosted site. It turns out that the official WordPress docker instance uses the Apache 2 handler and the hosted site uses CGI/FastCGI for the server API.

If you want to know which you're using, create a file (say info.php) with this:

<?php
phpinfo();  
var_dump(apache_request_headers());
?>

Only the first phpinfo() call is required. The second line dumps the Apache headers for further diagnostics.

This is the solution that worked for me. This solution is slightly different from the updated readme associated with this issue which is different from the readme on the homepage of this repository.

  1. Use the updated basic-auth.php file. The updated version is not in the downloaded ZIP file (Basic-Auth-master.zip). You have to clone the repository.

  2. Change the .htaccess file to include:

# BEGIN WordPress
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    RewriteBase /
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]
</IfModule>
  1. To stop WordPress permalinks overwriting this change, include the following in your theme's function.php:
add_filter('flush_rewrite_rules_hard','__return_false');
NeekunjC2C commented 5 years ago

I have tried all the suggestion provided including the above latest one by @Praful , Please suggest, any help will be highly appreciated.

jcsuzanne commented 5 years ago

I've been going around in circles chasing this issue for a WordPress instance hosted by 1&1. I couldn't figure out why this was working on my local docker WordPress instance but not on the hosted site. It turns out that the official WordPress docker instance uses the Apache 2 handler and the hosted site uses CGI/FastCGI for the server API.

If you want to know which you're using, create a file (say info.php) with this:

<?php
phpinfo();  
var_dump(apache_request_headers());
?>

Only the first phpinfo() call is required. The second line dumps the Apache headers for further diagnostics.

This is the solution that worked for me. This solution is slightly different from the updated readme associated with this issue which is different from the readme on the homepage of this repository.

  1. Use the updated basic-auth.php file. The updated version is not in the downloaded ZIP file (Basic-Auth-master.zip). You have to clone the repository.
  2. Change the .htaccess file to include:
# BEGIN WordPress
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    RewriteBase /
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]
</IfModule>
  1. To stop WordPress permalinks overwriting this change, include the following in your theme's function.php:
add_filter('flush_rewrite_rules_hard','__return_false');

Thanks a lot, this solution did the job for me on a Wordpress instance shared on 1&1 (ionos) too.

Just to be a litte more accurate about the modifications to do in the basic-auth.php file. You just need to follow the updated code referenced here https://github.com/WP-API/Basic-Auth/issues/35#issuecomment-461314998

Praful commented 5 years ago

@jcsuzanne - that's good to hear :)

I didn't patch anything myself (in step 1 above). I used the basic-auth.php file transferred when you clone the repository using the usual command, which for those who don't know is:

git clone https://github.com/WP-API/Basic-Auth.git

To expand step 1:

1a. I downloaded basic-auth-master.zip from the repository. 1b. Installed this ZIP as a plugin to WordPress. 1c. When 1b didn't work, I cloned the repository to my PC using the above git clone command. 1d. Copied the basic-auth.php file to WordPress, replacing the one from the ZIP file.

I know you've got it working but the above may save someone manually patching the file.

Praful

caseyryan commented 5 years ago

I'd also tried all of the solutions and none worked. Then I started looking for the place where my "not_logged_in" message came from and found out it was one of installed plugins. To be more specific it was a plugin called Members. I used it to restrics site access to some user Roles. That's what was restricting the API access too. For those who also can't solve this problem, this info might be useful

valerio-bozzolan commented 5 years ago

Small note: as you know you may need to restart your webserver after this change but, in addition, I had also to log-out and log-in again.

MichaelSmi commented 5 years ago

Small note for Plesk Users: You have to add SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 to your custom apache conf. Settings link as of Plesk 18.* is: https://domain.tld:8443/smb/web/web-server-settings/id/#

DarthTicius commented 4 years ago
<IfModule mod_rewrite.c>
RewriteEngine On

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

Can confirm that placing just after the RW rule the line:

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

in the .htaccess did the trick for me. comment in question: (koenhoeijmakers .htaccess comment)

gojetk commented 4 years ago

This works, thank you

Pezhvak commented 4 years ago
<IfModule mod_rewrite.c>
RewriteEngine On

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

Can confirm that placing just after the RW rule the line:

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

in the .htaccess did the trick for me. comment in question: (koenhoeijmakers .htaccess comment)

while this works, but it got replaced on the latest woocommerce update. this is not a permanent fix.

ryandavis84 commented 4 years ago

Any updates on this for nginx?

MatzeKitt commented 4 years ago

I use this configuration in the fastcgi_params:

    fastcgi_param   PHP_AUTH_USER           $remote_user;
    fastcgi_param   PHP_AUTH_PW             $http_authorization;

And these modifications: https://github.com/WP-API/Basic-Auth/issues/35#issuecomment-461314998

youry509 commented 4 years ago

None of these solution worked for me. Im using woordpress 5.4 on google cloud. Bitnami and Automaticc Certified. Cant get help from wordpress nor bitnami. Anyone in the same boat as me?

cdove99 commented 4 years ago

None of these solution worked for me. Im using woordpress 5.4 on google cloud. Bitnami and Automaticc Certified. Cant get help from wordpress nor bitnami. Anyone in the same boat as me?

if you're using bitnami you need to update /opt/bitnami/apps/wordpress/conf/http_app.conf instead of .htaccess. i was having this issue and couldn't find any solution. until i found out that bitnami doesn't use .htacces by default.

youry509 commented 4 years ago

For those still looking for a solution. I changed the version of my php from 7.4 to 7.2 and its now working for me. (back up your site before you do this). I also installed ioncube loader extension on my 7.2 version of php too, i don't know if that changed anything. Tell me if that worked for you.

EmXaN commented 3 years ago

Nothing above worked. So here is a permanent solution to fix this issue. Just paste the following code/rule right above (i.e. before) the # BEGIN Wordpress in the .htaccess file:

RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]

Example: RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}] # BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> # END WordPress

Logout from the Wordpress Admin and re-login. It won't remove this rule from the .htaccess despite any Wordpress updates.

suneth2 commented 3 years ago

finally 2-3 hours effort seems worked, hope this will help someone to solve their issue

on .htaccess


<IfModule mod_rewrite.c>
RewriteEngine On

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

On theme function.php file


add_filter('woocommerce_rest_check_permissions', 'my_woocommerce_rest_check_permissions', 90, 4);

function my_woocommerce_rest_check_permissions($permission, $context, $object_id, $post_type) {

    if($_SERVER['PHP_AUTH_USER'] == 'ck_consumer_key_here' && $_SERVER['PHP_AUTH_PW'] == 'cs_consumer_secrect_key_here') {
        return true;
    }

    return $permission;
}
apple-avadhesh commented 3 years ago

None of these solution worked for me. Im using woordpress 5.4 on google cloud. Bitnami and Automaticc Certified. Cant get help from wordpress nor bitnami. Anyone in the same boat as me?

if you're using bitnami you need to update /opt/bitnami/apps/wordpress/conf/http_app.conf instead of .htaccess. i was having this issue and couldn't find any solution. until i found out that bitnami doesn't use .htacces by default.

It says 'unwritable' when I tried to run the command 'nano /opt/bitnami/apps/wordpress/htdocs/.htaccess' tried setting permission too 'chmod 777' but it didn't work. What am I doing wrong here?? :(

fardinfahm commented 3 years ago

As you are using http: use oAuth1 if it's https then use Basic Authentication

erdostom commented 2 years ago

If anyone else is having this issue w Amazon / Bitnami, here is the solution that worked for me:

source: https://community.bitnami.com/t/wordpress-rest-api-basic-authentication-header-not-working/59090/6

my final httpd-app.conf looks like this:

RewriteEngine On
RewriteRule /<none> / [L,R]

<IfDefine USE_PHP_FPM>
    <Proxy "unix:/opt/bitnami/php/var/run/wordpress.sock|fcgi://wordpress-fpm" timeout=300>
    </Proxy>
</IfDefine>

<Directory "/opt/bitnami/apps/wordpress/htdocs">
    Options +MultiViews +FollowSymLinks
    AllowOverride None
    <IfVersion < 2.3 >
        Order allow,deny
        Allow from all
    </IfVersion>
    <IfVersion >= 2.3>
        Require all granted
    </IfVersion>

    <IfModule php7_module>
            php_value memory_limit 512M
    </IfModule>

    <IfDefine USE_PHP_FPM>
       <FilesMatch \.php$>
         SetHandler "proxy:fcgi://wordpress-fpm"
       </FilesMatch>
    </IfDefine>

RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]

    RewriteEngine On
    #RewriteBase /wordpress/
    RewriteRule ^index\.php$ - [S=1]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . index.php [L]

    Include "/opt/bitnami/apps/wordpress/conf/banner.conf"
</Directory>

Include "/opt/bitnami/apps/wordpress/conf/htaccess.conf"
pavelcalinmihai commented 2 years ago

Hello, I'm still receiving 401 but I don't have woocommerce installed

iiKulakov commented 1 year ago

My problem was with the cookie: wordpress_logged_in in JS fetch request. With this cookie i always got 401 error. When i passed credentials: 'omit' problem went away.

abdullahzreqat commented 1 year ago

If You had changed the .htaccess and still facing the issue? In my case, the URL was like "https://localhost/wordpress/wp-json/wc/v2/products" and I change it to my IP address instead of "localhost", https://"Your IP Address"/wordpress/wp-json/wc/v2/products and it works!!!

SaidiAli commented 7 months ago

Hello I got this error using Nextjs and i was making the request using fetch, I switch to axios and it worked. Good luck.

gnumoksha commented 7 months ago

In my case I was using the superadmin, so I had to create a new user, which the "editor" role, and then create an application password for him.