Skip to content

Commit 83d87a2

Browse files
committed
feat: Increase robustness of authentication header construction
Handle edge cases with missing data.
1 parent 3ef015d commit 83d87a2

File tree

2 files changed

+339
-98
lines changed

2 files changed

+339
-98
lines changed

WordPress/src/main/java/org/wordpress/android/ui/posts/GutenbergKitActivity.kt

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@ private const val VIEW_PAGER_OFFSCREEN_PAGE_LIMIT = 4
249249
private const val MEDIA_ID_NO_FEATURED_IMAGE_SET = 0
250250

251251
object GutenbergKitSettingsBuilder {
252+
private const val AUTH_BEARER_PREFIX = "Bearer "
253+
private const val AUTH_BASIC_PREFIX = "Basic "
254+
252255
data class SiteConfig(
253256
val url: String,
254257
val siteId: Long,
@@ -260,25 +263,33 @@ object GutenbergKitSettingsBuilder {
260263
val apiRestUsernamePlain: String?,
261264
val apiRestPasswordPlain: String?
262265
)
263-
266+
264267
data class PostConfig(
265268
val remotePostId: Long?,
266269
val isPage: Boolean,
267270
val title: String?,
268271
val content: String?
269272
)
270-
273+
271274
data class FeatureConfig(
272275
val isPluginsFeatureEnabled: Boolean,
273276
val isThemeStylesFeatureEnabled: Boolean
274277
)
275-
278+
276279
data class AppConfig(
277280
val accessToken: String?,
278281
val locale: String,
279282
val cookies: Any?
280283
)
281-
284+
285+
/**
286+
* Builds the settings configuration for GutenbergKit editor.
287+
*
288+
* This method determines the appropriate authentication method based on site type:
289+
* - WP.com sites use Bearer token authentication with the public API
290+
* - Jetpack/self-hosted sites with application passwords use Basic authentication
291+
* - Falls back to WP.com REST API when no application password is available
292+
*/
282293
fun buildSettings(
283294
siteConfig: SiteConfig,
284295
postConfig: PostConfig,
@@ -287,22 +298,23 @@ object GutenbergKitSettingsBuilder {
287298
): MutableMap<String, Any?> {
288299
val applicationPassword = siteConfig.apiRestPasswordPlain
289300
val shouldUseWPComRestApi = applicationPassword.isNullOrEmpty() && siteConfig.isUsingWpComRestApi
290-
301+
291302
val siteApiRoot = if (shouldUseWPComRestApi) "https://public-api.wordpress.com/"
292303
else siteConfig.wpApiRestUrl ?: "${siteConfig.url}/wp-json/"
293-
294-
val authHeader = if (shouldUseWPComRestApi) "Bearer ${appConfig.accessToken ?: ""}"
295-
else "Basic ${Base64.encodeToString(
296-
"${siteConfig.apiRestUsernamePlain}:$applicationPassword".toByteArray(),
297-
Base64.NO_WRAP
298-
)}"
299-
304+
305+
val authHeader = buildAuthHeader(
306+
shouldUseWPComRestApi = shouldUseWPComRestApi,
307+
accessToken = appConfig.accessToken,
308+
username = siteConfig.apiRestUsernamePlain,
309+
password = applicationPassword
310+
)
311+
300312
val siteApiNamespace = if (shouldUseWPComRestApi)
301313
arrayOf("sites/${siteConfig.siteId}/", "sites/${UrlUtils.removeScheme(siteConfig.url)}/")
302314
else arrayOf()
303-
315+
304316
val wpcomLocaleSlug = appConfig.locale.replace("_", "-").lowercase()
305-
317+
306318
return mutableMapOf(
307319
"postId" to postConfig.remotePostId?.toInt(),
308320
"postType" to if (postConfig.isPage) "page" else "post",
@@ -324,7 +336,49 @@ object GutenbergKitSettingsBuilder {
324336
"cookies" to appConfig.cookies
325337
)
326338
}
327-
339+
340+
/**
341+
* Builds the authentication header based on the authentication method.
342+
*
343+
* @param shouldUseWPComRestApi True if using WP.com REST API (Bearer auth)
344+
* @param accessToken The OAuth2 access token for WP.com authentication
345+
* @param username The username for Basic auth (application passwords)
346+
* @param password The password for Basic auth (application passwords)
347+
* @return The formatted authentication header string, or null if credentials are invalid
348+
*/
349+
private fun buildAuthHeader(
350+
shouldUseWPComRestApi: Boolean,
351+
accessToken: String?,
352+
username: String?,
353+
password: String?
354+
): String? {
355+
return if (shouldUseWPComRestApi) {
356+
if (!accessToken.isNullOrEmpty()) {
357+
"$AUTH_BEARER_PREFIX$accessToken"
358+
} else {
359+
AppLog.w(AppLog.T.EDITOR, "Missing access token for WP.com REST API authentication")
360+
null
361+
}
362+
} else {
363+
if (!username.isNullOrEmpty() && !password.isNullOrEmpty()) {
364+
try {
365+
val credentials = "$username:$password"
366+
val encodedCredentials = Base64.encodeToString(
367+
credentials.toByteArray(Charsets.UTF_8),
368+
Base64.NO_WRAP
369+
)
370+
"$AUTH_BASIC_PREFIX$encodedCredentials"
371+
} catch (e: IllegalArgumentException) {
372+
AppLog.e(AppLog.T.EDITOR, "Failed to encode Basic auth credentials", e)
373+
null
374+
}
375+
} else {
376+
AppLog.w(AppLog.T.EDITOR, "Incomplete credentials for Basic authentication")
377+
null
378+
}
379+
}
380+
}
381+
328382
private fun shouldUsePlugins(
329383
isFeatureEnabled: Boolean,
330384
isWPComSite: Boolean,
@@ -2407,27 +2461,27 @@ class GutenbergKitActivity : BaseAppCompatActivity(), EditorFragmentActivity, Ed
24072461
apiRestUsernamePlain = site.apiRestUsernamePlain,
24082462
apiRestPasswordPlain = siteModel.apiRestPasswordPlain
24092463
)
2410-
2464+
24112465
val postConfig = GutenbergKitSettingsBuilder.PostConfig(
24122466
remotePostId = editPostRepository.getPost()?.remotePostId,
24132467
isPage = editPostRepository.isPage,
24142468
title = editPostRepository.getPost()?.title,
24152469
content = editPostRepository.getPost()?.content
24162470
)
2417-
2471+
24182472
val featureConfig = GutenbergKitSettingsBuilder.FeatureConfig(
24192473
isPluginsFeatureEnabled = gutenbergKitPluginsFeature.isEnabled(),
24202474
isThemeStylesFeatureEnabled = experimentalFeatures.isEnabled(
24212475
Feature.EXPERIMENTAL_BLOCK_EDITOR_THEME_STYLES
24222476
)
24232477
)
2424-
2478+
24252479
val appConfig = GutenbergKitSettingsBuilder.AppConfig(
24262480
accessToken = accountStore.accessToken,
24272481
locale = perAppLocaleManager.getCurrentLocaleLanguageCode(),
24282482
cookies = editPostAuthViewModel.getCookiesForPrivateSites(site, privateAtomicCookie)
24292483
)
2430-
2484+
24312485
return GutenbergKitSettingsBuilder.buildSettings(
24322486
siteConfig = siteConfig,
24332487
postConfig = postConfig,

0 commit comments

Comments
 (0)