Make WordPress Core

Opened 2 weeks ago

Last modified 2 weeks ago

#66000 new defect (bug)

Application Passwords warning persists after HTTP Basic Authentication is disabled

Reported by: ethicaladitya Owned by:
Priority: normal Milestone: Awaiting Review
Component: Application Passwords Version:
Severity: normal Keywords:
Cc: Focuses:

Description

I found an issue where WordPress continues to show the following message under Users → Profile → Application Passwords:

“Your website appears to use Basic Authentication, which is not currently compatible with Application Passwords.”

This happens even after HTTP Basic Authentication has been disabled.

The issue appears to be browser/session dependent.

## Steps to reproduce

  1. Enable HTTP Basic Authentication on a WordPress site.
  2. Open the site in Browser A and access the WordPress profile page.
  3. Go to Users → Profile → Application Passwords.
  4. The Basic Authentication warning is displayed.
  5. Disable HTTP Basic Authentication.
  6. Clear any available caches and resave permalinks.
  7. Return to the Application Passwords section in Browser A.

The warning continues to be displayed.

However, if I open the same site with the same WordPress user in Browser B, where the site was never accessed while HTTP Authentication was enabled, Application Passwords work normally.

The same happens in an incognito/private window.

### Example

  • Browser A → accessed while HTTP Auth was enabled → HTTP Auth disabled → warning remains.
  • Browser B → never accessed while HTTP Auth was enabled → Application Passwords work.
  • Incognito → Application Passwords work.

## Additional checks

After disabling HTTP Authentication, I checked the server environment and neither of these variables was present:

`text
PHP_AUTH_USER
PHP_AUTH_PW
`

I also tried clearing caches, resaving permalinks.

The affected browser session still showed the warning.

## Expected behavior

Once HTTP Basic Authentication is disabled, WordPress should detect that it is no longer enabled and allow Application Passwords to be generated.

A browser session that previously encountered HTTP Basic Authentication should not continue preventing Application Passwords from being used.

## Actual behavior

The warning persists in the browser/session that previously encountered HTTP Basic Authentication, while a fresh browser session works correctly.

This makes the issue appear to be related to cached browser authentication/session state and how WordPress detects Basic Authentication.

## Environment

  • WordPress 7.1
  • Nginx
  • PHP-FPM
  • HTTP/3

## Workaround

Opening the site in a new/incognito browser allows Application Passwords to work.

Change History (2)

#1 @khokansardar
2 weeks ago

Confirmed on trunk @ 987d42d6ad. The report is accurate, and the cause is a known, documented limitation rather than a regression.

Environment

WordPress: 7.2-alpha-63166-src
PHP: 8.2.18, fpm-fcgi
Server: nginx 1.25.4 + PHP-FPM (same stack as reported)
MySQL: 8.0.36
Local wordpress-develop @ http://localhost:8889

Mechanism

wp_is_site_protected_by_basic_auth() in src/wp-includes/load.php decides entirely on this line:

$is_protected = ! empty( $_SERVER['PHP_AUTH_USER'] ) || ! empty( $_SERVER['PHP_AUTH_PW'] );

Under the CGI/FastCGI SAPI, PHP populates PHP_AUTH_USER and PHP_AUTH_PW from the client's Authorization: Basic request header on its own. No server-side Basic Auth needs to be configured for those keys to appear.

Browsers keep sending cached Basic credentials to an origin for the rest of the session, so after Basic Auth is switched off the browser keeps replaying the header, PHP keeps synthesising the two $_SERVER keys, and wp_is_site_protected_by_basic_auth( 'front' ) keeps returning true. That is what hides the form and prints the notice at src/wp-admin/user-edit.php.
A fresh browser or private window sends no header, so it works — exactly as reported.

Measured with Basic Auth completely disabled on the server, replaying a credential the server has never seen:

PHP_AUTH_USER: set ("staleuser")
AUTH_TYPE:
REMOTE_USER: unset
wp_is_site_protected_by_ba

On the reporter's `PHP_AU

The ticket notes that neitheer disabling Basic Auth. They are present precisely on the requests that carry the stale header; a check made from CLI or froched credential will not see them. So this observation does not contradict the diagnosis, it is a symptom of it.

Why there is no in-reques

I configured genuine nginx plus WWW-Authenticate when no credentials are sent) and compared the $_SERVER` fingerprint against the stale-credential case above:

genuinely protecte|
PHP_AUTH_USER set set
AUTH_TYPE unset
REMOTE_USER unset unset

They are indistinguishable. AUTH_TYPE and REMOTE_USER look like they could discriminate, but stochips neither, so keying on them would under-detect sites that really are behind Basic Auth and reintroduce the conflict #52066 was opened to prevent.

Existing guidance

This is the limitation the function documents: "this merely checks for the present of Basic Auth credentials ... In a future release, this evaluation may be made more robust." [50006], which introduced the function for #52066, names the intended fix: make a loopback request and check for a WWW-Authenticate header.

Until then the supported workaround is the filter added by that same changeset:

add_filter( 'wp_is_site_protected_by_basic_auth', '__return_false' );

Suggested next step

Needs a committer decision on whether to implement the loopback detection from [50006]. That is a behaviour change on every site plus a network request on the profile screen, so it needs caching and sign-off rather than a drive-by patch. Worth noting that wp_is_site_protected_by_basic_auth() currently has no PHPUnit coverage at all, which would be useful groundwork either way.

#2 @smeunus
2 weeks ago

I can replicate the same. Struggled for 2 hours due to this issue.

Note: See TracTickets for help on using tickets.