From e09e914da1d7aa143a2680314ecb744645db6e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=E2=89=A1ZRS?= <12814349+LZRS@users.noreply.github.com> Date: Wed, 10 Jan 2024 11:13:18 +0300 Subject: [PATCH 1/3] Update engine sdk to v0.1.0-beta04-preview4.2-SNAPSHOT --- android/engine/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/engine/build.gradle b/android/engine/build.gradle index d073f6246b..e4caabf341 100644 --- a/android/engine/build.gradle +++ b/android/engine/build.gradle @@ -222,7 +222,7 @@ dependencies { transitive = true } - api('org.smartregister:engine:0.1.0-beta04-preview4.1-SNAPSHOT') { + api('org.smartregister:engine:0.1.0-beta04-preview4.2-SNAPSHOT') { transitive = true exclude group: 'org.hamcrest', module: 'hamcrest-core' exclude group: 'javax.xml.bind', module: 'jaxb-api' From 2df2764343920f8c979eb8d14565861c9c48bb6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=E2=89=A1ZRS?= <12814349+LZRS@users.noreply.github.com> Date: Thu, 11 Jan 2024 14:10:43 +0300 Subject: [PATCH 2/3] Update refresh token to avoid reuse of stale refresh token (#2959) Stale refresh token on expiry leads to requests raising 401 and sync failing --- .../fhircore/engine/auth/AccountAuthenticator.kt | 2 +- .../engine/data/remote/shared/TokenAuthenticator.kt | 5 ++++- .../fhircore/engine/auth/AccountAuthenticatorTest.kt | 12 +++++++----- .../fhircore/engine/auth/TokenAuthenticatorTest.kt | 6 +++++- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/android/engine/src/main/java/org/smartregister/fhircore/engine/auth/AccountAuthenticator.kt b/android/engine/src/main/java/org/smartregister/fhircore/engine/auth/AccountAuthenticator.kt index a9f39dd35c..4df7d6f2a0 100644 --- a/android/engine/src/main/java/org/smartregister/fhircore/engine/auth/AccountAuthenticator.kt +++ b/android/engine/src/main/java/org/smartregister/fhircore/engine/auth/AccountAuthenticator.kt @@ -83,7 +83,7 @@ constructor( if (!refreshToken.isNullOrEmpty()) { authToken = try { - tokenAuthenticator.refreshToken(refreshToken) + tokenAuthenticator.refreshToken(account, refreshToken) } catch (ex: Exception) { Timber.e(ex) "" // Set to EMPTY, so as to redirect to log in screen, and try again diff --git a/android/engine/src/main/java/org/smartregister/fhircore/engine/data/remote/shared/TokenAuthenticator.kt b/android/engine/src/main/java/org/smartregister/fhircore/engine/data/remote/shared/TokenAuthenticator.kt index bd5d865584..8bd001e867 100644 --- a/android/engine/src/main/java/org/smartregister/fhircore/engine/data/remote/shared/TokenAuthenticator.kt +++ b/android/engine/src/main/java/org/smartregister/fhircore/engine/data/remote/shared/TokenAuthenticator.kt @@ -223,13 +223,16 @@ constructor( * [HttpException] or [UnknownHostException] exceptions */ @Throws(HttpException::class, UnknownHostException::class) - fun refreshToken(currentRefreshToken: String): String { + fun refreshToken(account: Account, currentRefreshToken: String): String { return runBlocking { val oAuthResponse = oAuthService.fetchToken( buildOAuthPayload(REFRESH_TOKEN).apply { put(REFRESH_TOKEN, currentRefreshToken) } ) + // Updates with new refresh-token + accountManager.setPassword(account, oAuthResponse.refreshToken!!) + // Returns valid token or throws exception, NullPointerException not expected oAuthResponse.accessToken!! } diff --git a/android/engine/src/test/java/org/smartregister/fhircore/engine/auth/AccountAuthenticatorTest.kt b/android/engine/src/test/java/org/smartregister/fhircore/engine/auth/AccountAuthenticatorTest.kt index 6a6d8e9ddd..7ff03f3ea5 100644 --- a/android/engine/src/test/java/org/smartregister/fhircore/engine/auth/AccountAuthenticatorTest.kt +++ b/android/engine/src/test/java/org/smartregister/fhircore/engine/auth/AccountAuthenticatorTest.kt @@ -253,8 +253,9 @@ class AccountAuthenticatorTest : RobolectricTest() { every { accountManager.peekAuthToken(account, authTokenType) } returns "" val refreshToken = "refreshToken" every { accountManager.getPassword(account) } returns refreshToken + every { accountManager.setPassword(account, any()) } just runs - every { tokenAuthenticator.refreshToken(refreshToken) } returns "" + every { tokenAuthenticator.refreshToken(account, refreshToken) } returns "" val authToken = accountAuthenticator.getAuthToken(mockk(), account, authTokenType, bundleOf()) val parcelable = authToken.get(AccountManager.KEY_INTENT) as Intent @@ -273,7 +274,8 @@ class AccountAuthenticatorTest : RobolectricTest() { val refreshToken = "refreshToken" every { accountManager.getPassword(account) } returns refreshToken - every { tokenAuthenticator.refreshToken(refreshToken) } returns "newAccessToken" + every { accountManager.setPassword(account, any()) } just runs + every { tokenAuthenticator.refreshToken(account, refreshToken) } returns "newAccessToken" val authTokenBundle: Bundle = accountAuthenticator.getAuthToken(null, account, authTokenType, bundleOf()) @@ -291,7 +293,7 @@ class AccountAuthenticatorTest : RobolectricTest() { val refreshToken = "refreshToken" every { accountManager.getPassword(account) } returns refreshToken - every { tokenAuthenticator.refreshToken(refreshToken) } throws + every { tokenAuthenticator.refreshToken(account, refreshToken) } throws HttpException( mockk { every { code() } returns 0 @@ -314,7 +316,7 @@ class AccountAuthenticatorTest : RobolectricTest() { val refreshToken = "refreshToken" every { accountManager.getPassword(account) } returns refreshToken - every { tokenAuthenticator.refreshToken(refreshToken) } throws UnknownHostException() + every { tokenAuthenticator.refreshToken(account, refreshToken) } throws UnknownHostException() val authTokenBundle: Bundle = accountAuthenticator.getAuthToken(null, account, authTokenType, bundleOf()) @@ -330,7 +332,7 @@ class AccountAuthenticatorTest : RobolectricTest() { val refreshToken = "refreshToken" every { accountManager.getPassword(account) } returns refreshToken - every { tokenAuthenticator.refreshToken(refreshToken) } throws RuntimeException() + every { tokenAuthenticator.refreshToken(account, refreshToken) } throws RuntimeException() val authTokenBundle = accountAuthenticator.getAuthToken(null, account, authTokenType, bundleOf()) diff --git a/android/engine/src/test/java/org/smartregister/fhircore/engine/auth/TokenAuthenticatorTest.kt b/android/engine/src/test/java/org/smartregister/fhircore/engine/auth/TokenAuthenticatorTest.kt index f2037ccd90..416f3e9b6e 100644 --- a/android/engine/src/test/java/org/smartregister/fhircore/engine/auth/TokenAuthenticatorTest.kt +++ b/android/engine/src/test/java/org/smartregister/fhircore/engine/auth/TokenAuthenticatorTest.kt @@ -34,6 +34,7 @@ import io.mockk.mockk import io.mockk.runs import io.mockk.slot import io.mockk.spyk +import io.mockk.verify import io.mockk.verifyOrder import java.io.IOException import java.net.UnknownHostException @@ -388,6 +389,7 @@ class TokenAuthenticatorTest : RobolectricTest() { @Test fun testRefreshTokenShouldReturnToken() { + val account = Account(sampleUsername, PROVIDER) val accessToken = "soRefreshingNewToken" val oAuthResponse = OAuthResponse( @@ -398,11 +400,13 @@ class TokenAuthenticatorTest : RobolectricTest() { scope = SCOPE ) coEvery { oAuthService.fetchToken(any()) } returns oAuthResponse + every { accountManager.setPassword(account, any()) } just runs val currentRefreshToken = "oldRefreshToken" - val newAccessToken = tokenAuthenticator.refreshToken(currentRefreshToken) + val newAccessToken = tokenAuthenticator.refreshToken(account, currentRefreshToken) Assert.assertNotNull(newAccessToken) Assert.assertEquals(accessToken, newAccessToken) + verify { accountManager.setPassword(eq(account), oAuthResponse.refreshToken) } } @OptIn(ExperimentalCoroutinesApi::class) From 96d01d0198b82a2120be1ee329daebf90484421a Mon Sep 17 00:00:00 2001 From: Christopher Seven Phiri Date: Wed, 24 Jan 2024 11:29:44 +0200 Subject: [PATCH 3/3] [MWCore] Internal release 0.1.21 - Prod 0.0.9 (#2993) --- android/quest/build.gradle | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/android/quest/build.gradle b/android/quest/build.gradle index 334ad41e5d..84373e17d4 100644 --- a/android/quest/build.gradle +++ b/android/quest/build.gradle @@ -173,22 +173,22 @@ android { dimension "apps" applicationIdSuffix ".mwcore" versionNameSuffix "-mwcore" - versionCode 30 - versionName "0.1.20" + versionCode 31 + versionName "0.1.21" } mwcoreDev { dimension "apps" applicationIdSuffix ".mwcoreDev" versionNameSuffix "-mwcoreDev" - versionCode 30 - versionName "0.1.20" + versionCode 31 + versionName "0.1.21" } mwcoreProd { dimension "apps" applicationIdSuffix ".mwcoreProd" versionNameSuffix "-mwcoreProd" - versionCode 8 - versionName "0.0.8" + versionCode 9 + versionName "0.0.9" } afyayangu { dimension "apps"