Rename OIDC components and variables to OAuth (#6686)

* Rename `OIDC` components and variables to `OAuth`. This matches the new behavior in the SDK.
This commit is contained in:
Jorge Martin Espinosa 2026-04-29 11:41:47 +02:00 committed by GitHub
parent 414da30d33
commit 1ef74f0cde
96 changed files with 479 additions and 482 deletions

View file

@ -103,13 +103,13 @@ android {
logger.warnInBox("Building ${defaultConfig.applicationId} ($baseAppName) [$buildType]") logger.warnInBox("Building ${defaultConfig.applicationId} ($baseAppName) [$buildType]")
buildTypes { buildTypes {
val oidcRedirectSchemeBase = BuildTimeConfig.METADATA_HOST_REVERSED ?: "io.element.android" val oAuthRedirectSchemeBase = BuildTimeConfig.METADATA_HOST_REVERSED ?: "io.element.android"
getByName("debug") { getByName("debug") {
resValue("string", "app_name", "$baseAppName dbg") resValue("string", "app_name", "$baseAppName dbg")
resValue( resValue(
"string", "string",
"login_redirect_scheme", "login_redirect_scheme",
"$oidcRedirectSchemeBase.debug", "$oAuthRedirectSchemeBase.debug",
) )
applicationIdSuffix = ".debug" applicationIdSuffix = ".debug"
signingConfig = signingConfigs.getByName("debug") signingConfig = signingConfigs.getByName("debug")
@ -120,7 +120,7 @@ android {
resValue( resValue(
"string", "string",
"login_redirect_scheme", "login_redirect_scheme",
oidcRedirectSchemeBase, oAuthRedirectSchemeBase,
) )
signingConfig = signingConfigs.getByName("debug") signingConfig = signingConfigs.getByName("debug")
@ -157,7 +157,7 @@ android {
resValue( resValue(
"string", "string",
"login_redirect_scheme", "login_redirect_scheme",
"$oidcRedirectSchemeBase.nightly", "$oAuthRedirectSchemeBase.nightly",
) )
matchingFallbacks += listOf("release") matchingFallbacks += listOf("release")
signingConfig = signingConfigs.getByName("nightly") signingConfig = signingConfigs.getByName("nightly")

View file

@ -75,7 +75,7 @@
android:scheme="elementx" /> android:scheme="elementx" />
</intent-filter> </intent-filter>
<!-- <!--
Oidc redirection OAuth redirection
--> -->
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />

View file

@ -10,14 +10,14 @@ package io.element.android.x.oidc
import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.matrix.api.auth.OidcRedirectUrlProvider import io.element.android.libraries.matrix.api.auth.OAuthRedirectUrlProvider
import io.element.android.services.toolbox.api.strings.StringProvider import io.element.android.services.toolbox.api.strings.StringProvider
import io.element.android.x.R import io.element.android.x.R
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class DefaultOidcRedirectUrlProvider( class DefaultOAuthRedirectUrlProvider(
private val stringProvider: StringProvider, private val stringProvider: StringProvider,
) : OidcRedirectUrlProvider { ) : OAuthRedirectUrlProvider {
override fun provide() = buildString { override fun provide() = buildString {
append(stringProvider.getString(R.string.login_redirect_scheme)) append(stringProvider.getString(R.string.login_redirect_scheme))
append(":/") append(":/")

View file

@ -13,13 +13,13 @@ import io.element.android.services.toolbox.test.strings.FakeStringProvider
import io.element.android.x.R import io.element.android.x.R
import org.junit.Test import org.junit.Test
class DefaultOidcRedirectUrlProviderTest { class DefaultOAuthRedirectUrlProviderTest {
@Test @Test
fun `test provide`() { fun `test provide`() {
val stringProvider = FakeStringProvider( val stringProvider = FakeStringProvider(
defaultResult = "str" defaultResult = "str"
) )
val sut = DefaultOidcRedirectUrlProvider( val sut = DefaultOAuthRedirectUrlProvider(
stringProvider = stringProvider, stringProvider = stringProvider,
) )
val result = sut.provide() val result = sut.provide()

View file

@ -33,7 +33,7 @@ dependencies {
implementation(projects.libraries.deeplink.api) implementation(projects.libraries.deeplink.api)
implementation(projects.libraries.featureflag.api) implementation(projects.libraries.featureflag.api)
implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrix.api)
implementation(projects.libraries.oidc.api) implementation(projects.libraries.oauth.api)
implementation(projects.libraries.preferences.api) implementation(projects.libraries.preferences.api)
implementation(projects.libraries.push.api) implementation(projects.libraries.push.api)
implementation(projects.libraries.pushproviders.api) implementation(projects.libraries.pushproviders.api)
@ -59,7 +59,7 @@ dependencies {
testImplementation(projects.features.login.test) testImplementation(projects.features.login.test)
testImplementation(projects.features.share.test) testImplementation(projects.features.share.test)
testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.oidc.test) testImplementation(projects.libraries.oauth.test)
testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.preferences.test)
testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.push.test)
testImplementation(projects.libraries.pushproviders.test) testImplementation(projects.libraries.pushproviders.test)

View file

@ -63,8 +63,8 @@ import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.core.asEventId import io.element.android.libraries.matrix.api.core.asEventId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
import io.element.android.libraries.oidc.api.OidcActionFlow import io.element.android.libraries.oauth.api.OAuthActionFlow
import io.element.android.libraries.sessionstorage.api.LoggedInState import io.element.android.libraries.sessionstorage.api.LoggedInState
import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.ui.common.nodes.emptyNode import io.element.android.libraries.ui.common.nodes.emptyNode
@ -95,7 +95,7 @@ class RootFlowNode(
private val signedOutEntryPoint: SignedOutEntryPoint, private val signedOutEntryPoint: SignedOutEntryPoint,
private val accountSelectEntryPoint: AccountSelectEntryPoint, private val accountSelectEntryPoint: AccountSelectEntryPoint,
private val intentResolver: IntentResolver, private val intentResolver: IntentResolver,
private val oidcActionFlow: OidcActionFlow, private val oAuthActionFlow: OAuthActionFlow,
private val featureFlagService: FeatureFlagService, private val featureFlagService: FeatureFlagService,
private val announcementService: AnnouncementService, private val announcementService: AnnouncementService,
private val analyticsService: AnalyticsService, private val analyticsService: AnalyticsService,
@ -392,7 +392,7 @@ class RootFlowNode(
navigateTo(resolvedIntent.deeplinkData) navigateTo(resolvedIntent.deeplinkData)
} }
is ResolvedIntent.Login -> onLoginLink(resolvedIntent.params) is ResolvedIntent.Login -> onLoginLink(resolvedIntent.params)
is ResolvedIntent.Oidc -> onOidcAction(resolvedIntent.oidcAction) is ResolvedIntent.OAuth -> onOAuthAction(resolvedIntent.oAuthAction)
is ResolvedIntent.Permalink -> navigateTo(resolvedIntent.permalinkData) is ResolvedIntent.Permalink -> navigateTo(resolvedIntent.permalinkData)
is ResolvedIntent.IncomingShare -> onIncomingShare(resolvedIntent.shareIntentData) is ResolvedIntent.IncomingShare -> onIncomingShare(resolvedIntent.shareIntentData)
} }
@ -529,8 +529,8 @@ class RootFlowNode(
} }
} }
private fun onOidcAction(oidcAction: OidcAction) { private fun onOAuthAction(oAuthAction: OAuthAction) {
oidcActionFlow.post(oidcAction) oAuthActionFlow.post(oAuthAction)
} }
private suspend fun attachSession(sessionId: SessionId): LoggedInFlowNode { private suspend fun attachSession(sessionId: SessionId): LoggedInFlowNode {

View file

@ -18,13 +18,13 @@ import io.element.android.libraries.deeplink.api.DeeplinkData
import io.element.android.libraries.deeplink.api.DeeplinkParser import io.element.android.libraries.deeplink.api.DeeplinkParser
import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
import io.element.android.libraries.oidc.api.OidcIntentResolver import io.element.android.libraries.oauth.api.OAuthIntentResolver
import timber.log.Timber import timber.log.Timber
sealed interface ResolvedIntent { sealed interface ResolvedIntent {
data class Navigation(val deeplinkData: DeeplinkData) : ResolvedIntent data class Navigation(val deeplinkData: DeeplinkData) : ResolvedIntent
data class Oidc(val oidcAction: OidcAction) : ResolvedIntent data class OAuth(val oAuthAction: OAuthAction) : ResolvedIntent
data class Permalink(val permalinkData: PermalinkData) : ResolvedIntent data class Permalink(val permalinkData: PermalinkData) : ResolvedIntent
data class Login(val params: LoginParams) : ResolvedIntent data class Login(val params: LoginParams) : ResolvedIntent
data class IncomingShare(val shareIntentData: ShareIntentData) : ResolvedIntent data class IncomingShare(val shareIntentData: ShareIntentData) : ResolvedIntent
@ -34,7 +34,7 @@ sealed interface ResolvedIntent {
class IntentResolver( class IntentResolver(
private val deeplinkParser: DeeplinkParser, private val deeplinkParser: DeeplinkParser,
private val loginIntentResolver: LoginIntentResolver, private val loginIntentResolver: LoginIntentResolver,
private val oidcIntentResolver: OidcIntentResolver, private val oAuthIntentResolver: OAuthIntentResolver,
private val permalinkParser: PermalinkParser, private val permalinkParser: PermalinkParser,
private val shareIntentHandler: ShareIntentHandler, private val shareIntentHandler: ShareIntentHandler,
) { ) {
@ -45,9 +45,9 @@ class IntentResolver(
val deepLinkData = deeplinkParser.getFromIntent(intent) val deepLinkData = deeplinkParser.getFromIntent(intent)
if (deepLinkData != null) return ResolvedIntent.Navigation(deepLinkData) if (deepLinkData != null) return ResolvedIntent.Navigation(deepLinkData)
// Coming during login using Oidc? // Coming during login using OAuth?
val oidcAction = oidcIntentResolver.resolve(intent) val oAuthAction = oAuthIntentResolver.resolve(intent)
if (oidcAction != null) return ResolvedIntent.Oidc(oidcAction) if (oAuthAction != null) return ResolvedIntent.OAuth(oAuthAction)
val actionViewData = intent val actionViewData = intent
.takeIf { it.action == Intent.ACTION_VIEW } .takeIf { it.action == Intent.ACTION_VIEW }

View file

@ -26,8 +26,8 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.A_THREAD_ID import io.element.android.libraries.matrix.test.A_THREAD_ID
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
import io.element.android.libraries.oidc.test.FakeOidcIntentResolver import io.element.android.libraries.oauth.test.FakeOAuthIntentResolver
import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaError
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@ -170,9 +170,9 @@ class IntentResolverTest {
} }
@Test @Test
fun `test resolve oidc`() { fun `test resolve OAuth`() {
val sut = createIntentResolver( val sut = createIntentResolver(
oidcIntentResolverResult = { OidcAction.GoBack() }, oAuthIntentResolverResult = { OAuthAction.GoBack() },
) )
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
action = Intent.ACTION_VIEW action = Intent.ACTION_VIEW
@ -180,8 +180,8 @@ class IntentResolverTest {
} }
val result = sut.resolve(intent) val result = sut.resolve(intent)
assertThat(result).isEqualTo( assertThat(result).isEqualTo(
ResolvedIntent.Oidc( ResolvedIntent.OAuth(
oidcAction = OidcAction.GoBack() oAuthAction = OAuthAction.GoBack()
) )
) )
} }
@ -194,7 +194,7 @@ class IntentResolverTest {
val sut = createIntentResolver( val sut = createIntentResolver(
loginIntentResolverResult = { null }, loginIntentResolverResult = { null },
permalinkParserResult = { permalinkData }, permalinkParserResult = { permalinkData },
oidcIntentResolverResult = { null }, oAuthIntentResolverResult = { null },
) )
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
action = Intent.ACTION_VIEW action = Intent.ACTION_VIEW
@ -213,7 +213,7 @@ class IntentResolverTest {
val sut = createIntentResolver( val sut = createIntentResolver(
permalinkParserResult = { PermalinkData.FallbackLink(Uri.parse("https://matrix.org")) }, permalinkParserResult = { PermalinkData.FallbackLink(Uri.parse("https://matrix.org")) },
loginIntentResolverResult = { null }, loginIntentResolverResult = { null },
oidcIntentResolverResult = { null }, oAuthIntentResolverResult = { null },
) )
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
action = Intent.ACTION_VIEW action = Intent.ACTION_VIEW
@ -230,7 +230,7 @@ class IntentResolverTest {
) )
val sut = createIntentResolver( val sut = createIntentResolver(
permalinkParserResult = { permalinkData }, permalinkParserResult = { permalinkData },
oidcIntentResolverResult = { null }, oAuthIntentResolverResult = { null },
) )
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
action = Intent.ACTION_BATTERY_LOW action = Intent.ACTION_BATTERY_LOW
@ -244,7 +244,7 @@ class IntentResolverTest {
fun `test incoming share simple`() { fun `test incoming share simple`() {
val shareIntentData = ShareIntentData.PlainText("Hello") val shareIntentData = ShareIntentData.PlainText("Hello")
val sut = createIntentResolver( val sut = createIntentResolver(
oidcIntentResolverResult = { null }, oAuthIntentResolverResult = { null },
onIncomingShareIntent = { shareIntentData }, onIncomingShareIntent = { shareIntentData },
) )
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
@ -260,7 +260,7 @@ class IntentResolverTest {
val fileUri = "content://com.example.app/file1.jpg".toUri() val fileUri = "content://com.example.app/file1.jpg".toUri()
val shareIntentData = ShareIntentData.Uris(text = "Hello", uris = listOf(UriToShare(fileUri, "image/jpg"))) val shareIntentData = ShareIntentData.Uris(text = "Hello", uris = listOf(UriToShare(fileUri, "image/jpg")))
val sut = createIntentResolver( val sut = createIntentResolver(
oidcIntentResolverResult = { null }, oAuthIntentResolverResult = { null },
onIncomingShareIntent = { shareIntentData }, onIncomingShareIntent = { shareIntentData },
) )
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
@ -277,7 +277,7 @@ class IntentResolverTest {
val sut = createIntentResolver( val sut = createIntentResolver(
permalinkParserResult = { PermalinkData.FallbackLink(Uri.parse("https://matrix.org")) }, permalinkParserResult = { PermalinkData.FallbackLink(Uri.parse("https://matrix.org")) },
loginIntentResolverResult = { null }, loginIntentResolverResult = { null },
oidcIntentResolverResult = { null }, oAuthIntentResolverResult = { null },
) )
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
action = Intent.ACTION_VIEW action = Intent.ACTION_VIEW
@ -292,7 +292,7 @@ class IntentResolverTest {
val aLoginParams = LoginParams("accountProvider", null) val aLoginParams = LoginParams("accountProvider", null)
val sut = createIntentResolver( val sut = createIntentResolver(
loginIntentResolverResult = { aLoginParams }, loginIntentResolverResult = { aLoginParams },
oidcIntentResolverResult = { null }, oAuthIntentResolverResult = { null },
) )
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
action = Intent.ACTION_VIEW action = Intent.ACTION_VIEW
@ -306,7 +306,7 @@ class IntentResolverTest {
deeplinkParserResult: DeeplinkData? = null, deeplinkParserResult: DeeplinkData? = null,
permalinkParserResult: (String) -> PermalinkData = { lambdaError() }, permalinkParserResult: (String) -> PermalinkData = { lambdaError() },
loginIntentResolverResult: (String) -> LoginParams? = { lambdaError() }, loginIntentResolverResult: (String) -> LoginParams? = { lambdaError() },
oidcIntentResolverResult: (Intent) -> OidcAction? = { lambdaError() }, oAuthIntentResolverResult: (Intent) -> OAuthAction? = { lambdaError() },
onIncomingShareIntent: (Intent) -> ShareIntentData? = { null }, onIncomingShareIntent: (Intent) -> ShareIntentData? = { null },
): IntentResolver { ): IntentResolver {
return IntentResolver( return IntentResolver(
@ -314,8 +314,8 @@ class IntentResolverTest {
loginIntentResolver = FakeLoginIntentResolver( loginIntentResolver = FakeLoginIntentResolver(
parseResult = loginIntentResolverResult, parseResult = loginIntentResolverResult,
), ),
oidcIntentResolver = FakeOidcIntentResolver( oAuthIntentResolver = FakeOAuthIntentResolver(
resolveResult = oidcIntentResolverResult, resolveResult = oAuthIntentResolverResult,
), ),
permalinkParser = FakePermalinkParser( permalinkParser = FakePermalinkParser(
result = permalinkParserResult result = permalinkParserResult

View file

@ -21,7 +21,7 @@ import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.RecoveryState import io.element.android.libraries.matrix.api.encryption.RecoveryState
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.oauth.AccountManagementAction
import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion
import io.element.android.libraries.matrix.api.sync.SyncState import io.element.android.libraries.matrix.api.sync.SyncState

View file

@ -1,4 +1,4 @@
This file contains some rough notes about Oidc implementation, with some examples of actual data. This file contains some rough notes about OAuth implementation, with some examples of actual data.
[ios implementation](https://github.com/element-hq/element-x-ios/compare/develop...doug/oidc-temp) [ios implementation](https://github.com/element-hq/element-x-ios/compare/develop...doug/oidc-temp)
@ -25,7 +25,7 @@ tosUri = "https://element.io/user-terms-of-service",
policyUri = "https://element.io/privacy" policyUri = "https://element.io/privacy"
Example of OidcData (from presentUrl callback): Example of OAuthData (from presentUrl callback):
url: https://auth-oidc.lab.element.dev/authorize?response_type=code&client_id=01GYCAGG3PA70CJ97ZVP0WFJY3&redirect_uri=io.element%3A%2Fcallback&scope=openid+urn%3Amatrix%3Aorg.matrix.msc2967.client%3Aapi%3A*+urn%3Amatrix%3Aorg.matrix.msc2967.client%3Adevice%3AYAgcPW4mcG&state=ex6mNJVFZ5jn9wL8&nonce=NZ93DOyIGQd9exPQ&code_challenge_method=S256&code_challenge=FFRcPALNSPCh-ZgpyTRFu_h8NZJVncfvihbfT9CyX8U&prompt=consent url: https://auth-oidc.lab.element.dev/authorize?response_type=code&client_id=01GYCAGG3PA70CJ97ZVP0WFJY3&redirect_uri=io.element%3A%2Fcallback&scope=openid+urn%3Amatrix%3Aorg.matrix.msc2967.client%3Aapi%3A*+urn%3Amatrix%3Aorg.matrix.msc2967.client%3Adevice%3AYAgcPW4mcG&state=ex6mNJVFZ5jn9wL8&nonce=NZ93DOyIGQd9exPQ&code_challenge_method=S256&code_challenge=FFRcPALNSPCh-ZgpyTRFu_h8NZJVncfvihbfT9CyX8U&prompt=consent
Formatted url: Formatted url:
@ -43,8 +43,8 @@ https://auth-oidc.lab.element.dev/authorize?
state: ex6mNJVFZ5jn9wL8 state: ex6mNJVFZ5jn9wL8
Oidc client example: https://github.com/matrix-org/matrix-rust-sdk/blob/39ad8a46801fb4317a777ebf895822b3675b709c/examples/oidc_cli/src/main.rs OAuth client example: https://github.com/matrix-org/matrix-rust-sdk/blob/39ad8a46801fb4317a777ebf895822b3675b709c/examples/oidc_cli/src/main.rs
Oidc sdk doc: https://github.com/matrix-org/matrix-rust-sdk/blob/39ad8a46801fb4317a777ebf895822b3675b709c/crates/matrix-sdk/src/oidc.rs OAuth sdk doc: https://github.com/matrix-org/matrix-rust-sdk/blob/39ad8a46801fb4317a777ebf895822b3675b709c/crates/matrix-sdk/src/oidc.rs
Test server: Test server:

View file

@ -43,7 +43,7 @@ dependencies {
implementation(projects.libraries.permissions.api) implementation(projects.libraries.permissions.api)
implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.sessionStorage.api)
implementation(projects.libraries.qrcode) implementation(projects.libraries.qrcode)
implementation(projects.libraries.oidc.api) implementation(projects.libraries.oauth.api)
implementation(projects.libraries.uiUtils) implementation(projects.libraries.uiUtils)
implementation(projects.libraries.wellknown.api) implementation(projects.libraries.wellknown.api)
implementation(libs.androidx.browser) implementation(libs.androidx.browser)
@ -56,7 +56,7 @@ dependencies {
testImplementation(projects.features.enterprise.test) testImplementation(projects.features.enterprise.test)
testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.featureflag.test)
testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.oidc.test) testImplementation(projects.libraries.oauth.test)
testImplementation(projects.libraries.permissions.test) testImplementation(projects.libraries.permissions.test)
testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.libraries.sessionStorage.test)
testImplementation(projects.libraries.wellknown.test) testImplementation(projects.libraries.wellknown.test)

View file

@ -69,7 +69,7 @@ dependencies {
implementation(projects.libraries.permissions.api) implementation(projects.libraries.permissions.api)
implementation(projects.libraries.sessionStorage.api) implementation(projects.libraries.sessionStorage.api)
implementation(projects.libraries.qrcode) implementation(projects.libraries.qrcode)
implementation(projects.libraries.oidc.api) implementation(projects.libraries.oauth.api)
implementation(projects.libraries.uiUtils) implementation(projects.libraries.uiUtils)
implementation(projects.libraries.wellknown.api) implementation(projects.libraries.wellknown.api)
implementation(libs.androidx.browser) implementation(libs.androidx.browser)
@ -83,7 +83,7 @@ dependencies {
testImplementation(projects.features.preferences.test) testImplementation(projects.features.preferences.test)
testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.featureflag.test)
testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.oidc.test) testImplementation(projects.libraries.oauth.test)
testImplementation(projects.libraries.permissions.test) testImplementation(projects.libraries.permissions.test)
testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.libraries.sessionStorage.test)
testImplementation(projects.libraries.wellknown.test) testImplementation(projects.libraries.wellknown.test)

View file

@ -50,9 +50,9 @@ import io.element.android.libraries.architecture.callback
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.annotations.AppCoroutineScope import io.element.android.libraries.di.annotations.AppCoroutineScope
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
import io.element.android.libraries.oidc.api.OidcActionFlow import io.element.android.libraries.oauth.api.OAuthActionFlow
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -64,7 +64,7 @@ class LoginFlowNode(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
private val accountProviderDataSource: AccountProviderDataSource, private val accountProviderDataSource: AccountProviderDataSource,
private val oidcActionFlow: OidcActionFlow, private val oAuthActionFlow: OAuthActionFlow,
@AppCoroutineScope @AppCoroutineScope
private val appCoroutineScope: CoroutineScope, private val appCoroutineScope: CoroutineScope,
private val elementClassicConnection: ElementClassicConnection, private val elementClassicConnection: ElementClassicConnection,
@ -100,7 +100,7 @@ class LoginFlowNode(
// by pressing back or by closing the Custom Chrome Tab. // by pressing back or by closing the Custom Chrome Tab.
lifecycleScope.launch { lifecycleScope.launch {
delay(5000) delay(5000)
oidcActionFlow.post(OidcAction.GoBack(toUnblock = true)) oAuthActionFlow.post(OAuthAction.GoBack(toUnblock = true))
} }
} }
} }
@ -161,8 +161,8 @@ class LoginFlowNode(
backstack.push(NavTarget.LoginPassword()) backstack.push(NavTarget.LoginPassword())
} }
override fun navigateToOidc(oidcDetails: OidcDetails) { override fun navigateToOAuth(oAuthDetails: OAuthDetails) {
navigateToMas(oidcDetails) navigateToMas(oAuthDetails)
} }
override fun navigateToCreateAccount(url: String) { override fun navigateToCreateAccount(url: String) {
@ -197,8 +197,8 @@ class LoginFlowNode(
callback.navigateToBugReport() callback.navigateToBugReport()
} }
override fun navigateToOidc(oidcDetails: OidcDetails) { override fun navigateToOAuth(oAuthDetails: OAuthDetails) {
navigateToMas(oidcDetails) navigateToMas(oAuthDetails)
} }
override fun navigateToCreateAccount(url: String) { override fun navigateToCreateAccount(url: String) {
@ -243,8 +243,8 @@ class LoginFlowNode(
} }
NavTarget.ChooseAccountProvider -> { NavTarget.ChooseAccountProvider -> {
val callback = object : ChooseAccountProviderNode.Callback { val callback = object : ChooseAccountProviderNode.Callback {
override fun navigateToOidc(oidcDetails: OidcDetails) { override fun navigateToOAuth(oAuthDetails: OAuthDetails) {
navigateToMas(oidcDetails) navigateToMas(oAuthDetails)
} }
override fun navigateToCreateAccount(url: String) { override fun navigateToCreateAccount(url: String) {
@ -270,8 +270,8 @@ class LoginFlowNode(
isAccountCreation = navTarget.isAccountCreation, isAccountCreation = navTarget.isAccountCreation,
) )
val callback = object : ConfirmAccountProviderNode.Callback { val callback = object : ConfirmAccountProviderNode.Callback {
override fun navigateToOidc(oidcDetails: OidcDetails) { override fun navigateToOAuth(oAuthDetails: OAuthDetails) {
navigateToMas(oidcDetails) navigateToMas(oAuthDetails)
} }
override fun navigateToCreateAccount(url: String) { override fun navigateToCreateAccount(url: String) {
@ -333,10 +333,10 @@ class LoginFlowNode(
} }
} }
private fun navigateToMas(oidcDetails: OidcDetails) { private fun navigateToMas(oAuthDetails: OAuthDetails) {
activity?.let { activity?.let {
externalAppStarted = true externalAppStarted = true
it.openUrlInChromeCustomTab(null, darkTheme, oidcDetails.url) it.openUrlInChromeCustomTab(null, darkTheme, oAuthDetails.url)
} }
} }

View file

@ -41,7 +41,7 @@ sealed class ChangeServerError : Exception() {
// AccountAlreadyLoggedIn error should not happen at this point // AccountAlreadyLoggedIn error should not happen at this point
is AuthenticationException.AccountAlreadyLoggedIn -> Error(messageStr = error.message) is AuthenticationException.AccountAlreadyLoggedIn -> Error(messageStr = error.message)
is AuthenticationException.Generic -> Error(messageStr = error.message) is AuthenticationException.Generic -> Error(messageStr = error.message)
is AuthenticationException.Oidc -> Error(messageStr = error.message) is AuthenticationException.OAuth -> Error(messageStr = error.message)
} }
} }
is AccountProviderAccessException.NeedElementProException -> NeedElementPro( is AccountProviderAccessException.NeedElementProException -> NeedElementPro(

View file

@ -23,9 +23,9 @@ import io.element.android.features.login.impl.web.WebClientUrlForAuthenticationR
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.architecture.runCatchingUpdatingState
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.api.auth.OidcPrompt import io.element.android.libraries.matrix.api.auth.OAuthPrompt
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
import io.element.android.libraries.oidc.api.OidcActionFlow import io.element.android.libraries.oauth.api.OAuthActionFlow
/** /**
* This class is responsible for managing the login flow, including handling OIDC actions and * This class is responsible for managing the login flow, including handling OIDC actions and
@ -35,7 +35,7 @@ import io.element.android.libraries.oidc.api.OidcActionFlow
*/ */
@Inject @Inject
class LoginHelper( class LoginHelper(
private val oidcActionFlow: OidcActionFlow, private val oAuthActionFlow: OAuthActionFlow,
private val authenticationService: MatrixAuthenticationService, private val authenticationService: MatrixAuthenticationService,
private val webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever, private val webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever,
) { ) {
@ -44,9 +44,9 @@ class LoginHelper(
@Composable @Composable
fun collectLoginMode(): State<AsyncData<LoginMode>> { fun collectLoginMode(): State<AsyncData<LoginMode>> {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
oidcActionFlow.collect { oidcAction -> oAuthActionFlow.collect { oAuthAction ->
if (oidcAction != null) { if (oAuthAction != null) {
onOidcAction(oidcAction) onOAuthAction(oAuthAction)
} }
} }
} }
@ -73,11 +73,11 @@ class LoginHelper(
throw it throw it
} }
}.map { matrixHomeServerDetails -> }.map { matrixHomeServerDetails ->
if (matrixHomeServerDetails.supportsOidcLogin) { if (matrixHomeServerDetails.supportsOAuthLogin) {
// Retrieve the details right now // Retrieve the details right now
val oidcPrompt = if (isAccountCreation) OidcPrompt.Create else OidcPrompt.Login val oAuthPrompt = if (isAccountCreation) OAuthPrompt.Create else OAuthPrompt.Login
LoginMode.Oidc( LoginMode.OAuth(
authenticationService.getOidcUrl(prompt = oidcPrompt, loginHint = loginHint).getOrThrow() authenticationService.getOAuthUrl(prompt = oAuthPrompt, loginHint = loginHint).getOrThrow()
) )
} else if (isAccountCreation) { } else if (isAccountCreation) {
val url = webClientUrlForAuthenticationRetriever.retrieve(homeserverUrl) val url = webClientUrlForAuthenticationRetriever.retrieve(homeserverUrl)
@ -99,16 +99,16 @@ class LoginHelper(
) )
} }
private suspend fun onOidcAction(oidcAction: OidcAction) { private suspend fun onOAuthAction(oAuthAction: OAuthAction) {
if (oidcAction is OidcAction.GoBack && oidcAction.toUnblock && loginModeState.value !is AsyncData.Loading) { if (oAuthAction is OAuthAction.GoBack && oAuthAction.toUnblock && loginModeState.value !is AsyncData.Loading) {
// Ignore GoBack action if the current state is not Loading. This GoBack action is coming from LoginFlowNode. // Ignore GoBack action if the current state is not Loading. This GoBack action is coming from LoginFlowNode.
// This can happen if there is an error, for instance attempt to login again on the same account. // This can happen if there is an error, for instance attempt to login again on the same account.
return return
} }
loginModeState.value = AsyncData.Loading() loginModeState.value = AsyncData.Loading()
when (oidcAction) { when (oAuthAction) {
is OidcAction.GoBack -> { is OAuthAction.GoBack -> {
authenticationService.cancelOidcLogin() authenticationService.cancelOAuthLogin()
.onSuccess { .onSuccess {
loginModeState.value = AsyncData.Uninitialized loginModeState.value = AsyncData.Uninitialized
} }
@ -116,13 +116,13 @@ class LoginHelper(
loginModeState.value = AsyncData.Failure(failure) loginModeState.value = AsyncData.Failure(failure)
} }
} }
is OidcAction.Success -> { is OAuthAction.Success -> {
authenticationService.loginWithOidc(oidcAction.url) authenticationService.loginWithOAuth(oAuthAction.url)
.onFailure { failure -> .onFailure { failure ->
loginModeState.value = AsyncData.Failure(failure) loginModeState.value = AsyncData.Failure(failure)
} }
} }
} }
oidcActionFlow.reset() oAuthActionFlow.reset()
} }
} }

View file

@ -8,10 +8,10 @@
package io.element.android.features.login.impl.login package io.element.android.features.login.impl.login
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
sealed interface LoginMode { sealed interface LoginMode {
data object PasswordLogin : LoginMode data object PasswordLogin : LoginMode
data class Oidc(val oidcDetails: OidcDetails) : LoginMode data class OAuth(val oAuthDetails: OAuthDetails) : LoginMode
data class AccountCreation(val url: String) : LoginMode data class AccountCreation(val url: String) : LoginMode
} }

View file

@ -24,7 +24,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.LocalBuildMeta import io.element.android.libraries.designsystem.theme.LocalBuildMeta
import io.element.android.libraries.matrix.api.auth.AuthenticationException import io.element.android.libraries.matrix.api.auth.AuthenticationException
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
@ -32,7 +32,7 @@ fun LoginModeView(
loginMode: AsyncData<LoginMode>, loginMode: AsyncData<LoginMode>,
onClearError: () -> Unit, onClearError: () -> Unit,
onLearnMoreClick: () -> Unit, onLearnMoreClick: () -> Unit,
onOidcDetails: (OidcDetails) -> Unit, onOAuthDetails: (OAuthDetails) -> Unit,
onNeedLoginPassword: () -> Unit, onNeedLoginPassword: () -> Unit,
onCreateAccountContinue: (url: String) -> Unit onCreateAccountContinue: (url: String) -> Unit
) { ) {
@ -118,7 +118,7 @@ fun LoginModeView(
is AsyncData.Loading -> Unit // The Continue button shows the loading state is AsyncData.Loading -> Unit // The Continue button shows the loading state
is AsyncData.Success -> { is AsyncData.Success -> {
when (val loginModeData = loginMode.data) { when (val loginModeData = loginMode.data) {
is LoginMode.Oidc -> onOidcDetails(loginModeData.oidcDetails) is LoginMode.OAuth -> onOAuthDetails(loginModeData.oAuthDetails)
LoginMode.PasswordLogin -> onNeedLoginPassword() LoginMode.PasswordLogin -> onNeedLoginPassword()
is LoginMode.AccountCreation -> onCreateAccountContinue(loginModeData.url) is LoginMode.AccountCreation -> onCreateAccountContinue(loginModeData.url)
} }
@ -137,7 +137,7 @@ internal fun LoginModeViewPreview(@PreviewParameter(LoginModeViewErrorProvider::
loginMode = AsyncData.Failure(error), loginMode = AsyncData.Failure(error),
onClearError = {}, onClearError = {},
onLearnMoreClick = {}, onLearnMoreClick = {},
onOidcDetails = {}, onOAuthDetails = {},
onNeedLoginPassword = {}, onNeedLoginPassword = {},
onCreateAccountContinue = {} onCreateAccountContinue = {}
) )

View file

@ -135,8 +135,8 @@ class QrCodeLoginFlowNode(
is QrLoginException.SlidingSyncNotAvailable -> { is QrLoginException.SlidingSyncNotAvailable -> {
backstack.replace(NavTarget.Error(QrCodeErrorScreenType.SlidingSyncNotAvailable)) backstack.replace(NavTarget.Error(QrCodeErrorScreenType.SlidingSyncNotAvailable))
} }
is QrLoginException.OidcMetadataInvalid -> { is QrLoginException.OAuthMetadataInvalid -> {
Timber.e(error, "OIDC metadata is invalid") Timber.e(error, "OAuth metadata is invalid")
backstack.replace(NavTarget.Error(QrCodeErrorScreenType.UnknownError)) backstack.replace(NavTarget.Error(QrCodeErrorScreenType.UnknownError))
} }
QrLoginException.CheckCodeAlreadySent, QrLoginException.CheckCodeAlreadySent,

View file

@ -20,7 +20,7 @@ import dev.zacsweers.metro.AssistedInject
import io.element.android.annotations.ContributesNode import io.element.android.annotations.ContributesNode
import io.element.android.features.login.impl.util.openLearnMorePage import io.element.android.features.login.impl.util.openLearnMorePage
import io.element.android.libraries.architecture.callback import io.element.android.libraries.architecture.callback
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
@ContributesNode(AppScope::class) @ContributesNode(AppScope::class)
@AssistedInject @AssistedInject
@ -31,7 +31,7 @@ class ChooseAccountProviderNode(
) : Node(buildContext, plugins = plugins) { ) : Node(buildContext, plugins = plugins) {
interface Callback : Plugin { interface Callback : Plugin {
fun navigateToLoginPassword() fun navigateToLoginPassword()
fun navigateToOidc(oidcDetails: OidcDetails) fun navigateToOAuth(oAuthDetails: OAuthDetails)
fun navigateToCreateAccount(url: String) fun navigateToCreateAccount(url: String)
} }
@ -45,7 +45,7 @@ class ChooseAccountProviderNode(
state = state, state = state,
modifier = modifier, modifier = modifier,
onBackClick = ::navigateUp, onBackClick = ::navigateUp,
onOidcDetails = callback::navigateToOidc, onOAuthDetails = callback::navigateToOAuth,
onNeedLoginPassword = callback::navigateToLoginPassword, onNeedLoginPassword = callback::navigateToLoginPassword,
onLearnMoreClick = { openLearnMorePage(context) }, onLearnMoreClick = { openLearnMorePage(context) },
onCreateAccountContinue = callback::navigateToCreateAccount, onCreateAccountContinue = callback::navigateToCreateAccount,

View file

@ -43,14 +43,14 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
fun ChooseAccountProviderView( fun ChooseAccountProviderView(
state: ChooseAccountProviderState, state: ChooseAccountProviderState,
onBackClick: () -> Unit, onBackClick: () -> Unit,
onOidcDetails: (OidcDetails) -> Unit, onOAuthDetails: (OAuthDetails) -> Unit,
onNeedLoginPassword: () -> Unit, onNeedLoginPassword: () -> Unit,
onLearnMoreClick: () -> Unit, onLearnMoreClick: () -> Unit,
onCreateAccountContinue: (url: String) -> Unit, onCreateAccountContinue: (url: String) -> Unit,
@ -129,7 +129,7 @@ fun ChooseAccountProviderView(
state.eventSink(ChooseAccountProviderEvents.ClearError) state.eventSink(ChooseAccountProviderEvents.ClearError)
}, },
onLearnMoreClick = onLearnMoreClick, onLearnMoreClick = onLearnMoreClick,
onOidcDetails = onOidcDetails, onOAuthDetails = onOAuthDetails,
onNeedLoginPassword = onNeedLoginPassword, onNeedLoginPassword = onNeedLoginPassword,
onCreateAccountContinue = onCreateAccountContinue, onCreateAccountContinue = onCreateAccountContinue,
) )
@ -144,7 +144,7 @@ internal fun ChooseAccountProviderViewPreview(@PreviewParameter(ChooseAccountPro
state = state, state = state,
onBackClick = { }, onBackClick = { },
onLearnMoreClick = { }, onLearnMoreClick = { },
onOidcDetails = { }, onOAuthDetails = { },
onNeedLoginPassword = { }, onNeedLoginPassword = { },
onCreateAccountContinue = { }, onCreateAccountContinue = { },
) )

View file

@ -31,7 +31,7 @@ import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.appyx.rememberFaderOrSliderTransitionHandler import io.element.android.libraries.architecture.appyx.rememberFaderOrSliderTransitionHandler
import io.element.android.libraries.architecture.callback import io.element.android.libraries.architecture.callback
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -54,7 +54,7 @@ class ClassicFlowNode(
interface Callback : Plugin { interface Callback : Plugin {
fun navigateToOnBoarding(allowBackNavigation: Boolean) fun navigateToOnBoarding(allowBackNavigation: Boolean)
fun navigateToLoginPassword() fun navigateToLoginPassword()
fun navigateToOidc(oidcDetails: OidcDetails) fun navigateToOAuth(oAuthDetails: OAuthDetails)
fun navigateToCreateAccount(url: String) fun navigateToCreateAccount(url: String)
} }
@ -111,8 +111,8 @@ class ClassicFlowNode(
callback.navigateToLoginPassword() callback.navigateToLoginPassword()
} }
override fun navigateToOidc(oidcDetails: OidcDetails) { override fun navigateToOAuth(oAuthDetails: OAuthDetails) {
callback.navigateToOidc(oidcDetails) callback.navigateToOAuth(oAuthDetails)
} }
override fun navigateToCreateAccount(url: String) { override fun navigateToCreateAccount(url: String) {

View file

@ -21,7 +21,7 @@ import io.element.android.features.login.impl.util.openLearnMorePage
import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.callback import io.element.android.libraries.architecture.callback
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
@ContributesNode(AppScope::class) @ContributesNode(AppScope::class)
@ -35,7 +35,7 @@ class LoginWithClassicNode(
interface Callback : Plugin { interface Callback : Plugin {
fun navigateToOtherOptions() fun navigateToOtherOptions()
fun navigateToLoginPassword() fun navigateToLoginPassword()
fun navigateToOidc(oidcDetails: OidcDetails) fun navigateToOAuth(oAuthDetails: OAuthDetails)
fun navigateToCreateAccount(url: String) fun navigateToCreateAccount(url: String)
fun navigateToMissingKeyBackup() fun navigateToMissingKeyBackup()
} }
@ -60,7 +60,7 @@ class LoginWithClassicNode(
state = state, state = state,
modifier = modifier, modifier = modifier,
onOtherOptionsClick = callback::navigateToOtherOptions, onOtherOptionsClick = callback::navigateToOtherOptions,
onOidcDetails = callback::navigateToOidc, onOAuthDetails = callback::navigateToOAuth,
onNeedLoginPassword = callback::navigateToLoginPassword, onNeedLoginPassword = callback::navigateToLoginPassword,
onLearnMoreClick = { openLearnMorePage(context) }, onLearnMoreClick = { openLearnMorePage(context) },
onCreateAccountContinue = callback::navigateToCreateAccount, onCreateAccountContinue = callback::navigateToCreateAccount,

View file

@ -49,7 +49,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.OutlinedButton
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag import io.element.android.libraries.testtags.testTag
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -59,7 +59,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
fun LoginWithClassicView( fun LoginWithClassicView(
state: LoginWithClassicState, state: LoginWithClassicState,
onOtherOptionsClick: () -> Unit, onOtherOptionsClick: () -> Unit,
onOidcDetails: (OidcDetails) -> Unit, onOAuthDetails: (OAuthDetails) -> Unit,
onNeedLoginPassword: () -> Unit, onNeedLoginPassword: () -> Unit,
onLearnMoreClick: () -> Unit, onLearnMoreClick: () -> Unit,
onCreateAccountContinue: (url: String) -> Unit, onCreateAccountContinue: (url: String) -> Unit,
@ -200,7 +200,7 @@ fun LoginWithClassicView(
state.eventSink(LoginWithClassicEvent.ClearError) state.eventSink(LoginWithClassicEvent.ClearError)
}, },
onLearnMoreClick = onLearnMoreClick, onLearnMoreClick = onLearnMoreClick,
onOidcDetails = onOidcDetails, onOAuthDetails = onOAuthDetails,
onNeedLoginPassword = onNeedLoginPassword, onNeedLoginPassword = onNeedLoginPassword,
onCreateAccountContinue = onCreateAccountContinue, onCreateAccountContinue = onCreateAccountContinue,
) )
@ -212,7 +212,7 @@ internal fun LoginWithClassicViewPreview(@PreviewParameter(LoginWithClassicState
LoginWithClassicView( LoginWithClassicView(
state = state, state = state,
onOtherOptionsClick = {}, onOtherOptionsClick = {},
onOidcDetails = {}, onOAuthDetails = {},
onNeedLoginPassword = {}, onNeedLoginPassword = {},
onLearnMoreClick = {}, onLearnMoreClick = {},
onCreateAccountContinue = {}, onCreateAccountContinue = {},

View file

@ -22,7 +22,7 @@ import io.element.android.features.login.impl.util.openLearnMorePage
import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.callback import io.element.android.libraries.architecture.callback
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
@ContributesNode(AppScope::class) @ContributesNode(AppScope::class)
@AssistedInject @AssistedInject
@ -44,7 +44,7 @@ class ConfirmAccountProviderNode(
interface Callback : Plugin { interface Callback : Plugin {
fun navigateToLoginPassword() fun navigateToLoginPassword()
fun navigateToOidc(oidcDetails: OidcDetails) fun navigateToOAuth(oAuthDetails: OAuthDetails)
fun navigateToCreateAccount(url: String) fun navigateToCreateAccount(url: String)
fun navigateToChangeAccountProvider() fun navigateToChangeAccountProvider()
} }
@ -58,7 +58,7 @@ class ConfirmAccountProviderNode(
ConfirmAccountProviderView( ConfirmAccountProviderView(
state = state, state = state,
modifier = modifier, modifier = modifier,
onOidcDetails = callback::navigateToOidc, onOAuthDetails = callback::navigateToOAuth,
onNeedLoginPassword = callback::navigateToLoginPassword, onNeedLoginPassword = callback::navigateToLoginPassword,
onCreateAccountContinue = callback::navigateToCreateAccount, onCreateAccountContinue = callback::navigateToCreateAccount,
onChange = callback::navigateToChangeAccountProvider, onChange = callback::navigateToChangeAccountProvider,

View file

@ -30,7 +30,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag import io.element.android.libraries.testtags.testTag
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -38,7 +38,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
fun ConfirmAccountProviderView( fun ConfirmAccountProviderView(
state: ConfirmAccountProviderState, state: ConfirmAccountProviderState,
onOidcDetails: (OidcDetails) -> Unit, onOAuthDetails: (OAuthDetails) -> Unit,
onNeedLoginPassword: () -> Unit, onNeedLoginPassword: () -> Unit,
onLearnMoreClick: () -> Unit, onLearnMoreClick: () -> Unit,
onCreateAccountContinue: (url: String) -> Unit, onCreateAccountContinue: (url: String) -> Unit,
@ -103,7 +103,7 @@ fun ConfirmAccountProviderView(
eventSink(ConfirmAccountProviderEvents.ClearError) eventSink(ConfirmAccountProviderEvents.ClearError)
}, },
onLearnMoreClick = onLearnMoreClick, onLearnMoreClick = onLearnMoreClick,
onOidcDetails = onOidcDetails, onOAuthDetails = onOAuthDetails,
onNeedLoginPassword = onNeedLoginPassword, onNeedLoginPassword = onNeedLoginPassword,
onCreateAccountContinue = onCreateAccountContinue, onCreateAccountContinue = onCreateAccountContinue,
) )
@ -117,7 +117,7 @@ internal fun ConfirmAccountProviderViewPreview(
) = ElementPreview { ) = ElementPreview {
ConfirmAccountProviderView( ConfirmAccountProviderView(
state = state, state = state,
onOidcDetails = {}, onOAuthDetails = {},
onNeedLoginPassword = {}, onNeedLoginPassword = {},
onCreateAccountContinue = {}, onCreateAccountContinue = {},
onLearnMoreClick = {}, onLearnMoreClick = {},

View file

@ -22,7 +22,7 @@ import io.element.android.features.login.impl.util.openLearnMorePage
import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.callback import io.element.android.libraries.architecture.callback
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
@ContributesNode(AppScope::class) @ContributesNode(AppScope::class)
@AssistedInject @AssistedInject
@ -40,7 +40,7 @@ class OnBoardingNode(
fun navigateToQrCode() fun navigateToQrCode()
fun navigateToBugReport() fun navigateToBugReport()
fun navigateToLoginPassword() fun navigateToLoginPassword()
fun navigateToOidc(oidcDetails: OidcDetails) fun navigateToOAuth(oAuthDetails: OAuthDetails)
fun navigateToCreateAccount(url: String) fun navigateToCreateAccount(url: String)
fun navigateToDeveloperSettings() fun navigateToDeveloperSettings()
fun onDone() fun onDone()
@ -71,7 +71,7 @@ class OnBoardingNode(
onCreateAccount = callback::navigateToSignUpFlow, onCreateAccount = callback::navigateToSignUpFlow,
onSignInWithQrCode = callback::navigateToQrCode, onSignInWithQrCode = callback::navigateToQrCode,
onReportProblem = callback::navigateToBugReport, onReportProblem = callback::navigateToBugReport,
onOidcDetails = callback::navigateToOidc, onOAuthDetails = callback::navigateToOAuth,
onNeedLoginPassword = callback::navigateToLoginPassword, onNeedLoginPassword = callback::navigateToLoginPassword,
onLearnMoreClick = { openLearnMorePage(context) }, onLearnMoreClick = { openLearnMorePage(context) },
onCreateAccountContinue = callback::navigateToCreateAccount, onCreateAccountContinue = callback::navigateToCreateAccount,

View file

@ -50,7 +50,7 @@ import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.IconSource
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag import io.element.android.libraries.testtags.testTag
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -68,7 +68,7 @@ fun OnBoardingView(
onSignInWithQrCode: () -> Unit, onSignInWithQrCode: () -> Unit,
onSignIn: (mustChooseAccountProvider: Boolean) -> Unit, onSignIn: (mustChooseAccountProvider: Boolean) -> Unit,
onCreateAccount: () -> Unit, onCreateAccount: () -> Unit,
onOidcDetails: (OidcDetails) -> Unit, onOAuthDetails: (OAuthDetails) -> Unit,
onNeedLoginPassword: () -> Unit, onNeedLoginPassword: () -> Unit,
onLearnMoreClick: () -> Unit, onLearnMoreClick: () -> Unit,
onCreateAccountContinue: (url: String) -> Unit, onCreateAccountContinue: (url: String) -> Unit,
@ -82,7 +82,7 @@ fun OnBoardingView(
state.eventSink(OnBoardingEvents.ClearError) state.eventSink(OnBoardingEvents.ClearError)
}, },
onLearnMoreClick = onLearnMoreClick, onLearnMoreClick = onLearnMoreClick,
onOidcDetails = onOidcDetails, onOAuthDetails = onOAuthDetails,
onNeedLoginPassword = onNeedLoginPassword, onNeedLoginPassword = onNeedLoginPassword,
onCreateAccountContinue = onCreateAccountContinue, onCreateAccountContinue = onCreateAccountContinue,
) )
@ -354,7 +354,7 @@ internal fun OnBoardingViewPreview(
onSignIn = {}, onSignIn = {},
onCreateAccount = {}, onCreateAccount = {},
onReportProblem = {}, onReportProblem = {},
onOidcDetails = {}, onOAuthDetails = {},
onNeedLoginPassword = {}, onNeedLoginPassword = {},
onLearnMoreClick = {}, onLearnMoreClick = {},
onCreateAccountContinue = {}, onCreateAccountContinue = {},

View file

@ -17,7 +17,7 @@ import io.element.android.features.login.api.LoginEntryPoint
import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource
import io.element.android.features.login.impl.classic.FakeElementClassicConnection import io.element.android.features.login.impl.classic.FakeElementClassicConnection
import io.element.android.features.preferences.test.FakePreferencesEntryPoint import io.element.android.features.preferences.test.FakePreferencesEntryPoint
import io.element.android.libraries.oidc.test.customtab.FakeOidcActionFlow import io.element.android.libraries.oauth.test.customtab.FakeOAuthActionFlow
import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.node.TestParentNode import io.element.android.tests.testutils.node.TestParentNode
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
@ -39,7 +39,7 @@ class DefaultLoginEntryPointTest {
buildContext = buildContext, buildContext = buildContext,
plugins = plugins, plugins = plugins,
accountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), accountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()),
oidcActionFlow = FakeOidcActionFlow(), oAuthActionFlow = FakeOAuthActionFlow(),
appCoroutineScope = backgroundScope, appCoroutineScope = backgroundScope,
elementClassicConnection = FakeElementClassicConnection(), elementClassicConnection = FakeElementClassicConnection(),
preferencesEntryPoint = FakePreferencesEntryPoint(), preferencesEntryPoint = FakePreferencesEntryPoint(),

View file

@ -50,7 +50,7 @@ class ChangeServerPresenterTest {
fun `present - change server ok`() = runTest { fun `present - change server ok`() = runTest {
val authenticationService = FakeMatrixAuthenticationService( val authenticationService = FakeMatrixAuthenticationService(
setHomeserverResult = { setHomeserverResult = {
Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true))
}, },
) )
createPresenter( createPresenter(

View file

@ -79,7 +79,7 @@ class QrCodeLoginFlowNodeTest {
qrCodeLoginManager.currentLoginStep.value = QrCodeLoginStep.Failed(QrLoginException.ConnectionInsecure) qrCodeLoginManager.currentLoginStep.value = QrCodeLoginStep.Failed(QrLoginException.ConnectionInsecure)
assertThat(flowNode.currentNavTarget()).isEqualTo(QrCodeLoginFlowNode.NavTarget.Error(QrCodeErrorScreenType.InsecureChannelDetected)) assertThat(flowNode.currentNavTarget()).isEqualTo(QrCodeLoginFlowNode.NavTarget.Error(QrCodeErrorScreenType.InsecureChannelDetected))
qrCodeLoginManager.currentLoginStep.value = QrCodeLoginStep.Failed(QrLoginException.OidcMetadataInvalid) qrCodeLoginManager.currentLoginStep.value = QrCodeLoginStep.Failed(QrLoginException.OAuthMetadataInvalid)
assertThat(flowNode.currentNavTarget()).isEqualTo(QrCodeLoginFlowNode.NavTarget.Error(QrCodeErrorScreenType.UnknownError)) assertThat(flowNode.currentNavTarget()).isEqualTo(QrCodeLoginFlowNode.NavTarget.Error(QrCodeErrorScreenType.UnknownError))
qrCodeLoginManager.currentLoginStep.value = QrCodeLoginStep.Failed(QrLoginException.Unknown) qrCodeLoginManager.currentLoginStep.value = QrCodeLoginStep.Failed(QrLoginException.Unknown)

View file

@ -16,7 +16,7 @@ import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.features.login.impl.accountprovider.anAccountProvider import io.element.android.features.login.impl.accountprovider.anAccountProvider
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.AN_EXCEPTION
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EnsureNeverCalled
@ -84,7 +84,7 @@ class ChooseAccountProviderViewTest {
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setChooseAccountProviderView( private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setChooseAccountProviderView(
state: ChooseAccountProviderState, state: ChooseAccountProviderState,
onBackClick: () -> Unit = EnsureNeverCalled(), onBackClick: () -> Unit = EnsureNeverCalled(),
onOidcDetails: (OidcDetails) -> Unit = EnsureNeverCalledWithParam(), onOAuthDetails: (OAuthDetails) -> Unit = EnsureNeverCalledWithParam(),
onNeedLoginPassword: () -> Unit = EnsureNeverCalled(), onNeedLoginPassword: () -> Unit = EnsureNeverCalled(),
onLearnMoreClick: () -> Unit = EnsureNeverCalled(), onLearnMoreClick: () -> Unit = EnsureNeverCalled(),
onCreateAccountContinue: (url: String) -> Unit = EnsureNeverCalledWithParam(), onCreateAccountContinue: (url: String) -> Unit = EnsureNeverCalledWithParam(),
@ -93,7 +93,7 @@ class ChooseAccountProviderViewTest {
ChooseAccountProviderView( ChooseAccountProviderView(
state = state, state = state,
onBackClick = onBackClick, onBackClick = onBackClick,
onOidcDetails = onOidcDetails, onOAuthDetails = onOAuthDetails,
onNeedLoginPassword = onNeedLoginPassword, onNeedLoginPassword = onNeedLoginPassword,
onLearnMoreClick = onLearnMoreClick, onLearnMoreClick = onLearnMoreClick,
onCreateAccountContinue = onCreateAccountContinue, onCreateAccountContinue = onCreateAccountContinue,

View file

@ -22,9 +22,9 @@ import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.AN_EXCEPTION
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
import io.element.android.libraries.matrix.test.auth.aMatrixHomeServerDetails import io.element.android.libraries.matrix.test.auth.aMatrixHomeServerDetails
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
import io.element.android.libraries.oidc.api.OidcActionFlow import io.element.android.libraries.oauth.api.OAuthActionFlow
import io.element.android.libraries.oidc.test.customtab.FakeOidcActionFlow import io.element.android.libraries.oauth.test.customtab.FakeOAuthActionFlow
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.test import io.element.android.tests.testutils.test
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
@ -74,7 +74,7 @@ class ConfirmAccountProviderPresenterTest {
fun `present - continue oidc`() = runTest { fun `present - continue oidc`() = runTest {
val authenticationService = FakeMatrixAuthenticationService( val authenticationService = FakeMatrixAuthenticationService(
setHomeserverResult = { setHomeserverResult = {
Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true))
}, },
) )
val presenter = createConfirmAccountProviderPresenter( val presenter = createConfirmAccountProviderPresenter(
@ -89,21 +89,21 @@ class ConfirmAccountProviderPresenterTest {
val successState = awaitItem() val successState = awaitItem()
assertThat(successState.submitEnabled).isFalse() assertThat(successState.submitEnabled).isFalse()
assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java)
assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java)
} }
} }
@Test @Test
fun `present - oidc - cancel with failure`() = runTest { fun `present - OAuth - cancel with failure`() = runTest {
val authenticationService = FakeMatrixAuthenticationService( val authenticationService = FakeMatrixAuthenticationService(
setHomeserverResult = { setHomeserverResult = {
Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true))
}, },
) )
val defaultOidcActionFlow = FakeOidcActionFlow() val defaultOAuthActionFlow = FakeOAuthActionFlow()
val presenter = createConfirmAccountProviderPresenter( val presenter = createConfirmAccountProviderPresenter(
matrixAuthenticationService = authenticationService, matrixAuthenticationService = authenticationService,
defaultOidcActionFlow = defaultOidcActionFlow, defaultOAuthActionFlow = defaultOAuthActionFlow,
) )
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
@ -114,25 +114,25 @@ class ConfirmAccountProviderPresenterTest {
val successState = awaitItem() val successState = awaitItem()
assertThat(successState.submitEnabled).isFalse() assertThat(successState.submitEnabled).isFalse()
assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java)
assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java)
authenticationService.givenOidcCancelError(AN_EXCEPTION) authenticationService.givenOAuthCancelError(AN_EXCEPTION)
defaultOidcActionFlow.post(OidcAction.GoBack()) defaultOAuthActionFlow.post(OAuthAction.GoBack())
val cancelFailureState = awaitItem() val cancelFailureState = awaitItem()
assertThat(cancelFailureState.loginMode).isInstanceOf(AsyncData.Failure::class.java) assertThat(cancelFailureState.loginMode).isInstanceOf(AsyncData.Failure::class.java)
} }
} }
@Test @Test
fun `present - oidc - cancel with success`() = runTest { fun `present - OAuth - cancel with success`() = runTest {
val authenticationService = FakeMatrixAuthenticationService( val authenticationService = FakeMatrixAuthenticationService(
setHomeserverResult = { setHomeserverResult = {
Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true))
}, },
) )
val defaultOidcActionFlow = FakeOidcActionFlow() val defaultOAuthActionFlow = FakeOAuthActionFlow()
val presenter = createConfirmAccountProviderPresenter( val presenter = createConfirmAccountProviderPresenter(
matrixAuthenticationService = authenticationService, matrixAuthenticationService = authenticationService,
defaultOidcActionFlow = defaultOidcActionFlow, defaultOAuthActionFlow = defaultOAuthActionFlow,
) )
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
@ -143,24 +143,24 @@ class ConfirmAccountProviderPresenterTest {
val successState = awaitItem() val successState = awaitItem()
assertThat(successState.submitEnabled).isFalse() assertThat(successState.submitEnabled).isFalse()
assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java)
assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java)
defaultOidcActionFlow.post(OidcAction.GoBack()) defaultOAuthActionFlow.post(OAuthAction.GoBack())
val cancelFinalState = awaitItem() val cancelFinalState = awaitItem()
assertThat(cancelFinalState.loginMode).isInstanceOf(AsyncData.Uninitialized::class.java) assertThat(cancelFinalState.loginMode).isInstanceOf(AsyncData.Uninitialized::class.java)
} }
} }
@Test @Test
fun `present - oidc - cancel to unblock`() = runTest { fun `present - OAuth - cancel to unblock`() = runTest {
val authenticationService = FakeMatrixAuthenticationService( val authenticationService = FakeMatrixAuthenticationService(
setHomeserverResult = { setHomeserverResult = {
Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true))
}, },
) )
val defaultOidcActionFlow = FakeOidcActionFlow() val defaultOAuthActionFlow = FakeOAuthActionFlow()
val presenter = createConfirmAccountProviderPresenter( val presenter = createConfirmAccountProviderPresenter(
matrixAuthenticationService = authenticationService, matrixAuthenticationService = authenticationService,
defaultOidcActionFlow = defaultOidcActionFlow, defaultOAuthActionFlow = defaultOAuthActionFlow,
) )
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
@ -168,23 +168,23 @@ class ConfirmAccountProviderPresenterTest {
val loadingState = awaitItem() val loadingState = awaitItem()
assertThat(loadingState.submitEnabled).isTrue() assertThat(loadingState.submitEnabled).isTrue()
assertThat(loadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) assertThat(loadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java)
defaultOidcActionFlow.post(OidcAction.GoBack(toUnblock = true)) defaultOAuthActionFlow.post(OAuthAction.GoBack(toUnblock = true))
val cancelFinalState = awaitItem() val cancelFinalState = awaitItem()
assertThat(cancelFinalState.loginMode).isInstanceOf(AsyncData.Uninitialized::class.java) assertThat(cancelFinalState.loginMode).isInstanceOf(AsyncData.Uninitialized::class.java)
} }
} }
@Test @Test
fun `present - oidc - success with failure`() = runTest { fun `present - OAuth - success with failure`() = runTest {
val authenticationService = FakeMatrixAuthenticationService( val authenticationService = FakeMatrixAuthenticationService(
setHomeserverResult = { setHomeserverResult = {
Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true))
}, },
) )
val defaultOidcActionFlow = FakeOidcActionFlow() val defaultOAuthActionFlow = FakeOAuthActionFlow()
val presenter = createConfirmAccountProviderPresenter( val presenter = createConfirmAccountProviderPresenter(
matrixAuthenticationService = authenticationService, matrixAuthenticationService = authenticationService,
defaultOidcActionFlow = defaultOidcActionFlow, defaultOAuthActionFlow = defaultOAuthActionFlow,
) )
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
@ -195,9 +195,9 @@ class ConfirmAccountProviderPresenterTest {
val successState = awaitItem() val successState = awaitItem()
assertThat(successState.submitEnabled).isFalse() assertThat(successState.submitEnabled).isFalse()
assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java)
assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java)
authenticationService.givenLoginError(AN_EXCEPTION) authenticationService.givenLoginError(AN_EXCEPTION)
defaultOidcActionFlow.post(OidcAction.Success("aUrl")) defaultOAuthActionFlow.post(OAuthAction.Success("aUrl"))
val cancelLoadingState = awaitItem() val cancelLoadingState = awaitItem()
assertThat(cancelLoadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) assertThat(cancelLoadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java)
val cancelFailureState = awaitItem() val cancelFailureState = awaitItem()
@ -206,16 +206,16 @@ class ConfirmAccountProviderPresenterTest {
} }
@Test @Test
fun `present - oidc - success with success`() = runTest { fun `present - OAuth - success with success`() = runTest {
val authenticationService = FakeMatrixAuthenticationService( val authenticationService = FakeMatrixAuthenticationService(
setHomeserverResult = { setHomeserverResult = {
Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true))
}, },
) )
val defaultOidcActionFlow = FakeOidcActionFlow() val defaultOidcActionFlow = FakeOAuthActionFlow()
val presenter = createConfirmAccountProviderPresenter( val presenter = createConfirmAccountProviderPresenter(
matrixAuthenticationService = authenticationService, matrixAuthenticationService = authenticationService,
defaultOidcActionFlow = defaultOidcActionFlow, defaultOAuthActionFlow = defaultOidcActionFlow,
) )
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
@ -226,8 +226,8 @@ class ConfirmAccountProviderPresenterTest {
val successState = awaitItem() val successState = awaitItem()
assertThat(successState.submitEnabled).isFalse() assertThat(successState.submitEnabled).isFalse()
assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java)
assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java)
defaultOidcActionFlow.post(OidcAction.Success("aUrl")) defaultOidcActionFlow.post(OAuthAction.Success("aUrl"))
val successSuccessState = awaitItem() val successSuccessState = awaitItem()
assertThat(successSuccessState.loginMode).isInstanceOf(AsyncData.Loading::class.java) assertThat(successSuccessState.loginMode).isInstanceOf(AsyncData.Loading::class.java)
} }
@ -311,10 +311,10 @@ class ConfirmAccountProviderPresenterTest {
} }
@Test @Test
fun `present - confirm account creation with oidc is successful`() = runTest { fun `present - confirm account creation with OAuth is successful`() = runTest {
val authenticationService = FakeMatrixAuthenticationService( val authenticationService = FakeMatrixAuthenticationService(
setHomeserverResult = { setHomeserverResult = {
Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true))
}, },
) )
val presenter = createConfirmAccountProviderPresenter( val presenter = createConfirmAccountProviderPresenter(
@ -327,16 +327,16 @@ class ConfirmAccountProviderPresenterTest {
skipItems(1) // Loading skipItems(1) // Loading
val submittedState = awaitItem() val submittedState = awaitItem()
assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Success::class.java) assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Success::class.java)
assertThat(submittedState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) assertThat(submittedState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java)
} }
} }
@Test @Test
fun `present - confirm account creation with oidc and url continues with oidc`() = runTest { fun `present - confirm account creation with OAuth and url continues with OAuth`() = runTest {
val aUrl = "aUrl" val aUrl = "aUrl"
val authenticationService = FakeMatrixAuthenticationService( val authenticationService = FakeMatrixAuthenticationService(
setHomeserverResult = { setHomeserverResult = {
Result.success(aMatrixHomeServerDetails(supportsOidcLogin = true)) Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true))
}, },
) )
val presenter = createConfirmAccountProviderPresenter( val presenter = createConfirmAccountProviderPresenter(
@ -350,12 +350,12 @@ class ConfirmAccountProviderPresenterTest {
skipItems(1) // Loading skipItems(1) // Loading
val submittedState = awaitItem() val submittedState = awaitItem()
assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Success::class.java) assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Success::class.java)
assertThat(submittedState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java) assertThat(submittedState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java)
} }
} }
@Test @Test
fun `present - confirm account creation without oidc and with url continuing with url`() = runTest { fun `present - confirm account creation without OAuth and with url continuing with url`() = runTest {
val aUrl = "aUrl" val aUrl = "aUrl"
val authenticationService = FakeMatrixAuthenticationService( val authenticationService = FakeMatrixAuthenticationService(
setHomeserverResult = { setHomeserverResult = {
@ -380,14 +380,14 @@ class ConfirmAccountProviderPresenterTest {
params: ConfirmAccountProviderPresenter.Params = ConfirmAccountProviderPresenter.Params(isAccountCreation = false), params: ConfirmAccountProviderPresenter.Params = ConfirmAccountProviderPresenter.Params(isAccountCreation = false),
accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()),
matrixAuthenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(), matrixAuthenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(),
defaultOidcActionFlow: OidcActionFlow = FakeOidcActionFlow(), defaultOAuthActionFlow: OAuthActionFlow = FakeOAuthActionFlow(),
webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever(), webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever(),
) = ConfirmAccountProviderPresenter( ) = ConfirmAccountProviderPresenter(
params = params, params = params,
accountProviderDataSource = accountProviderDataSource, accountProviderDataSource = accountProviderDataSource,
loginHelper = createLoginHelper( loginHelper = createLoginHelper(
authenticationService = matrixAuthenticationService, authenticationService = matrixAuthenticationService,
oidcActionFlow = defaultOidcActionFlow, oAuthActionFlow = defaultOAuthActionFlow,
webClientUrlForAuthenticationRetriever = webClientUrlForAuthenticationRetriever, webClientUrlForAuthenticationRetriever = webClientUrlForAuthenticationRetriever,
), ),
) )

View file

@ -31,8 +31,8 @@ import io.element.android.libraries.matrix.test.A_HOMESERVER_URL_2
import io.element.android.libraries.matrix.test.A_LOGIN_HINT import io.element.android.libraries.matrix.test.A_LOGIN_HINT
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.oidc.api.OidcActionFlow import io.element.android.libraries.oauth.api.OAuthActionFlow
import io.element.android.libraries.oidc.test.customtab.FakeOidcActionFlow import io.element.android.libraries.oauth.test.customtab.FakeOAuthActionFlow
import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData import io.element.android.libraries.sessionstorage.test.aSessionData
@ -312,11 +312,11 @@ private fun createPresenter(
) )
fun createLoginHelper( fun createLoginHelper(
oidcActionFlow: OidcActionFlow = FakeOidcActionFlow(), oAuthActionFlow: OAuthActionFlow = FakeOAuthActionFlow(),
authenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(), authenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(),
webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever(), webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever(),
): LoginHelper = LoginHelper( ): LoginHelper = LoginHelper(
oidcActionFlow = oidcActionFlow, oAuthActionFlow = oAuthActionFlow,
authenticationService = authenticationService, authenticationService = authenticationService,
webClientUrlForAuthenticationRetriever = webClientUrlForAuthenticationRetriever, webClientUrlForAuthenticationRetriever = webClientUrlForAuthenticationRetriever,
) )

View file

@ -19,7 +19,7 @@ import com.google.testing.junit.testparameterinjector.TestParameter
import io.element.android.features.login.impl.R import io.element.android.features.login.impl.R
import io.element.android.features.login.impl.login.LoginMode import io.element.android.features.login.impl.login.LoginMode
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.AN_EXCEPTION
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EnsureNeverCalled
@ -224,14 +224,14 @@ class OnboardingViewTest {
@Test @Test
fun `when success Oidc - the expected callback is invoked and the event is received`() { fun `when success Oidc - the expected callback is invoked and the event is received`() {
val eventSink = EventsRecorder<OnBoardingEvents>() val eventSink = EventsRecorder<OnBoardingEvents>()
val oidcDetails = OidcDetails("aUrl") val oAuthDetails = OAuthDetails("aUrl")
ensureCalledOnceWithParam(oidcDetails) { callback -> ensureCalledOnceWithParam(oAuthDetails) { callback ->
rule.setOnboardingView( rule.setOnboardingView(
state = anOnBoardingState( state = anOnBoardingState(
loginMode = AsyncData.Success(LoginMode.Oidc(oidcDetails)), loginMode = AsyncData.Success(LoginMode.OAuth(oAuthDetails)),
eventSink = eventSink, eventSink = eventSink,
), ),
onOidcDetails = callback, onOAuthDetails = callback,
) )
} }
eventSink.assertSingle(OnBoardingEvents.ClearError) eventSink.assertSingle(OnBoardingEvents.ClearError)
@ -240,8 +240,8 @@ class OnboardingViewTest {
@Test @Test
fun `when success AccountCreation - the expected callback is invoked and the event is received`() { fun `when success AccountCreation - the expected callback is invoked and the event is received`() {
val eventSink = EventsRecorder<OnBoardingEvents>() val eventSink = EventsRecorder<OnBoardingEvents>()
val oidcDetails = OidcDetails("aUrl") val oAuthDetails = OAuthDetails("aUrl")
ensureCalledOnceWithParam(oidcDetails.url) { callback -> ensureCalledOnceWithParam(oAuthDetails.url) { callback ->
rule.setOnboardingView( rule.setOnboardingView(
state = anOnBoardingState( state = anOnBoardingState(
loginMode = AsyncData.Success(LoginMode.AccountCreation("aUrl")), loginMode = AsyncData.Success(LoginMode.AccountCreation("aUrl")),
@ -261,7 +261,7 @@ class OnboardingViewTest {
onSignIn: (Boolean) -> Unit = EnsureNeverCalledWithParam(), onSignIn: (Boolean) -> Unit = EnsureNeverCalledWithParam(),
onCreateAccount: () -> Unit = EnsureNeverCalled(), onCreateAccount: () -> Unit = EnsureNeverCalled(),
onReportProblem: () -> Unit = EnsureNeverCalled(), onReportProblem: () -> Unit = EnsureNeverCalled(),
onOidcDetails: (OidcDetails) -> Unit = EnsureNeverCalledWithParam(), onOAuthDetails: (OAuthDetails) -> Unit = EnsureNeverCalledWithParam(),
onNeedLoginPassword: () -> Unit = EnsureNeverCalled(), onNeedLoginPassword: () -> Unit = EnsureNeverCalled(),
onLearnMoreClick: () -> Unit = EnsureNeverCalled(), onLearnMoreClick: () -> Unit = EnsureNeverCalled(),
onCreateAccountContinue: (url: String) -> Unit = EnsureNeverCalledWithParam(), onCreateAccountContinue: (url: String) -> Unit = EnsureNeverCalledWithParam(),
@ -275,7 +275,7 @@ class OnboardingViewTest {
onSignIn = onSignIn, onSignIn = onSignIn,
onCreateAccount = onCreateAccount, onCreateAccount = onCreateAccount,
onReportProblem = onReportProblem, onReportProblem = onReportProblem,
onOidcDetails = onOidcDetails, onOAuthDetails = onOAuthDetails,
onNeedLoginPassword = onNeedLoginPassword, onNeedLoginPassword = onNeedLoginPassword,
onLearnMoreClick = onLearnMoreClick, onLearnMoreClick = onLearnMoreClick,
onCreateAccountContinue = onCreateAccountContinue, onCreateAccountContinue = onCreateAccountContinue,

View file

@ -23,7 +23,7 @@ import io.element.android.libraries.featureflag.test.FakeFeature
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.indicator.api.IndicatorService import io.element.android.libraries.indicator.api.IndicatorService
import io.element.android.libraries.indicator.test.FakeIndicatorService import io.element.android.libraries.indicator.test.FakeIndicatorService
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.oauth.AccountManagementAction
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_SESSION_ID

View file

@ -34,7 +34,7 @@ dependencies {
implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrix.api)
implementation(projects.libraries.matrixui) implementation(projects.libraries.matrixui)
implementation(projects.libraries.designsystem) implementation(projects.libraries.designsystem)
implementation(projects.libraries.oidc.api) implementation(projects.libraries.oauth.api)
implementation(projects.libraries.uiStrings) implementation(projects.libraries.uiStrings)
implementation(projects.libraries.testtags) implementation(projects.libraries.testtags)
api(libs.statemachine) api(libs.statemachine)

View file

@ -36,7 +36,7 @@ import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.di.annotations.SessionCoroutineScope
import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityOAuthResetHandle
import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -123,12 +123,12 @@ class ResetIdentityFlowNode(
null -> { null -> {
Timber.d("No reset handle return, the reset is done.") Timber.d("No reset handle return, the reset is done.")
} }
is IdentityOidcResetHandle -> { is IdentityOAuthResetHandle -> {
Timber.d("Launching reset confirmation in MAS") Timber.d("Launching reset confirmation in MAS")
activity.openUrlInChromeCustomTab(null, darkTheme, handle.url) activity.openUrlInChromeCustomTab(null, darkTheme, handle.url)
Timber.d("Starting resetOidc") Timber.d("Starting resetOAuth")
resetJob = launch { handle.resetOidc() } resetJob = launch { handle.resetOAuth() }
resetJob?.invokeOnCompletion { Timber.d("resetOidc ended") } resetJob?.invokeOnCompletion { Timber.d("resetOAuth ended") }
} }
is IdentityPasswordResetHandle -> backstack.push(NavTarget.ResetPassword) is IdentityPasswordResetHandle -> backstack.push(NavTarget.ResetPassword)
} }

View file

@ -36,7 +36,7 @@ private fun aSessionData(
accessToken = "anAccessToken", accessToken = "anAccessToken",
refreshToken = "aRefreshToken", refreshToken = "aRefreshToken",
homeserverUrl = "aHomeserverUrl", homeserverUrl = "aHomeserverUrl",
oidcData = null, oAuthData = null,
loginTimestamp = null, loginTimestamp = null,
isTokenValid = isTokenValid, isTokenValid = isTokenValid,
loginType = LoginType.UNKNOWN, loginType = LoginType.UNKNOWN,

View file

@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.media.MediaPreviewService import io.element.android.libraries.matrix.api.media.MediaPreviewService
import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.libraries.matrix.api.notification.NotificationService
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.oauth.AccountManagementAction
import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.pusher.PushersService
import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.JoinedRoom

View file

@ -16,6 +16,6 @@ sealed class AuthenticationException(message: String?) : Exception(message) {
class InvalidServerName(message: String?) : AuthenticationException(message) class InvalidServerName(message: String?) : AuthenticationException(message)
class SlidingSyncVersion(message: String?) : AuthenticationException(message) class SlidingSyncVersion(message: String?) : AuthenticationException(message)
class ServerUnreachable(message: String?) : AuthenticationException(message) class ServerUnreachable(message: String?) : AuthenticationException(message)
class Oidc(message: String?) : AuthenticationException(message) class OAuth(message: String?) : AuthenticationException(message)
class Generic(message: String?) : AuthenticationException(message) class Generic(message: String?) : AuthenticationException(message)
} }

View file

@ -37,21 +37,21 @@ interface MatrixAuthenticationService {
suspend fun importCreatedSession(externalSession: ExternalSession): Result<SessionId> suspend fun importCreatedSession(externalSession: ExternalSession): Result<SessionId>
/* /*
* OIDC part. * OAuth part.
*/ */
/** /**
* Get the Oidc url to display to the user. * Get the OAuth url to display to the user.
*/ */
suspend fun getOidcUrl( suspend fun getOAuthUrl(
prompt: OidcPrompt, prompt: OAuthPrompt,
loginHint: String?, loginHint: String?,
): Result<OidcDetails> ): Result<OAuthDetails>
/** /**
* Cancel Oidc login sequence. * Cancel OAuth login sequence.
*/ */
suspend fun cancelOidcLogin(): Result<Unit> suspend fun cancelOAuthLogin(): Result<Unit>
/** /**
* Set the existing data about Element Classic session, if any. * Set the existing data about Element Classic session, if any.
@ -68,9 +68,9 @@ interface MatrixAuthenticationService {
): Boolean ): Boolean
/** /**
* Attempt to login using the [callbackUrl] provided by the Oidc page. * Attempt to log in using the [callbackUrl] provided by the OAuth page.
*/ */
suspend fun loginWithOidc(callbackUrl: String): Result<SessionId> suspend fun loginWithOAuth(callbackUrl: String): Result<SessionId>
suspend fun loginWithQrCode(qrCodeData: MatrixQrCodeLoginData, progress: (QrCodeLoginStep) -> Unit): Result<SessionId> suspend fun loginWithQrCode(qrCodeData: MatrixQrCodeLoginData, progress: (QrCodeLoginStep) -> Unit): Result<SessionId>

View file

@ -11,7 +11,7 @@ package io.element.android.libraries.matrix.api.auth
data class MatrixHomeServerDetails( data class MatrixHomeServerDetails(
val url: String, val url: String,
val supportsPasswordLogin: Boolean, val supportsPasswordLogin: Boolean,
val supportsOidcLogin: Boolean, val supportsOAuthLogin: Boolean,
) { ) {
val isSupported = supportsPasswordLogin || supportsOidcLogin val isSupported = supportsPasswordLogin || supportsOAuthLogin
} }

View file

@ -10,7 +10,7 @@ package io.element.android.libraries.matrix.api.auth
import io.element.android.libraries.matrix.api.BuildConfig import io.element.android.libraries.matrix.api.BuildConfig
object OidcConfig { object OAuthConfig {
const val CLIENT_URI = BuildConfig.CLIENT_URI const val CLIENT_URI = BuildConfig.CLIENT_URI
// Note: host must match with the host of CLIENT_URI // Note: host must match with the host of CLIENT_URI

View file

@ -12,6 +12,6 @@ import android.os.Parcelable
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@Parcelize @Parcelize
data class OidcDetails( data class OAuthDetails(
val url: String, val url: String,
) : Parcelable ) : Parcelable

View file

@ -8,12 +8,12 @@
package io.element.android.libraries.matrix.api.auth package io.element.android.libraries.matrix.api.auth
sealed interface OidcPrompt { sealed interface OAuthPrompt {
/** /**
* The Authorization Server should prompt the End-User for * The Authorization Server should prompt the End-User for
* reauthentication. * reauthentication.
*/ */
data object Login : OidcPrompt data object Login : OAuthPrompt
/** /**
* The Authorization Server should prompt the End-User to create a user * The Authorization Server should prompt the End-User to create a user
@ -21,10 +21,10 @@ sealed interface OidcPrompt {
* *
* Defined in [Initiating User Registration via OpenID Connect](https://openid.net/specs/openid-connect-prompt-create-1_0.html). * Defined in [Initiating User Registration via OpenID Connect](https://openid.net/specs/openid-connect-prompt-create-1_0.html).
*/ */
data object Create : OidcPrompt data object Create : OAuthPrompt
/** /**
* An unknown value. * An unknown value.
*/ */
data class Unknown(val value: String) : OidcPrompt data class Unknown(val value: String) : OAuthPrompt
} }

View file

@ -8,6 +8,6 @@
package io.element.android.libraries.matrix.api.auth package io.element.android.libraries.matrix.api.auth
interface OidcRedirectUrlProvider { interface OAuthRedirectUrlProvider {
fun provide(): String fun provide(): String
} }

View file

@ -15,7 +15,7 @@ sealed class QrLoginException : Exception() {
data object Expired : QrLoginException() data object Expired : QrLoginException()
data object NotFound : QrLoginException() data object NotFound : QrLoginException()
data object LinkingNotSupported : QrLoginException() data object LinkingNotSupported : QrLoginException()
data object OidcMetadataInvalid : QrLoginException() data object OAuthMetadataInvalid : QrLoginException()
data object SlidingSyncNotAvailable : QrLoginException() data object SlidingSyncNotAvailable : QrLoginException()
data object OtherDeviceNotSignedIn : QrLoginException() data object OtherDeviceNotSignedIn : QrLoginException()
data object CheckCodeAlreadySent : QrLoginException() data object CheckCodeAlreadySent : QrLoginException()

View file

@ -112,19 +112,19 @@ interface IdentityPasswordResetHandle : IdentityResetHandle {
} }
/** /**
* A handle to reset the user's identity with an OIDC login type. * A handle to reset the user's identity with an OAuth login type.
*/ */
interface IdentityOidcResetHandle : IdentityResetHandle { interface IdentityOAuthResetHandle : IdentityResetHandle {
/** /**
* The URL to open in a webview/custom tab to reset the identity. * The URL to open in a webview/custom tab to reset the identity.
*/ */
val url: String val url: String
/** /**
* Reset the identity using the OIDC flow. * Reset the identity using the OAuth flow.
* *
* This method will block the coroutine it's running on and keep polling indefinitely until either the coroutine is cancelled, the [cancel] method is * This method will block the coroutine it's running on and keep polling indefinitely until either the coroutine is cancelled, the [cancel] method is
* called, or the identity is reset. * called, or the identity is reset.
*/ */
suspend fun resetOidc(): Result<Unit> suspend fun resetOAuth(): Result<Unit>
} }

View file

@ -6,7 +6,7 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.matrix.api.oidc package io.element.android.libraries.matrix.api.oauth
import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.DeviceId

View file

@ -16,7 +16,7 @@ class MatrixHomeServerDetailsTest {
@Test @Test
fun `if homeserver supports oidc, then it is supported`() { fun `if homeserver supports oidc, then it is supported`() {
val sut = aMatrixHomeServerDetails( val sut = aMatrixHomeServerDetails(
supportsOidcLogin = true, supportsOAuthLogin = true,
supportsPasswordLogin = false, supportsPasswordLogin = false,
) )
assertThat(sut.isSupported).isTrue() assertThat(sut.isSupported).isTrue()
@ -25,7 +25,7 @@ class MatrixHomeServerDetailsTest {
@Test @Test
fun `if homeserver supports password, then it is supported`() { fun `if homeserver supports password, then it is supported`() {
val sut = aMatrixHomeServerDetails( val sut = aMatrixHomeServerDetails(
supportsOidcLogin = false, supportsOAuthLogin = false,
supportsPasswordLogin = true, supportsPasswordLogin = true,
) )
assertThat(sut.isSupported).isTrue() assertThat(sut.isSupported).isTrue()
@ -34,7 +34,7 @@ class MatrixHomeServerDetailsTest {
@Test @Test
fun `if homeserver supports both, then it is supported`() { fun `if homeserver supports both, then it is supported`() {
val sut = aMatrixHomeServerDetails( val sut = aMatrixHomeServerDetails(
supportsOidcLogin = true, supportsOAuthLogin = true,
supportsPasswordLogin = true, supportsPasswordLogin = true,
) )
assertThat(sut.isSupported).isTrue() assertThat(sut.isSupported).isTrue()
@ -43,7 +43,7 @@ class MatrixHomeServerDetailsTest {
@Test @Test
fun `if homeserver supports none, then it is not supported`() { fun `if homeserver supports none, then it is not supported`() {
val sut = aMatrixHomeServerDetails( val sut = aMatrixHomeServerDetails(
supportsOidcLogin = false, supportsOAuthLogin = false,
supportsPasswordLogin = false, supportsPasswordLogin = false,
) )
assertThat(sut.isSupported).isFalse() assertThat(sut.isSupported).isFalse()

View file

@ -31,7 +31,7 @@ import io.element.android.libraries.matrix.api.createroom.RoomPreset
import io.element.android.libraries.matrix.api.linknewdevice.LinkDesktopHandler import io.element.android.libraries.matrix.api.linknewdevice.LinkDesktopHandler
import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileHandler import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileHandler
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.oauth.AccountManagementAction
import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.JoinedRoom
@ -59,7 +59,7 @@ import io.element.android.libraries.matrix.impl.media.RustMediaLoader
import io.element.android.libraries.matrix.impl.media.RustMediaPreviewService import io.element.android.libraries.matrix.impl.media.RustMediaPreviewService
import io.element.android.libraries.matrix.impl.notification.RustNotificationService import io.element.android.libraries.matrix.impl.notification.RustNotificationService
import io.element.android.libraries.matrix.impl.notificationsettings.RustNotificationSettingsService import io.element.android.libraries.matrix.impl.notificationsettings.RustNotificationSettingsService
import io.element.android.libraries.matrix.impl.oidc.toRustAction import io.element.android.libraries.matrix.impl.oauth.toRustAction
import io.element.android.libraries.matrix.impl.pushers.RustPushersService import io.element.android.libraries.matrix.impl.pushers.RustPushersService
import io.element.android.libraries.matrix.impl.room.GetRoomResult import io.element.android.libraries.matrix.impl.room.GetRoomResult
import io.element.android.libraries.matrix.impl.room.NotJoinedRustRoom import io.element.android.libraries.matrix.impl.room.NotJoinedRustRoom

View file

@ -214,5 +214,5 @@ fun SessionData.toSession() = Session(
deviceId = deviceId, deviceId = deviceId,
homeserverUrl = homeserverUrl, homeserverUrl = homeserverUrl,
slidingSyncVersion = SlidingSyncVersion.NATIVE, slidingSyncVersion = SlidingSyncVersion.NATIVE,
oauthData = oidcData, oauthData = oAuthData,
) )

View file

@ -30,11 +30,11 @@ fun Throwable.mapAuthenticationException(): AuthenticationException {
is ClientBuildException.EventCache -> AuthenticationException.Generic(message) is ClientBuildException.EventCache -> AuthenticationException.Generic(message)
} }
is OAuthException -> when (this) { is OAuthException -> when (this) {
is OAuthException.Generic -> AuthenticationException.Oidc(message) is OAuthException.Generic -> AuthenticationException.OAuth(message)
is OAuthException.CallbackUrlInvalid -> AuthenticationException.Oidc(message) is OAuthException.CallbackUrlInvalid -> AuthenticationException.OAuth(message)
is OAuthException.Cancelled -> AuthenticationException.Oidc(message) is OAuthException.Cancelled -> AuthenticationException.OAuth(message)
is OAuthException.MetadataInvalid -> AuthenticationException.Oidc(message) is OAuthException.MetadataInvalid -> AuthenticationException.OAuth(message)
is OAuthException.NotSupported -> AuthenticationException.Oidc(message) is OAuthException.NotSupported -> AuthenticationException.OAuth(message)
} }
else -> AuthenticationException.Generic(message) else -> AuthenticationException.Generic(message)
} }

View file

@ -15,6 +15,6 @@ fun HomeserverLoginDetails.map(): MatrixHomeServerDetails = use {
MatrixHomeServerDetails( MatrixHomeServerDetails(
url = url(), url = url(),
supportsPasswordLogin = supportsPasswordLogin(), supportsPasswordLogin = supportsPasswordLogin(),
supportsOidcLogin = supportsOauthLogin(), supportsOAuthLogin = supportsOauthLogin(),
) )
} }

View file

@ -10,22 +10,22 @@ package io.element.android.libraries.matrix.impl.auth
import dev.zacsweers.metro.Inject import dev.zacsweers.metro.Inject
import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.matrix.api.auth.OidcConfig import io.element.android.libraries.matrix.api.auth.OAuthConfig
import io.element.android.libraries.matrix.api.auth.OidcRedirectUrlProvider import io.element.android.libraries.matrix.api.auth.OAuthRedirectUrlProvider
import org.matrix.rustcomponents.sdk.OAuthConfiguration import org.matrix.rustcomponents.sdk.OAuthConfiguration
@Inject @Inject
class OidcConfigurationProvider( class OAuthConfigurationProvider(
private val buildMeta: BuildMeta, private val buildMeta: BuildMeta,
private val oidcRedirectUrlProvider: OidcRedirectUrlProvider, private val oAuthRedirectUrlProvider: OAuthRedirectUrlProvider,
) { ) {
fun get(): OAuthConfiguration = OAuthConfiguration( fun get(): OAuthConfiguration = OAuthConfiguration(
clientName = buildMeta.applicationName, clientName = buildMeta.applicationName,
redirectUri = oidcRedirectUrlProvider.provide(), redirectUri = oAuthRedirectUrlProvider.provide(),
clientUri = OidcConfig.CLIENT_URI, clientUri = OAuthConfig.CLIENT_URI,
logoUri = OidcConfig.LOGO_URI, logoUri = OAuthConfig.LOGO_URI,
tosUri = OidcConfig.TOS_URI, tosUri = OAuthConfig.TOS_URI,
policyUri = OidcConfig.POLICY_URI, policyUri = OAuthConfig.POLICY_URI,
staticRegistrations = OidcConfig.STATIC_REGISTRATIONS, staticRegistrations = OAuthConfig.STATIC_REGISTRATIONS,
) )
} }

View file

@ -8,13 +8,13 @@
package io.element.android.libraries.matrix.impl.auth package io.element.android.libraries.matrix.impl.auth
import io.element.android.libraries.matrix.api.auth.OidcPrompt import io.element.android.libraries.matrix.api.auth.OAuthPrompt
import org.matrix.rustcomponents.sdk.OAuthPrompt as RustOidcPrompt import org.matrix.rustcomponents.sdk.OAuthPrompt as RustOAuthPrompt
internal fun OidcPrompt.toRustPrompt(): RustOidcPrompt { internal fun OAuthPrompt.toRustPrompt(): RustOAuthPrompt {
return when (this) { return when (this) {
OidcPrompt.Login -> RustOidcPrompt.Unknown("consent") OAuthPrompt.Login -> RustOAuthPrompt.Unknown("consent")
OidcPrompt.Create -> RustOidcPrompt.Create OAuthPrompt.Create -> RustOAuthPrompt.Create
is OidcPrompt.Unknown -> RustOidcPrompt.Unknown(value) is OAuthPrompt.Unknown -> RustOAuthPrompt.Unknown(value)
} }
} }

View file

@ -31,7 +31,7 @@ class RustHomeServerLoginCompatibilityChecker(
it.homeserverLoginDetails() it.homeserverLoginDetails()
} }
.use { .use {
Timber.d("Homeserver $url | OIDC: ${it.supportsOauthLogin()} | Password: ${it.supportsPasswordLogin()} | SSO: ${it.supportsSsoLogin()}") Timber.d("Homeserver $url | OAuth: ${it.supportsOauthLogin()} | Password: ${it.supportsPasswordLogin()} | SSO: ${it.supportsSsoLogin()}")
it.supportsOauthLogin() || it.supportsPasswordLogin() it.supportsOauthLogin() || it.supportsPasswordLogin()
} }
} }

View file

@ -19,8 +19,8 @@ import io.element.android.libraries.matrix.api.auth.AuthenticationException
import io.element.android.libraries.matrix.api.auth.ElementClassicSession import io.element.android.libraries.matrix.api.auth.ElementClassicSession
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.matrix.api.auth.OidcPrompt import io.element.android.libraries.matrix.api.auth.OAuthPrompt
import io.element.android.libraries.matrix.api.auth.SessionRestorationException import io.element.android.libraries.matrix.api.auth.SessionRestorationException
import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.external.ExternalSession
import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData
@ -65,7 +65,7 @@ class RustMatrixAuthenticationService(
private val sessionStore: SessionStore, private val sessionStore: SessionStore,
private val rustMatrixClientFactory: RustMatrixClientFactory, private val rustMatrixClientFactory: RustMatrixClientFactory,
private val passphraseGenerator: PassphraseGenerator, private val passphraseGenerator: PassphraseGenerator,
private val oidcConfigurationProvider: OidcConfigurationProvider, private val oAuthConfigurationProvider: OAuthConfigurationProvider,
) : MatrixAuthenticationService { ) : MatrixAuthenticationService {
// Any existing Element Classic session that we want to try to import secrets from during login. // Any existing Element Classic session that we want to try to import secrets from during login.
private var elementClassicSession: ElementClassicSession? = null private var elementClassicSession: ElementClassicSession? = null
@ -253,15 +253,15 @@ class RustMatrixAuthenticationService(
private var pendingOAuthAuthorizationData: OAuthAuthorizationData? = null private var pendingOAuthAuthorizationData: OAuthAuthorizationData? = null
override suspend fun getOidcUrl( override suspend fun getOAuthUrl(
prompt: OidcPrompt, prompt: OAuthPrompt,
loginHint: String?, loginHint: String?,
): Result<OidcDetails> { ): Result<OAuthDetails> {
return withContext(coroutineDispatchers.io) { return withContext(coroutineDispatchers.io) {
runCatchingExceptions { runCatchingExceptions {
val client = currentClient ?: error("You need to call `setHomeserver()` first") val client = currentClient ?: error("You need to call `setHomeserver()` first")
val oAuthAuthorizationData = client.urlForOauth( val oAuthAuthorizationData = client.urlForOauth(
oauthConfiguration = oidcConfigurationProvider.get(), oauthConfiguration = oAuthConfigurationProvider.get(),
prompt = prompt.toRustPrompt(), prompt = prompt.toRustPrompt(),
loginHint = loginHint, loginHint = loginHint,
// If we want to restore a previous session for which we have encryption keys, we can pass the deviceId here. At the moment, we don't // If we want to restore a previous session for which we have encryption keys, we can pass the deviceId here. At the moment, we don't
@ -270,15 +270,15 @@ class RustMatrixAuthenticationService(
) )
val url = oAuthAuthorizationData.loginUrl() val url = oAuthAuthorizationData.loginUrl()
pendingOAuthAuthorizationData = oAuthAuthorizationData pendingOAuthAuthorizationData = oAuthAuthorizationData
OidcDetails(url) OAuthDetails(url)
}.mapFailure { failure -> }.mapFailure { failure ->
Timber.e(failure, "Failed to get OIDC URL") Timber.e(failure, "Failed to get OAuth URL")
failure.mapAuthenticationException() failure.mapAuthenticationException()
} }
} }
} }
override suspend fun cancelOidcLogin(): Result<Unit> { override suspend fun cancelOAuthLogin(): Result<Unit> {
return withContext(coroutineDispatchers.io) { return withContext(coroutineDispatchers.io) {
runCatchingExceptions { runCatchingExceptions {
pendingOAuthAuthorizationData?.use { pendingOAuthAuthorizationData?.use {
@ -286,7 +286,7 @@ class RustMatrixAuthenticationService(
} }
pendingOAuthAuthorizationData = null pendingOAuthAuthorizationData = null
}.mapFailure { failure -> }.mapFailure { failure ->
Timber.e(failure, "Failed to cancel OIDC login") Timber.e(failure, "Failed to cancel OAuth login")
failure.mapAuthenticationException() failure.mapAuthenticationException()
} }
} }
@ -297,9 +297,9 @@ class RustMatrixAuthenticationService(
} }
/** /**
* callbackUrl should be the uriRedirect from OidcClientMetadata (with all the parameters). * callbackUrl should be the `url` from `OAuthAction` (with all the parameters).
*/ */
override suspend fun loginWithOidc(callbackUrl: String): Result<SessionId> { override suspend fun loginWithOAuth(callbackUrl: String): Result<SessionId> {
return withContext(coroutineDispatchers.io) { return withContext(coroutineDispatchers.io) {
runCatchingExceptions { runCatchingExceptions {
val client = currentClient ?: error("You need to call `setHomeserver()` first") val client = currentClient ?: error("You need to call `setHomeserver()` first")
@ -330,7 +330,7 @@ class RustMatrixAuthenticationService(
SessionId(sessionData.userId) SessionId(sessionData.userId)
}.mapFailure { failure -> }.mapFailure { failure ->
Timber.e(failure, "Failed to login with OIDC") Timber.e(failure, "Failed to login with OAuth")
failure.mapAuthenticationException() failure.mapAuthenticationException()
} }
} }
@ -355,7 +355,7 @@ class RustMatrixAuthenticationService(
withContext(coroutineDispatchers.io) { withContext(coroutineDispatchers.io) {
val sdkQrCodeLoginData = (qrCodeData as SdkQrCodeLoginData).rustQrCodeData val sdkQrCodeLoginData = (qrCodeData as SdkQrCodeLoginData).rustQrCodeData
val emptySessionPaths = rotateSessionPath() val emptySessionPaths = rotateSessionPath()
val oidcConfiguration = oidcConfigurationProvider.get() val oAuthConfiguration = oAuthConfigurationProvider.get()
val progressListener = object : QrLoginProgressListener { val progressListener = object : QrLoginProgressListener {
override fun onUpdate(state: QrLoginProgress) { override fun onUpdate(state: QrLoginProgress) {
Timber.d("QR Code login progress: $state") Timber.d("QR Code login progress: $state")
@ -368,7 +368,7 @@ class RustMatrixAuthenticationService(
qrCodeData = sdkQrCodeLoginData, qrCodeData = sdkQrCodeLoginData,
) )
client.newLoginWithQrCodeHandler( client.newLoginWithQrCodeHandler(
oauthConfiguration = oidcConfiguration, oauthConfiguration = oAuthConfiguration,
).use { ).use {
it.scan( it.scan(
qrCodeData = qrCodeData.rustQrCodeData, qrCodeData = qrCodeData.rustQrCodeData,

View file

@ -42,7 +42,7 @@ object QrErrorMapper {
is RustHumanQrLoginException.OtherDeviceNotSignedIn -> QrLoginException.OtherDeviceNotSignedIn is RustHumanQrLoginException.OtherDeviceNotSignedIn -> QrLoginException.OtherDeviceNotSignedIn
is RustHumanQrLoginException.LinkingNotSupported -> QrLoginException.LinkingNotSupported is RustHumanQrLoginException.LinkingNotSupported -> QrLoginException.LinkingNotSupported
is RustHumanQrLoginException.Unknown -> QrLoginException.Unknown is RustHumanQrLoginException.Unknown -> QrLoginException.Unknown
is RustHumanQrLoginException.OAuthMetadataInvalid -> QrLoginException.OidcMetadataInvalid is RustHumanQrLoginException.OAuthMetadataInvalid -> QrLoginException.OAuthMetadataInvalid
is RustHumanQrLoginException.SlidingSyncNotAvailable -> QrLoginException.SlidingSyncNotAvailable is RustHumanQrLoginException.SlidingSyncNotAvailable -> QrLoginException.SlidingSyncNotAvailable
is RustHumanQrLoginException.CheckCodeAlreadySent -> QrLoginException.CheckCodeAlreadySent is RustHumanQrLoginException.CheckCodeAlreadySent -> QrLoginException.CheckCodeAlreadySent
is RustHumanQrLoginException.CheckCodeCannotBeSent -> QrLoginException.CheckCodeCannotBeSent is RustHumanQrLoginException.CheckCodeCannotBeSent -> QrLoginException.CheckCodeCannotBeSent

View file

@ -10,7 +10,7 @@ package io.element.android.libraries.matrix.impl.encryption
import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityOAuthResetHandle
import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle
import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityResetHandle
import org.matrix.rustcomponents.sdk.AuthData import org.matrix.rustcomponents.sdk.AuthData
@ -25,7 +25,7 @@ object RustIdentityResetHandleFactory {
return runCatchingExceptions { return runCatchingExceptions {
identityResetHandle?.let { identityResetHandle?.let {
when (val authType = identityResetHandle.authType()) { when (val authType = identityResetHandle.authType()) {
is CrossSigningResetAuthType.OAuth -> RustOidcIdentityResetHandle(identityResetHandle, authType.info.approvalUrl) is CrossSigningResetAuthType.OAuth -> RustIdentityOAuthResetHandle(identityResetHandle, authType.info.approvalUrl)
// User interactive authentication (user + password) // User interactive authentication (user + password)
CrossSigningResetAuthType.Uiaa -> RustPasswordIdentityResetHandle(userId, identityResetHandle) CrossSigningResetAuthType.Uiaa -> RustPasswordIdentityResetHandle(userId, identityResetHandle)
} }
@ -47,11 +47,11 @@ class RustPasswordIdentityResetHandle(
} }
} }
class RustOidcIdentityResetHandle( class RustIdentityOAuthResetHandle(
private val identityResetHandle: org.matrix.rustcomponents.sdk.IdentityResetHandle, private val identityResetHandle: org.matrix.rustcomponents.sdk.IdentityResetHandle,
override val url: String, override val url: String,
) : IdentityOidcResetHandle { ) : IdentityOAuthResetHandle {
override suspend fun resetOidc(): Result<Unit> { override suspend fun resetOAuth(): Result<Unit> {
return runCatchingExceptions { identityResetHandle.reset(null) } return runCatchingExceptions { identityResetHandle.reset(null) }
} }

View file

@ -27,7 +27,7 @@ internal fun Session.toSessionData(
accessToken = accessToken, accessToken = accessToken,
refreshToken = refreshToken, refreshToken = refreshToken,
homeserverUrl = homeserverUrl ?: this.homeserverUrl, homeserverUrl = homeserverUrl ?: this.homeserverUrl,
oidcData = oauthData, oAuthData = oauthData,
loginTimestamp = Date(), loginTimestamp = Date(),
isTokenValid = isTokenValid, isTokenValid = isTokenValid,
loginType = loginType, loginType = loginType,
@ -52,7 +52,7 @@ internal fun ExternalSession.toSessionData(
accessToken = accessToken, accessToken = accessToken,
refreshToken = refreshToken, refreshToken = refreshToken,
homeserverUrl = homeserverUrl, homeserverUrl = homeserverUrl,
oidcData = null, oAuthData = null,
loginTimestamp = Date(), loginTimestamp = Date(),
isTokenValid = isTokenValid, isTokenValid = isTokenValid,
loginType = loginType, loginType = loginType,

View file

@ -6,9 +6,9 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.matrix.impl.oidc package io.element.android.libraries.matrix.impl.oauth
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.oauth.AccountManagementAction
import org.matrix.rustcomponents.sdk.AccountManagementAction as RustAccountManagementAction import org.matrix.rustcomponents.sdk.AccountManagementAction as RustAccountManagementAction
fun AccountManagementAction.toRustAction(): RustAccountManagementAction { fun AccountManagementAction.toRustAction(): RustAccountManagementAction {

View file

@ -64,17 +64,17 @@ class AuthenticationExceptionMappingTest {
} }
@Test @Test
fun `mapping Oidc exceptions map to the Oidc Kotlin`() { fun `mapping Oidc exceptions map to the OAuth Kotlin`() {
assertThat(OAuthException.Generic("Generic").mapAuthenticationException()) assertThat(OAuthException.Generic("Generic").mapAuthenticationException())
.isException<AuthenticationException.Oidc>("Generic") .isException<AuthenticationException.OAuth>("Generic")
assertThat(OAuthException.CallbackUrlInvalid("CallbackUrlInvalid").mapAuthenticationException()) assertThat(OAuthException.CallbackUrlInvalid("CallbackUrlInvalid").mapAuthenticationException())
.isException<AuthenticationException.Oidc>("CallbackUrlInvalid") .isException<AuthenticationException.OAuth>("CallbackUrlInvalid")
assertThat(OAuthException.Cancelled("Cancelled").mapAuthenticationException()) assertThat(OAuthException.Cancelled("Cancelled").mapAuthenticationException())
.isException<AuthenticationException.Oidc>("Cancelled") .isException<AuthenticationException.OAuth>("Cancelled")
assertThat(OAuthException.MetadataInvalid("MetadataInvalid").mapAuthenticationException()) assertThat(OAuthException.MetadataInvalid("MetadataInvalid").mapAuthenticationException())
.isException<AuthenticationException.Oidc>("MetadataInvalid") .isException<AuthenticationException.OAuth>("MetadataInvalid")
assertThat(OAuthException.NotSupported("NotSupported").mapAuthenticationException()) assertThat(OAuthException.NotSupported("NotSupported").mapAuthenticationException())
.isException<AuthenticationException.Oidc>("NotSupported") .isException<AuthenticationException.OAuth>("NotSupported")
} }
private inline fun <reified T> ThrowableSubject.isException(message: String) { private inline fun <reified T> ThrowableSubject.isException(message: String) {

View file

@ -20,7 +20,7 @@ class HomeserverDetailsKtTest {
val homeserverLoginDetails = FakeFfiHomeserverLoginDetails( val homeserverLoginDetails = FakeFfiHomeserverLoginDetails(
url = "https://example.org", url = "https://example.org",
supportsPasswordLogin = true, supportsPasswordLogin = true,
supportsOidcLogin = false supportsOAuthLogin = false
) )
// When // When
@ -31,7 +31,7 @@ class HomeserverDetailsKtTest {
MatrixHomeServerDetails( MatrixHomeServerDetails(
url = "https://example.org", url = "https://example.org",
supportsPasswordLogin = true, supportsPasswordLogin = true,
supportsOidcLogin = false supportsOAuthLogin = false
) )
) )
} }

View file

@ -10,18 +10,18 @@ package io.element.android.libraries.matrix.impl.auth
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.test.auth.FAKE_REDIRECT_URL import io.element.android.libraries.matrix.test.auth.FAKE_REDIRECT_URL
import io.element.android.libraries.matrix.test.auth.FakeOidcRedirectUrlProvider import io.element.android.libraries.matrix.test.auth.FakeOAuthRedirectUrlProvider
import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.core.aBuildMeta
import org.junit.Test import org.junit.Test
class OidcConfigurationProviderTest { class OAuthConfigurationProviderTest {
@Test @Test
fun get() { fun get() {
val result = OidcConfigurationProvider( val result = OAuthConfigurationProvider(
buildMeta = aBuildMeta( buildMeta = aBuildMeta(
applicationName = "myName", applicationName = "myName",
), ),
oidcRedirectUrlProvider = FakeOidcRedirectUrlProvider(), oAuthRedirectUrlProvider = FakeOAuthRedirectUrlProvider(),
).get() ).get()
assertThat(result.clientName).isEqualTo("myName") assertThat(result.clientName).isEqualTo("myName")
assertThat(result.redirectUri).isEqualTo(FAKE_REDIRECT_URL) assertThat(result.redirectUri).isEqualTo(FAKE_REDIRECT_URL)

View file

@ -18,8 +18,8 @@ import org.junit.Test
class RustHomeserverLoginCompatibilityCheckerTest { class RustHomeserverLoginCompatibilityCheckerTest {
@Test @Test
fun `check - is valid if it supports OIDC login`() = runTest { fun `check - is valid if it supports OAuth login`() = runTest {
val sut = createChecker { FakeFfiHomeserverLoginDetails(supportsOidcLogin = true) } val sut = createChecker { FakeFfiHomeserverLoginDetails(supportsOAuthLogin = true) }
assertThat(sut.check("https://matrix.host.org").getOrNull()).isTrue() assertThat(sut.check("https://matrix.host.org").getOrNull()).isTrue()
} }

View file

@ -16,7 +16,7 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClientBuilder import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClientBuilder
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverLoginDetails import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverLoginDetails
import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory
import io.element.android.libraries.matrix.test.auth.FakeOidcRedirectUrlProvider import io.element.android.libraries.matrix.test.auth.FakeOAuthRedirectUrlProvider
import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
@ -64,9 +64,9 @@ class RustMatrixAuthenticationServiceTest {
sessionStore = sessionStore, sessionStore = sessionStore,
rustMatrixClientFactory = rustMatrixClientFactory, rustMatrixClientFactory = rustMatrixClientFactory,
passphraseGenerator = FakePassphraseGenerator(), passphraseGenerator = FakePassphraseGenerator(),
oidcConfigurationProvider = OidcConfigurationProvider( oAuthConfigurationProvider = OAuthConfigurationProvider(
buildMeta = aBuildMeta(), buildMeta = aBuildMeta(),
oidcRedirectUrlProvider = FakeOidcRedirectUrlProvider(), oAuthRedirectUrlProvider = FakeOAuthRedirectUrlProvider(),
), ),
) )
} }

View file

@ -32,7 +32,7 @@ class QrErrorMapperTest {
assertThat(QrErrorMapper.map(RustHumanQrLoginException.OtherDeviceNotSignedIn())).isEqualTo(QrLoginException.OtherDeviceNotSignedIn) assertThat(QrErrorMapper.map(RustHumanQrLoginException.OtherDeviceNotSignedIn())).isEqualTo(QrLoginException.OtherDeviceNotSignedIn)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.LinkingNotSupported())).isEqualTo(QrLoginException.LinkingNotSupported) assertThat(QrErrorMapper.map(RustHumanQrLoginException.LinkingNotSupported())).isEqualTo(QrLoginException.LinkingNotSupported)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.Unknown())).isEqualTo(QrLoginException.Unknown) assertThat(QrErrorMapper.map(RustHumanQrLoginException.Unknown())).isEqualTo(QrLoginException.Unknown)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.OAuthMetadataInvalid())).isEqualTo(QrLoginException.OidcMetadataInvalid) assertThat(QrErrorMapper.map(RustHumanQrLoginException.OAuthMetadataInvalid())).isEqualTo(QrLoginException.OAuthMetadataInvalid)
assertThat(QrErrorMapper.map(RustHumanQrLoginException.SlidingSyncNotAvailable())).isEqualTo(QrLoginException.SlidingSyncNotAvailable) assertThat(QrErrorMapper.map(RustHumanQrLoginException.SlidingSyncNotAvailable())).isEqualTo(QrLoginException.SlidingSyncNotAvailable)
} }
} }

View file

@ -14,11 +14,11 @@ import org.matrix.rustcomponents.sdk.NoHandle
class FakeFfiHomeserverLoginDetails( class FakeFfiHomeserverLoginDetails(
private val url: String = "https://example.org", private val url: String = "https://example.org",
private val supportsPasswordLogin: Boolean = false, private val supportsPasswordLogin: Boolean = false,
private val supportsOidcLogin: Boolean = false, private val supportsOAuthLogin: Boolean = false,
private val supportsSsoLogin: Boolean = false, private val supportsSsoLogin: Boolean = false,
) : HomeserverLoginDetails(NoHandle) { ) : HomeserverLoginDetails(NoHandle) {
override fun url(): String = url override fun url(): String = url
override fun supportsOauthLogin(): Boolean = supportsOidcLogin override fun supportsOauthLogin(): Boolean = supportsOAuthLogin
override fun supportsPasswordLogin(): Boolean = supportsPasswordLogin override fun supportsPasswordLogin(): Boolean = supportsPasswordLogin
override fun supportsSsoLogin(): Boolean = supportsSsoLogin override fun supportsSsoLogin(): Boolean = supportsSsoLogin
} }

View file

@ -36,7 +36,7 @@ class SessionKtTest {
assertThat(result.refreshToken).isEqualTo("refreshToken") assertThat(result.refreshToken).isEqualTo("refreshToken")
assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL) assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL)
assertThat(result.isTokenValid).isTrue() assertThat(result.isTokenValid).isTrue()
assertThat(result.oidcData).isNull() assertThat(result.oAuthData).isNull()
assertThat(result.loginType).isEqualTo(LoginType.PASSWORD) assertThat(result.loginType).isEqualTo(LoginType.PASSWORD)
assertThat(result.loginTimestamp).isNotNull() assertThat(result.loginTimestamp).isNotNull()
assertThat(result.passphrase).isEqualTo(A_SECRET) assertThat(result.passphrase).isEqualTo(A_SECRET)
@ -82,7 +82,7 @@ class SessionKtTest {
assertThat(result.refreshToken).isNull() assertThat(result.refreshToken).isNull()
assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL) assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL)
assertThat(result.isTokenValid).isTrue() assertThat(result.isTokenValid).isTrue()
assertThat(result.oidcData).isNull() assertThat(result.oAuthData).isNull()
assertThat(result.loginType).isEqualTo(LoginType.PASSWORD) assertThat(result.loginType).isEqualTo(LoginType.PASSWORD)
assertThat(result.loginTimestamp).isNotNull() assertThat(result.loginTimestamp).isNotNull()
assertThat(result.passphrase).isEqualTo(A_SECRET) assertThat(result.passphrase).isEqualTo(A_SECRET)

View file

@ -6,10 +6,10 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.matrix.impl.oidc package io.element.android.libraries.matrix.impl.oauth
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.oauth.AccountManagementAction
import io.element.android.libraries.matrix.test.A_DEVICE_ID import io.element.android.libraries.matrix.test.A_DEVICE_ID
import org.junit.Test import org.junit.Test
import org.matrix.rustcomponents.sdk.AccountManagementAction as RustAccountManagementAction import org.matrix.rustcomponents.sdk.AccountManagementAction as RustAccountManagementAction

View file

@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.media.MediaPreviewService import io.element.android.libraries.matrix.api.media.MediaPreviewService
import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.libraries.matrix.api.notification.NotificationService
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.oauth.AccountManagementAction
import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.pusher.PushersService
import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.JoinedRoom

View file

@ -12,8 +12,8 @@ import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.auth.ElementClassicSession import io.element.android.libraries.matrix.api.auth.ElementClassicSession
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.matrix.api.auth.OidcPrompt import io.element.android.libraries.matrix.api.auth.OAuthPrompt
import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.external.ExternalSession
import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData
import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep
@ -26,7 +26,7 @@ import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.simulateLongTask import io.element.android.tests.testutils.simulateLongTask
val A_OIDC_DATA = OidcDetails(url = "a-url") val AN_OAUTH_DATA = OAuthDetails(url = "a-url")
class FakeMatrixAuthenticationService( class FakeMatrixAuthenticationService(
var matrixClientResult: ((SessionId) -> Result<MatrixClient>)? = null, var matrixClientResult: ((SessionId) -> Result<MatrixClient>)? = null,
@ -37,8 +37,8 @@ class FakeMatrixAuthenticationService(
private val setElementClassicSessionResult: (ElementClassicSession?) -> Unit = { lambdaError() }, private val setElementClassicSessionResult: (ElementClassicSession?) -> Unit = { lambdaError() },
private val doSecretsContainBackupKeyResult: (UserId, String, String) -> Boolean = { _, _, _ -> lambdaError() }, private val doSecretsContainBackupKeyResult: (UserId, String, String) -> Boolean = { _, _, _ -> lambdaError() },
) : MatrixAuthenticationService { ) : MatrixAuthenticationService {
private var oidcError: Throwable? = null private var oAuthError: Throwable? = null
private var oidcCancelError: Throwable? = null private var oAuthCancelError: Throwable? = null
private var loginError: Throwable? = null private var loginError: Throwable? = null
private var matrixClient: MatrixClient? = null private var matrixClient: MatrixClient? = null
private var onAuthenticationListener: ((MatrixClient) -> Unit)? = null private var onAuthenticationListener: ((MatrixClient) -> Unit)? = null
@ -70,18 +70,18 @@ class FakeMatrixAuthenticationService(
return importCreatedSessionLambda(externalSession) return importCreatedSessionLambda(externalSession)
} }
override suspend fun getOidcUrl( override suspend fun getOAuthUrl(
prompt: OidcPrompt, prompt: OAuthPrompt,
loginHint: String?, loginHint: String?,
): Result<OidcDetails> = simulateLongTask { ): Result<OAuthDetails> = simulateLongTask {
oidcError?.let { Result.failure(it) } ?: Result.success(A_OIDC_DATA) oAuthError?.let { Result.failure(it) } ?: Result.success(AN_OAUTH_DATA)
} }
override suspend fun cancelOidcLogin(): Result<Unit> { override suspend fun cancelOAuthLogin(): Result<Unit> {
return oidcCancelError?.let { Result.failure(it) } ?: Result.success(Unit) return oAuthCancelError?.let { Result.failure(it) } ?: Result.success(Unit)
} }
override suspend fun loginWithOidc(callbackUrl: String): Result<SessionId> = simulateLongTask { override suspend fun loginWithOAuth(callbackUrl: String): Result<SessionId> = simulateLongTask {
loginError?.let { Result.failure(it) } ?: run { loginError?.let { Result.failure(it) } ?: run {
onAuthenticationListener?.invoke(matrixClient ?: FakeMatrixClient()) onAuthenticationListener?.invoke(matrixClient ?: FakeMatrixClient())
Result.success(A_USER_ID) Result.success(A_USER_ID)
@ -97,12 +97,12 @@ class FakeMatrixAuthenticationService(
onAuthenticationListener = lambda onAuthenticationListener = lambda
} }
fun givenOidcError(throwable: Throwable?) { fun givenOAuthError(throwable: Throwable?) {
oidcError = throwable oAuthError = throwable
} }
fun givenOidcCancelError(throwable: Throwable?) { fun givenOAuthCancelError(throwable: Throwable?) {
oidcCancelError = throwable oAuthCancelError = throwable
} }
fun givenLoginError(throwable: Throwable?) { fun givenLoginError(throwable: Throwable?) {

View file

@ -8,12 +8,12 @@
package io.element.android.libraries.matrix.test.auth package io.element.android.libraries.matrix.test.auth
import io.element.android.libraries.matrix.api.auth.OidcRedirectUrlProvider import io.element.android.libraries.matrix.api.auth.OAuthRedirectUrlProvider
const val FAKE_REDIRECT_URL = "io.element.android:/" const val FAKE_REDIRECT_URL = "io.element.android:/"
class FakeOidcRedirectUrlProvider( class FakeOAuthRedirectUrlProvider(
private val provideResult: String = FAKE_REDIRECT_URL, private val provideResult: String = FAKE_REDIRECT_URL,
) : OidcRedirectUrlProvider { ) : OAuthRedirectUrlProvider {
override fun provide() = provideResult override fun provide() = provideResult
} }

View file

@ -14,9 +14,9 @@ import io.element.android.libraries.matrix.test.A_HOMESERVER_URL
fun aMatrixHomeServerDetails( fun aMatrixHomeServerDetails(
url: String = A_HOMESERVER_URL, url: String = A_HOMESERVER_URL,
supportsPasswordLogin: Boolean = false, supportsPasswordLogin: Boolean = false,
supportsOidcLogin: Boolean = false, supportsOAuthLogin: Boolean = false,
) = MatrixHomeServerDetails( ) = MatrixHomeServerDetails(
url = url, url = url,
supportsPasswordLogin = supportsPasswordLogin, supportsPasswordLogin = supportsPasswordLogin,
supportsOidcLogin = supportsOidcLogin, supportsOAuthLogin = supportsOAuthLogin,
) )

View file

@ -8,16 +8,16 @@
package io.element.android.libraries.matrix.test.encryption package io.element.android.libraries.matrix.test.encryption
import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityOAuthResetHandle
import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle
class FakeIdentityOidcResetHandle( class FakeIdentityOAuthResetHandle(
override val url: String = "", override val url: String = "",
var resetOidcLambda: () -> Result<Unit> = { error("Not implemented") }, var resetOAuthLambda: () -> Result<Unit> = { error("Not implemented") },
var cancelLambda: () -> Unit = { error("Not implemented") }, var cancelLambda: () -> Unit = { error("Not implemented") },
) : IdentityOidcResetHandle { ) : IdentityOAuthResetHandle {
override suspend fun resetOidc(): Result<Unit> { override suspend fun resetOAuth(): Result<Unit> {
return resetOidcLambda() return resetOAuthLambda()
} }
override suspend fun cancel() { override suspend fun cancel() {

View file

@ -11,7 +11,7 @@ plugins {
} }
android { android {
namespace = "io.element.android.libraries.oidc.api" namespace = "io.element.android.libraries.oauth.api"
} }
dependencies { dependencies {

View file

@ -6,9 +6,9 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.oidc.api package io.element.android.libraries.oauth.api
sealed interface OidcAction { sealed interface OAuthAction {
data class GoBack(val toUnblock: Boolean = false) : OidcAction data class GoBack(val toUnblock: Boolean = false) : OAuthAction
data class Success(val url: String) : OidcAction data class Success(val url: String) : OAuthAction
} }

View file

@ -6,12 +6,12 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.oidc.api package io.element.android.libraries.oauth.api
import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.FlowCollector
interface OidcActionFlow { interface OAuthActionFlow {
fun post(oidcAction: OidcAction) fun post(oAuthAction: OAuthAction)
suspend fun collect(collector: FlowCollector<OidcAction?>) suspend fun collect(collector: FlowCollector<OAuthAction?>)
fun reset() fun reset()
} }

View file

@ -6,10 +6,10 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.oidc.api package io.element.android.libraries.oauth.api
import android.content.Intent import android.content.Intent
interface OidcIntentResolver { interface OAuthIntentResolver {
fun resolve(intent: Intent): OidcAction? fun resolve(intent: Intent): OAuthAction?
} }

View file

@ -16,7 +16,7 @@ plugins {
} }
android { android {
namespace = "io.element.android.libraries.oidc.impl" namespace = "io.element.android.libraries.oauth.impl"
testOptions { testOptions {
unitTests { unitTests {
@ -39,7 +39,7 @@ dependencies {
implementation(platform(libs.network.retrofit.bom)) implementation(platform(libs.network.retrofit.bom))
implementation(libs.network.retrofit) implementation(libs.network.retrofit)
implementation(libs.serialization.json) implementation(libs.serialization.json)
api(projects.libraries.oidc.api) api(projects.libraries.oauth.api)
testCommonDependencies(libs) testCommonDependencies(libs)
testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.matrix.test)

View file

@ -6,26 +6,26 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.oidc.impl package io.element.android.libraries.oauth.impl
import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.SingleIn import dev.zacsweers.metro.SingleIn
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
import io.element.android.libraries.oidc.api.OidcActionFlow import io.element.android.libraries.oauth.api.OAuthActionFlow
import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
@SingleIn(AppScope::class) @SingleIn(AppScope::class)
class DefaultOidcActionFlow : OidcActionFlow { class DefaultOAuthActionFlow : OAuthActionFlow {
private val mutableStateFlow = MutableStateFlow<OidcAction?>(null) private val mutableStateFlow = MutableStateFlow<OAuthAction?>(null)
override fun post(oidcAction: OidcAction) { override fun post(oAuthAction: OAuthAction) {
mutableStateFlow.value = oidcAction mutableStateFlow.value = oAuthAction
} }
override suspend fun collect(collector: FlowCollector<OidcAction?>) { override suspend fun collect(collector: FlowCollector<OAuthAction?>) {
mutableStateFlow.collect(collector) mutableStateFlow.collect(collector)
} }

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.oauth.impl
import android.content.Intent
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.oauth.api.OAuthAction
import io.element.android.libraries.oauth.api.OAuthIntentResolver
@ContributesBinding(AppScope::class)
class DefaultOAuthIntentResolver(
private val oAuthUrlParser: OAuthUrlParser,
) : OAuthIntentResolver {
override fun resolve(intent: Intent): OAuthAction? {
return oAuthUrlParser.parse(intent.dataString.orEmpty())
}
}

View file

@ -6,37 +6,37 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.oidc.impl package io.element.android.libraries.oauth.impl
import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.matrix.api.auth.OidcRedirectUrlProvider import io.element.android.libraries.matrix.api.auth.OAuthRedirectUrlProvider
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
fun interface OidcUrlParser { fun interface OAuthUrlParser {
fun parse(url: String): OidcAction? fun parse(url: String): OAuthAction?
} }
/** /**
* Simple parser for oidc url interception. * Simple parser for OAuth url interception.
* TODO Find documentation about the format. * TODO Find documentation about the format.
*/ */
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class DefaultOidcUrlParser( class DefaultOAuthUrlParser(
private val oidcRedirectUrlProvider: OidcRedirectUrlProvider, private val oAuthRedirectUrlProvider: OAuthRedirectUrlProvider,
) : OidcUrlParser { ) : OAuthUrlParser {
/** /**
* Return a OidcAction, or null if the url is not a OidcUrl. * Return a [OAuthAction], or null if the url is not an OAuth url.
* Note: * Note:
* When user press button "Cancel", we get the url: * When user press button "Cancel", we get the url:
* `io.element.android:/?error=access_denied&state=IFF1UETGye2ZA8pO` * `io.element.android:/?error=access_denied&state=IFF1UETGye2ZA8pO`
* On success, we get: * On success, we get:
* `io.element.android:/?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB` * `io.element.android:/?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB`
*/ */
override fun parse(url: String): OidcAction? { override fun parse(url: String): OAuthAction? {
if (url.startsWith(oidcRedirectUrlProvider.provide()).not()) return null if (url.startsWith(oAuthRedirectUrlProvider.provide()).not()) return null
if (url.contains("error=access_denied")) return OidcAction.GoBack() if (url.contains("error=access_denied")) return OAuthAction.GoBack()
if (url.contains("code=")) return OidcAction.Success(url) if (url.contains("code=")) return OAuthAction.Success(url)
// Other case not supported, let's crash the app for now // Other case not supported, let's crash the app for now
error("Not supported: $url") error("Not supported: $url")

View file

@ -1,34 +1,33 @@
/* /*
* Copyright (c) 2025 Element Creations Ltd. * Copyright (c) 2026 Element Creations Ltd.
* Copyright 2025 New Vector Ltd.
* *
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.oidc.impl package io.element.android.libraries.oauth.impl
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test
class DefaultOidcActionFlowTest { class DefaultOAuthActionFlowTest {
@Test @Test
fun `collect gets all the posted events`() = runTest { fun `collect gets all the posted events`() = runTest {
val data = mutableListOf<OidcAction?>() val data = mutableListOf<OAuthAction?>()
val sut = DefaultOidcActionFlow() val sut = DefaultOAuthActionFlow()
backgroundScope.launch { backgroundScope.launch {
sut.collect { action -> sut.collect { action ->
data.add(action) data.add(action)
} }
} }
sut.post(OidcAction.GoBack()) sut.post(OAuthAction.GoBack())
delay(1) delay(1)
sut.reset() sut.reset()
delay(1) delay(1)
assertThat(data).containsExactly(OidcAction.GoBack(), null) assertThat(data).containsExactly(OAuthAction.GoBack(), null)
} }
} }

View file

@ -1,19 +1,18 @@
/* /*
* Copyright (c) 2025 Element Creations Ltd. * Copyright (c) 2026 Element Creations Ltd.
* Copyright 2025 New Vector Ltd.
* *
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.oidc.impl package io.element.android.libraries.oauth.impl
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import androidx.core.net.toUri import androidx.core.net.toUri
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.test.auth.FakeOidcRedirectUrlProvider import io.element.android.libraries.matrix.test.auth.FakeOAuthRedirectUrlProvider
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
import org.junit.Assert.assertThrows import org.junit.Assert.assertThrows
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@ -21,36 +20,36 @@ import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment import org.robolectric.RuntimeEnvironment
@RunWith(RobolectricTestRunner::class) @RunWith(RobolectricTestRunner::class)
class DefaultOidcIntentResolverTest { class DefaultOAuthIntentResolverTest {
@Test @Test
fun `test resolve oidc go back`() { fun `test resolve OAuth go back`() {
val sut = createDefaultOidcIntentResolver() val sut = createDefaultOAuthIntentResolver()
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
action = Intent.ACTION_VIEW action = Intent.ACTION_VIEW
data = "io.element.android:/?error=access_denied&state=IFF1UETGye2ZA8pO".toUri() data = "io.element.android:/?error=access_denied&state=IFF1UETGye2ZA8pO".toUri()
} }
val result = sut.resolve(intent) val result = sut.resolve(intent)
assertThat(result).isEqualTo(OidcAction.GoBack()) assertThat(result).isEqualTo(OAuthAction.GoBack())
} }
@Test @Test
fun `test resolve oidc success`() { fun `test resolve OAuth success`() {
val sut = createDefaultOidcIntentResolver() val sut = createDefaultOAuthIntentResolver()
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
action = Intent.ACTION_VIEW action = Intent.ACTION_VIEW
data = "io.element.android:/?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB".toUri() data = "io.element.android:/?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB".toUri()
} }
val result = sut.resolve(intent) val result = sut.resolve(intent)
assertThat(result).isEqualTo( assertThat(result).isEqualTo(
OidcAction.Success( OAuthAction.Success(
url = "io.element.android:/?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB" url = "io.element.android:/?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB"
) )
) )
} }
@Test @Test
fun `test resolve oidc invalid`() { fun `test resolve OAuth invalid`() {
val sut = createDefaultOidcIntentResolver() val sut = createDefaultOAuthIntentResolver()
val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply { val intent = Intent(RuntimeEnvironment.getApplication(), Activity::class.java).apply {
action = Intent.ACTION_VIEW action = Intent.ACTION_VIEW
data = "io.element.android:/invalid".toUri() data = "io.element.android:/invalid".toUri()
@ -60,10 +59,10 @@ class DefaultOidcIntentResolverTest {
} }
} }
private fun createDefaultOidcIntentResolver(): DefaultOidcIntentResolver { private fun createDefaultOAuthIntentResolver(): DefaultOAuthIntentResolver {
return DefaultOidcIntentResolver( return DefaultOAuthIntentResolver(
oidcUrlParser = DefaultOidcUrlParser( oAuthUrlParser = DefaultOAuthUrlParser(
oidcRedirectUrlProvider = FakeOidcRedirectUrlProvider(), oAuthRedirectUrlProvider = FakeOAuthRedirectUrlProvider(),
), ),
) )
} }

View file

@ -1,59 +1,58 @@
/* /*
* Copyright (c) 2025 Element Creations Ltd. * Copyright (c) 2026 Element Creations Ltd.
* Copyright 2023-2025 New Vector Ltd.
* *
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.oidc.impl package io.element.android.libraries.oauth.impl
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.test.auth.FAKE_REDIRECT_URL import io.element.android.libraries.matrix.test.auth.FAKE_REDIRECT_URL
import io.element.android.libraries.matrix.test.auth.FakeOidcRedirectUrlProvider import io.element.android.libraries.matrix.test.auth.FakeOAuthRedirectUrlProvider
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
import org.junit.Assert import org.junit.Assert
import org.junit.Test import org.junit.Test
class DefaultOidcUrlParserTest { class DefaultOAuthUrlParserTest {
@Test @Test
fun `test empty url`() { fun `test empty url`() {
val sut = createDefaultOidcUrlParser() val sut = createDefaultOAuthUrlParser()
assertThat(sut.parse("")).isNull() assertThat(sut.parse("")).isNull()
} }
@Test @Test
fun `test regular url`() { fun `test regular url`() {
val sut = createDefaultOidcUrlParser() val sut = createDefaultOAuthUrlParser()
assertThat(sut.parse("https://matrix.org")).isNull() assertThat(sut.parse("https://matrix.org")).isNull()
} }
@Test @Test
fun `test cancel url`() { fun `test cancel url`() {
val sut = createDefaultOidcUrlParser() val sut = createDefaultOAuthUrlParser()
val aCancelUrl = "$FAKE_REDIRECT_URL?error=access_denied&state=IFF1UETGye2ZA8pO" val aCancelUrl = "$FAKE_REDIRECT_URL?error=access_denied&state=IFF1UETGye2ZA8pO"
assertThat(sut.parse(aCancelUrl)).isEqualTo(OidcAction.GoBack()) assertThat(sut.parse(aCancelUrl)).isEqualTo(OAuthAction.GoBack())
} }
@Test @Test
fun `test success url`() { fun `test success url`() {
val sut = createDefaultOidcUrlParser() val sut = createDefaultOAuthUrlParser()
val aSuccessUrl = "$FAKE_REDIRECT_URL?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB" val aSuccessUrl = "$FAKE_REDIRECT_URL?state=IFF1UETGye2ZA8pO&code=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB"
assertThat(sut.parse(aSuccessUrl)).isEqualTo(OidcAction.Success(aSuccessUrl)) assertThat(sut.parse(aSuccessUrl)).isEqualTo(OAuthAction.Success(aSuccessUrl))
} }
@Test @Test
fun `test unknown url`() { fun `test unknown url`() {
val sut = createDefaultOidcUrlParser() val sut = createDefaultOAuthUrlParser()
val anUnknownUrl = "$FAKE_REDIRECT_URL?state=IFF1UETGye2ZA8pO&goat=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB" val anUnknownUrl = "$FAKE_REDIRECT_URL?state=IFF1UETGye2ZA8pO&goat=y6X1GZeqA3xxOWcTeShgv8nkgFJXyzWB"
Assert.assertThrows(IllegalStateException::class.java) { Assert.assertThrows(IllegalStateException::class.java) {
assertThat(sut.parse(anUnknownUrl)) assertThat(sut.parse(anUnknownUrl))
} }
} }
private fun createDefaultOidcUrlParser(): DefaultOidcUrlParser { private fun createDefaultOAuthUrlParser(): DefaultOAuthUrlParser {
return DefaultOidcUrlParser( return DefaultOAuthUrlParser(
oidcRedirectUrlProvider = FakeOidcRedirectUrlProvider(), oAuthRedirectUrlProvider = FakeOAuthRedirectUrlProvider(),
) )
} }
} }

View file

@ -11,11 +11,11 @@ plugins {
} }
android { android {
namespace = "io.element.android.libraries.oidc.test" namespace = "io.element.android.libraries.oauth.test"
} }
dependencies { dependencies {
implementation(libs.coroutines.core) implementation(libs.coroutines.core)
api(projects.libraries.oidc.api) api(projects.libraries.oauth.api)
implementation(projects.tests.testutils) implementation(projects.tests.testutils)
} }

View file

@ -6,17 +6,17 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
package io.element.android.libraries.oidc.test package io.element.android.libraries.oauth.test
import android.content.Intent import android.content.Intent
import io.element.android.libraries.oidc.api.OidcAction import io.element.android.libraries.oauth.api.OAuthAction
import io.element.android.libraries.oidc.api.OidcIntentResolver import io.element.android.libraries.oauth.api.OAuthIntentResolver
import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaError
class FakeOidcIntentResolver( class FakeOAuthIntentResolver(
private val resolveResult: (Intent) -> OidcAction? = { lambdaError() } private val resolveResult: (Intent) -> OAuthAction? = { lambdaError() }
) : OidcIntentResolver { ) : OAuthIntentResolver {
override fun resolve(intent: Intent): OidcAction? { override fun resolve(intent: Intent): OAuthAction? {
return resolveResult(intent) return resolveResult(intent)
} }
} }

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.oauth.test.customtab
import io.element.android.libraries.oauth.api.OAuthAction
import io.element.android.libraries.oauth.api.OAuthActionFlow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableStateFlow
/**
* This is actually a copy of DefaultOAuthActionFlow.
*/
class FakeOAuthActionFlow : OAuthActionFlow {
private val mutableStateFlow = MutableStateFlow<OAuthAction?>(null)
override fun post(oAuthAction: OAuthAction) {
mutableStateFlow.value = oAuthAction
}
override suspend fun collect(collector: FlowCollector<OAuthAction?>) {
mutableStateFlow.collect(collector)
}
override fun reset() {
mutableStateFlow.value = null
}
}

View file

@ -1,24 +0,0 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.oidc.impl
import android.content.Intent
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.libraries.oidc.api.OidcIntentResolver
@ContributesBinding(AppScope::class)
class DefaultOidcIntentResolver(
private val oidcUrlParser: OidcUrlParser,
) : OidcIntentResolver {
override fun resolve(intent: Intent): OidcAction? {
return oidcUrlParser.parse(intent.dataString.orEmpty())
}
}

View file

@ -1,33 +0,0 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.oidc.test.customtab
import io.element.android.libraries.oidc.api.OidcAction
import io.element.android.libraries.oidc.api.OidcActionFlow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableStateFlow
/**
* This is actually a copy of DefaultOidcActionFlow.
*/
class FakeOidcActionFlow : OidcActionFlow {
private val mutableStateFlow = MutableStateFlow<OidcAction?>(null)
override fun post(oidcAction: OidcAction) {
mutableStateFlow.value = oidcAction
}
override suspend fun collect(collector: FlowCollector<OidcAction?>) {
mutableStateFlow.collect(collector)
}
override fun reset() {
mutableStateFlow.value = null
}
}

View file

@ -24,8 +24,8 @@ data class SessionData(
val refreshToken: String?, val refreshToken: String?,
/** The homeserver URL of the session. */ /** The homeserver URL of the session. */
val homeserverUrl: String, val homeserverUrl: String,
/** The Open ID Connect info for this session, if any. */ /** The Open Authorization info for this session, if any. */
val oidcData: String?, val oAuthData: String?,
/** The timestamp of the last login. May be `null` in very old sessions. */ /** The timestamp of the last login. May be `null` in very old sessions. */
val loginTimestamp: Date?, val loginTimestamp: Date?,
/** Whether the [accessToken] is valid or not. */ /** Whether the [accessToken] is valid or not. */

View file

@ -20,7 +20,7 @@ internal fun SessionData.toDbModel(): DbSessionData {
accessToken = accessToken, accessToken = accessToken,
refreshToken = refreshToken, refreshToken = refreshToken,
homeserverUrl = homeserverUrl, homeserverUrl = homeserverUrl,
oidcData = oidcData, oidcData = oAuthData,
loginTimestamp = loginTimestamp?.time, loginTimestamp = loginTimestamp?.time,
isTokenValid = if (isTokenValid) 1L else 0L, isTokenValid = if (isTokenValid) 1L else 0L,
loginType = loginType.name, loginType = loginType.name,
@ -41,7 +41,7 @@ internal fun DbSessionData.toApiModel(): SessionData {
accessToken = accessToken, accessToken = accessToken,
refreshToken = refreshToken, refreshToken = refreshToken,
homeserverUrl = homeserverUrl, homeserverUrl = homeserverUrl,
oidcData = oidcData, oAuthData = oidcData,
loginTimestamp = loginTimestamp?.let { Date(it) }, loginTimestamp = loginTimestamp?.let { Date(it) },
isTokenValid = isTokenValid == 1L, isTokenValid = isTokenValid == 1L,
loginType = LoginType.fromName(loginType ?: LoginType.UNKNOWN.name), loginType = LoginType.fromName(loginType ?: LoginType.UNKNOWN.name),

View file

@ -30,7 +30,7 @@ fun aSessionData(
accessToken = accessToken, accessToken = accessToken,
refreshToken = refreshToken, refreshToken = refreshToken,
homeserverUrl = "aHomeserverUrl", homeserverUrl = "aHomeserverUrl",
oidcData = null, oAuthData = null,
loginTimestamp = null, loginTimestamp = null,
isTokenValid = isTokenValid, isTokenValid = isTokenValid,
loginType = LoginType.UNKNOWN, loginType = LoginType.UNKNOWN,

View file

@ -120,7 +120,7 @@ fun DependencyHandlerScope.allLibrariesImpl() {
implementation(project(":libraries:troubleshoot:impl")) implementation(project(":libraries:troubleshoot:impl"))
implementation(project(":libraries:fullscreenintent:impl")) implementation(project(":libraries:fullscreenintent:impl"))
implementation(project(":libraries:wellknown:impl")) implementation(project(":libraries:wellknown:impl"))
implementation(project(":libraries:oidc:impl")) implementation(project(":libraries:oauth:impl"))
implementation(project(":libraries:workmanager:impl")) implementation(project(":libraries:workmanager:impl"))
implementation(project(":libraries:recentemojis:impl")) implementation(project(":libraries:recentemojis:impl"))
} }