Skip to content

Commit 4476028

Browse files
authored
chore(auth): Refactor fetchAuthSession to useCase (#3017)
1 parent 179a95f commit 4476028

File tree

11 files changed

+389
-211
lines changed

11 files changed

+389
-211
lines changed

aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthPlugin.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ class AWSCognitoAuthPlugin : AuthPlugin<AWSCognitoAuthService>() {
176176
logger
177177
)
178178

179-
useCaseFactory = AuthUseCaseFactory(realPlugin, authEnvironment, authStateMachine)
179+
useCaseFactory = AuthUseCaseFactory(authEnvironment, authStateMachine)
180180

181181
blockQueueChannelWhileConfiguring()
182182
}
@@ -291,10 +291,10 @@ class AWSCognitoAuthPlugin : AuthPlugin<AWSCognitoAuthService>() {
291291
options: AuthFetchSessionOptions,
292292
onSuccess: Consumer<AuthSession>,
293293
onError: Consumer<AuthException>
294-
) = enqueue(onSuccess, onError) { queueFacade.fetchAuthSession(options) }
294+
) = enqueue(onSuccess, onError) { useCaseFactory.fetchAuthSession().execute(options) }
295295

296296
override fun fetchAuthSession(onSuccess: Consumer<AuthSession>, onError: Consumer<AuthException>) =
297-
enqueue(onSuccess, onError) { queueFacade.fetchAuthSession() }
297+
enqueue(onSuccess, onError) { useCaseFactory.fetchAuthSession().execute() }
298298

299299
override fun rememberDevice(onSuccess: Action, onError: Consumer<AuthException>) =
300300
enqueue(onSuccess, onError) { useCaseFactory.rememberDevice().execute() }

aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthSession.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,7 @@ internal fun AmplifyCredential.isValid(): Boolean = when (this) {
6666
else -> false
6767
}
6868

69-
internal fun AmplifyCredential.getCognitoSession(
70-
exception: AuthException? = null
71-
): AWSAuthSessionBehavior<AWSCognitoUserPoolTokens> {
69+
internal fun AmplifyCredential.getCognitoSession(exception: AuthException? = null): AWSCognitoAuthSession {
7270
fun getCredentialsResult(
7371
awsCredentials: CognitoCredentials,
7472
exception: AuthException?

aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/KotlinAuthFacadeInternal.kt

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@ package com.amplifyframework.auth.cognito
1818
import android.app.Activity
1919
import android.content.Intent
2020
import com.amplifyframework.auth.AuthProvider
21-
import com.amplifyframework.auth.AuthSession
2221
import com.amplifyframework.auth.cognito.options.FederateToIdentityPoolOptions
2322
import com.amplifyframework.auth.cognito.result.FederateToIdentityPoolResult
2423
import com.amplifyframework.auth.options.AuthConfirmSignInOptions
25-
import com.amplifyframework.auth.options.AuthFetchSessionOptions
2624
import com.amplifyframework.auth.options.AuthSignInOptions
2725
import com.amplifyframework.auth.options.AuthSignOutOptions
2826
import com.amplifyframework.auth.options.AuthWebUISignInOptions
@@ -118,21 +116,6 @@ internal class KotlinAuthFacadeInternal(private val delegate: RealAWSCognitoAuth
118116
delegate.handleWebUISignInResponse(intent)
119117
}
120118

121-
suspend fun fetchAuthSession(): AuthSession = suspendCoroutine { continuation ->
122-
delegate.fetchAuthSession(
123-
{ continuation.resume(it) },
124-
{ continuation.resumeWithException(it) }
125-
)
126-
}
127-
128-
suspend fun fetchAuthSession(options: AuthFetchSessionOptions): AuthSession = suspendCoroutine { continuation ->
129-
delegate.fetchAuthSession(
130-
options,
131-
{ continuation.resume(it) },
132-
{ continuation.resumeWithException(it) }
133-
)
134-
}
135-
136119
suspend fun signOut(): AuthSignOutResult = suspendCoroutine { continuation ->
137120
delegate.signOut { continuation.resume(it) }
138121
}

aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt

Lines changed: 0 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,11 @@ import com.amplifyframework.auth.AuthCodeDeliveryDetails
2929
import com.amplifyframework.auth.AuthException
3030
import com.amplifyframework.auth.AuthFactorType
3131
import com.amplifyframework.auth.AuthProvider
32-
import com.amplifyframework.auth.AuthSession
3332
import com.amplifyframework.auth.MFAType
3433
import com.amplifyframework.auth.cognito.exceptions.configuration.InvalidOauthConfigurationException
3534
import com.amplifyframework.auth.cognito.exceptions.configuration.InvalidUserPoolConfigurationException
3635
import com.amplifyframework.auth.cognito.exceptions.invalidstate.SignedInException
3736
import com.amplifyframework.auth.cognito.exceptions.service.HostedUISignOutException
38-
import com.amplifyframework.auth.cognito.exceptions.service.InvalidAccountTypeException
3937
import com.amplifyframework.auth.cognito.exceptions.service.InvalidParameterException
4038
import com.amplifyframework.auth.cognito.exceptions.service.UserCancelledException
4139
import com.amplifyframework.auth.cognito.helpers.HostedUIHelper
@@ -57,15 +55,9 @@ import com.amplifyframework.auth.cognito.result.FederateToIdentityPoolResult
5755
import com.amplifyframework.auth.cognito.result.GlobalSignOutError
5856
import com.amplifyframework.auth.cognito.result.HostedUIError
5957
import com.amplifyframework.auth.cognito.result.RevokeTokenError
60-
import com.amplifyframework.auth.exceptions.ConfigurationException
6158
import com.amplifyframework.auth.exceptions.InvalidStateException
62-
import com.amplifyframework.auth.exceptions.NotAuthorizedException
63-
import com.amplifyframework.auth.exceptions.ServiceException
64-
import com.amplifyframework.auth.exceptions.SessionExpiredException
65-
import com.amplifyframework.auth.exceptions.SignedOutException
6659
import com.amplifyframework.auth.exceptions.UnknownException
6760
import com.amplifyframework.auth.options.AuthConfirmSignInOptions
68-
import com.amplifyframework.auth.options.AuthFetchSessionOptions
6961
import com.amplifyframework.auth.options.AuthSignInOptions
7062
import com.amplifyframework.auth.options.AuthSignOutOptions
7163
import com.amplifyframework.auth.options.AuthWebUISignInOptions
@@ -112,9 +104,6 @@ import java.lang.ref.WeakReference
112104
import java.util.concurrent.CountDownLatch
113105
import java.util.concurrent.TimeUnit
114106
import java.util.concurrent.atomic.AtomicReference
115-
import kotlin.coroutines.resume
116-
import kotlin.coroutines.resumeWithException
117-
import kotlin.coroutines.suspendCoroutine
118107
import kotlinx.coroutines.flow.collect
119108
import kotlinx.coroutines.flow.takeWhile
120109

@@ -990,142 +979,6 @@ internal class RealAWSCognitoAuthPlugin(
990979
}
991980
}
992981

993-
private suspend fun getSession(): AWSCognitoAuthSession = suspendCoroutine { continuation ->
994-
fetchAuthSession(
995-
{ authSession ->
996-
if (authSession is AWSCognitoAuthSession) {
997-
continuation.resume(authSession)
998-
} else {
999-
continuation.resumeWithException(
1000-
UnknownException(
1001-
message = "fetchAuthSession did not return a type of AWSCognitoAuthSession"
1002-
)
1003-
)
1004-
}
1005-
},
1006-
{ continuation.resumeWithException(it) }
1007-
)
1008-
}
1009-
1010-
fun fetchAuthSession(onSuccess: Consumer<AuthSession>, onError: Consumer<AuthException>) {
1011-
fetchAuthSession(AuthFetchSessionOptions.defaults(), onSuccess, onError)
1012-
}
1013-
1014-
fun fetchAuthSession(
1015-
options: AuthFetchSessionOptions,
1016-
onSuccess: Consumer<AuthSession>,
1017-
onError: Consumer<AuthException>
1018-
) {
1019-
val forceRefresh = options.forceRefresh
1020-
authStateMachine.getCurrentState { authState ->
1021-
when (val authZState = authState.authZState) {
1022-
is AuthorizationState.Configured -> {
1023-
authStateMachine.send(AuthorizationEvent(AuthorizationEvent.EventType.FetchUnAuthSession))
1024-
_fetchAuthSession(onSuccess)
1025-
}
1026-
is AuthorizationState.SessionEstablished -> {
1027-
val credential = authZState.amplifyCredential
1028-
if (!credential.isValid() || forceRefresh) {
1029-
if (credential is AmplifyCredential.IdentityPoolFederated) {
1030-
authStateMachine.send(
1031-
AuthorizationEvent(
1032-
AuthorizationEvent.EventType.StartFederationToIdentityPool(
1033-
credential.federatedToken,
1034-
credential.identityId,
1035-
credential
1036-
)
1037-
)
1038-
)
1039-
} else {
1040-
authStateMachine.send(
1041-
AuthorizationEvent(AuthorizationEvent.EventType.RefreshSession(credential))
1042-
)
1043-
}
1044-
_fetchAuthSession(onSuccess)
1045-
} else {
1046-
onSuccess.accept(credential.getCognitoSession())
1047-
}
1048-
}
1049-
is AuthorizationState.Error -> {
1050-
val error = authZState.exception
1051-
if (error is SessionError) {
1052-
val amplifyCredential = error.amplifyCredential
1053-
if (amplifyCredential is AmplifyCredential.IdentityPoolFederated) {
1054-
authStateMachine.send(
1055-
AuthorizationEvent(
1056-
AuthorizationEvent.EventType.StartFederationToIdentityPool(
1057-
amplifyCredential.federatedToken,
1058-
amplifyCredential.identityId,
1059-
amplifyCredential
1060-
)
1061-
)
1062-
)
1063-
} else {
1064-
authStateMachine.send(
1065-
AuthorizationEvent(AuthorizationEvent.EventType.RefreshSession(amplifyCredential))
1066-
)
1067-
}
1068-
_fetchAuthSession(onSuccess)
1069-
} else {
1070-
onError.accept(InvalidStateException())
1071-
}
1072-
}
1073-
else -> onError.accept(InvalidStateException())
1074-
}
1075-
}
1076-
}
1077-
1078-
private fun _fetchAuthSession(onSuccess: Consumer<AuthSession>) {
1079-
val token = StateChangeListenerToken()
1080-
authStateMachine.listen(
1081-
token,
1082-
{ authState ->
1083-
when (val authZState = authState.authZState) {
1084-
is AuthorizationState.SessionEstablished -> {
1085-
authStateMachine.cancel(token)
1086-
onSuccess.accept(authZState.amplifyCredential.getCognitoSession())
1087-
}
1088-
is AuthorizationState.Error -> {
1089-
authStateMachine.cancel(token)
1090-
when (val error = authZState.exception) {
1091-
is SessionError -> {
1092-
when (val innerException = error.exception) {
1093-
is SignedOutException -> {
1094-
onSuccess.accept(error.amplifyCredential.getCognitoSession(innerException))
1095-
}
1096-
is SessionExpiredException -> {
1097-
onSuccess.accept(error.amplifyCredential.getCognitoSession(innerException))
1098-
sendHubEvent(AuthChannelEventName.SESSION_EXPIRED.toString())
1099-
}
1100-
is ServiceException -> {
1101-
onSuccess.accept(error.amplifyCredential.getCognitoSession(innerException))
1102-
}
1103-
is NotAuthorizedException -> {
1104-
onSuccess.accept(error.amplifyCredential.getCognitoSession(innerException))
1105-
}
1106-
else -> {
1107-
val errorResult = UnknownException("Fetch auth session failed.", innerException)
1108-
onSuccess.accept(error.amplifyCredential.getCognitoSession(errorResult))
1109-
}
1110-
}
1111-
}
1112-
is ConfigurationException -> {
1113-
val errorResult = InvalidAccountTypeException(error)
1114-
onSuccess.accept(AmplifyCredential.Empty.getCognitoSession(errorResult))
1115-
}
1116-
else -> {
1117-
val errorResult = UnknownException("Fetch auth session failed.", error)
1118-
onSuccess.accept(AmplifyCredential.Empty.getCognitoSession(errorResult))
1119-
}
1120-
}
1121-
}
1122-
else -> Unit
1123-
}
1124-
},
1125-
null
1126-
)
1127-
}
1128-
1129982
fun signOut(onComplete: Consumer<AuthSignOutResult>) {
1130983
signOut(AuthSignOutOptions.builder().build(), onComplete)
1131984
}

aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/usecases/AuthUseCaseFactory.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,19 @@ package com.amplifyframework.auth.cognito.usecases
1717

1818
import com.amplifyframework.auth.cognito.AuthEnvironment
1919
import com.amplifyframework.auth.cognito.AuthStateMachine
20-
import com.amplifyframework.auth.cognito.RealAWSCognitoAuthPlugin
2120
import com.amplifyframework.auth.cognito.helpers.WebAuthnHelper
2221
import com.amplifyframework.auth.cognito.requireIdentityProviderClient
2322
import com.amplifyframework.auth.plugins.core.AuthHubEventEmitter
2423

2524
internal class AuthUseCaseFactory(
26-
private val plugin: RealAWSCognitoAuthPlugin,
2725
private val authEnvironment: AuthEnvironment,
2826
private val stateMachine: AuthStateMachine,
2927
private val hubEmitter: AuthHubEventEmitter = AuthHubEventEmitter()
3028
) {
3129

32-
fun fetchAuthSession() = FetchAuthSessionUseCase(plugin)
30+
fun fetchAuthSession() = FetchAuthSessionUseCase(
31+
stateMachine = stateMachine
32+
)
3333

3434
fun associateWebAuthnCredential() = AssociateWebAuthnCredentialUseCase(
3535
client = authEnvironment.requireIdentityProviderClient(),

aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/usecases/FetchAuthSessionUseCase.kt

Lines changed: 99 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,110 @@
1515

1616
package com.amplifyframework.auth.cognito.usecases
1717

18+
import com.amplifyframework.auth.AuthChannelEventName
1819
import com.amplifyframework.auth.cognito.AWSCognitoAuthSession
19-
import com.amplifyframework.auth.cognito.RealAWSCognitoAuthPlugin
20-
import kotlin.coroutines.resume
21-
import kotlin.coroutines.resumeWithException
22-
import kotlin.coroutines.suspendCoroutine
20+
import com.amplifyframework.auth.cognito.AuthStateMachine
21+
import com.amplifyframework.auth.cognito.exceptions.service.InvalidAccountTypeException
22+
import com.amplifyframework.auth.cognito.getCognitoSession
23+
import com.amplifyframework.auth.cognito.isValid
24+
import com.amplifyframework.auth.exceptions.ConfigurationException
25+
import com.amplifyframework.auth.exceptions.InvalidStateException
26+
import com.amplifyframework.auth.exceptions.NotAuthorizedException
27+
import com.amplifyframework.auth.exceptions.ServiceException
28+
import com.amplifyframework.auth.exceptions.SessionExpiredException
29+
import com.amplifyframework.auth.exceptions.SignedOutException
30+
import com.amplifyframework.auth.exceptions.UnknownException
31+
import com.amplifyframework.auth.options.AuthFetchSessionOptions
32+
import com.amplifyframework.auth.plugins.core.AuthHubEventEmitter
33+
import com.amplifyframework.statemachine.codegen.data.AmplifyCredential
34+
import com.amplifyframework.statemachine.codegen.errors.SessionError
35+
import com.amplifyframework.statemachine.codegen.events.AuthorizationEvent
36+
import com.amplifyframework.statemachine.codegen.states.AuthorizationState
37+
import kotlinx.coroutines.flow.first
38+
import kotlinx.coroutines.flow.mapNotNull
2339

2440
internal class FetchAuthSessionUseCase(
25-
private val plugin: RealAWSCognitoAuthPlugin
41+
private val stateMachine: AuthStateMachine,
42+
private val emitter: AuthHubEventEmitter = AuthHubEventEmitter()
2643
) {
27-
suspend fun execute(): AWSCognitoAuthSession {
28-
// TODO - we should migrate the fetch auth session business logic to this class
29-
val session = suspendCoroutine { continuation ->
30-
plugin.fetchAuthSession(
31-
onSuccess = { continuation.resume(it) },
32-
onError = { continuation.resumeWithException(it) }
44+
suspend fun execute(options: AuthFetchSessionOptions = AuthFetchSessionOptions.defaults()): AWSCognitoAuthSession =
45+
when (val authZState = stateMachine.getCurrentState().authZState) {
46+
is AuthorizationState.Configured -> {
47+
stateMachine.send(AuthorizationEvent(AuthorizationEvent.EventType.FetchUnAuthSession))
48+
listenForSessionEstablished()
49+
}
50+
is AuthorizationState.SessionEstablished -> {
51+
val credential = authZState.amplifyCredential
52+
if (!credential.isValid() || options.forceRefresh) {
53+
sendRefreshSessionEvent(credential)
54+
listenForSessionEstablished()
55+
} else {
56+
credential.getCognitoSession()
57+
}
58+
}
59+
is AuthorizationState.Error -> {
60+
val error = authZState.exception
61+
if (error is SessionError) {
62+
sendRefreshSessionEvent(error.amplifyCredential)
63+
listenForSessionEstablished()
64+
} else {
65+
throw InvalidStateException()
66+
}
67+
}
68+
else -> throw InvalidStateException()
69+
}
70+
71+
private fun sendRefreshSessionEvent(credential: AmplifyCredential) {
72+
if (credential is AmplifyCredential.IdentityPoolFederated) {
73+
stateMachine.send(
74+
AuthorizationEvent(
75+
AuthorizationEvent.EventType.StartFederationToIdentityPool(
76+
credential.federatedToken,
77+
credential.identityId,
78+
credential
79+
)
80+
)
3381
)
82+
} else {
83+
stateMachine.send(AuthorizationEvent(AuthorizationEvent.EventType.RefreshSession(credential)))
3484
}
35-
return session as AWSCognitoAuthSession
85+
}
86+
87+
private suspend fun listenForSessionEstablished(): AWSCognitoAuthSession {
88+
val session = stateMachine.stateTransitions.mapNotNull { authState ->
89+
when (val authZState = authState.authZState) {
90+
is AuthorizationState.SessionEstablished -> authZState.amplifyCredential.getCognitoSession()
91+
is AuthorizationState.Error -> {
92+
when (val error = authZState.exception) {
93+
is SessionError -> {
94+
when (val innerException = error.exception) {
95+
is SignedOutException -> error.amplifyCredential.getCognitoSession(innerException)
96+
is ServiceException -> error.amplifyCredential.getCognitoSession(innerException)
97+
is NotAuthorizedException -> error.amplifyCredential.getCognitoSession(innerException)
98+
is SessionExpiredException -> {
99+
emitter.sendHubEvent(AuthChannelEventName.SESSION_EXPIRED.toString())
100+
error.amplifyCredential.getCognitoSession(innerException)
101+
}
102+
else -> {
103+
val errorResult = UnknownException("Fetch auth session failed.", innerException)
104+
error.amplifyCredential.getCognitoSession(errorResult)
105+
}
106+
}
107+
}
108+
is ConfigurationException -> {
109+
val errorResult = InvalidAccountTypeException(error)
110+
AmplifyCredential.Empty.getCognitoSession(errorResult)
111+
}
112+
else -> {
113+
val errorResult = UnknownException("Fetch auth session failed.", error)
114+
AmplifyCredential.Empty.getCognitoSession(errorResult)
115+
}
116+
}
117+
}
118+
else -> null // no-op
119+
}
120+
}.first()
121+
122+
return session
36123
}
37124
}

0 commit comments

Comments
 (0)