diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/applicationpassword/ApplicationPasswordsViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/applicationpassword/ApplicationPasswordsViewModel.kt index 65fde978c160..faafa774c871 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/applicationpassword/ApplicationPasswordsViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/applicationpassword/ApplicationPasswordsViewModel.kt @@ -186,7 +186,13 @@ class ApplicationPasswordsViewModel @Inject constructor( } private suspend fun getApplicationPasswordsList(site: SiteModel): List { - val wpApiClient = wpApiClientProvider.getWpApiClient(site) + // Always use the direct-host Basic-auth client. `getWpApiClient` routes WPCom-flagged + // sites (including Atomic) through the WP.com REST proxy, which doesn't expose the + // `application-passwords` routes — every call 404s with `rest_no_route`. Talking to the + // site directly with the stored application password sidesteps that limitation. + // Requires the SiteModel to have credentials already (e.g. via the My Site auto-mint + // flow); otherwise the call will 401. + val wpApiClient = wpApiClientProvider.getApplicationPasswordClient(site) val currentUserId = getCurrentUserId(wpApiClient) return if (currentUserId == null) { diff --git a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/rs/WpApiClientProvider.kt b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/rs/WpApiClientProvider.kt index 5647227ef2e0..f0598b43b748 100644 --- a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/rs/WpApiClientProvider.kt +++ b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/rs/WpApiClientProvider.kt @@ -70,6 +70,20 @@ class WpApiClientProvider @Inject constructor( } } + /** + * Always returns a Basic-auth client against the direct host using the SiteModel's + * application-password credentials, regardless of WP.com routing. Use this when you need to + * talk to the site's own REST endpoints with the application password — `getWpApiClient` + * routes WPCom-flagged sites (including Atomic) through the bearer-token path and the WP.com + * REST proxy, which doesn't expose application-password-authenticated routes like + * `/wp/v2/users/{id}/application-passwords`. + */ + @Synchronized + fun getApplicationPasswordClient(site: SiteModel): WpApiClient = + selfHostedClients.getOrPut(site.id) { + createSelfHostedClient(site, uploadListener = null) + } + private fun createSelfHostedClient( site: SiteModel, uploadListener: WpRequestExecutor.UploadListener?,