Skip to content

feat(auth): Removed dependency on oauth2 token for refreshToken and move to initiateAuth for hostedUI #2543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 23, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,6 @@ internal class HostedUIClient private constructor(
return HostedUIHttpHelper.fetchTokens(createFetchTokenUrl(), createFetchTokenHeaders(), body)
}

fun fetchRefreshedToken(refreshToken: String): CognitoUserPoolTokens {
val body = mapOf(
"grant_type" to "refresh_token",
"client_id" to configuration.appClient,
"redirect_uri" to configuration.signInRedirectURI,
"refresh_token" to refreshToken
)
return HostedUIHttpHelper.fetchTokens(createFetchTokenUrl(), createFetchTokenHeaders(), body)
}

private fun createAuthorizeUri(hostedUIOptions: HostedUIOptions): Uri {
// Build the complete web domain to launch the login screen
val builder = Uri.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ import aws.sdk.kotlin.services.cognitoidentityprovider.initiateAuth
import aws.sdk.kotlin.services.cognitoidentityprovider.model.AuthFlowType
import aws.smithy.kotlin.runtime.time.Instant
import com.amplifyframework.auth.cognito.AuthEnvironment
import com.amplifyframework.auth.cognito.exceptions.configuration.InvalidOauthConfigurationException
import com.amplifyframework.auth.cognito.helpers.AuthHelper
import com.amplifyframework.auth.cognito.helpers.SessionHelper
import com.amplifyframework.auth.exceptions.NotAuthorizedException
import com.amplifyframework.auth.exceptions.SessionExpiredException
import com.amplifyframework.auth.exceptions.SignedOutException
import com.amplifyframework.auth.exceptions.UnknownException
import com.amplifyframework.statemachine.Action
import com.amplifyframework.statemachine.codegen.actions.FetchAuthSessionActions
import com.amplifyframework.statemachine.codegen.data.AWSCredentials
Expand Down Expand Up @@ -109,50 +107,6 @@ internal object FetchAuthSessionCognitoActions : FetchAuthSessionActions {
dispatcher.send(evt)
}

override fun refreshHostedUIUserPoolTokensAction(signedInData: SignedInData) =
Action<AuthEnvironment>("RefreshHostedUITokens") { id, dispatcher ->
logger.verbose("$id Starting execution")
val evt = try {
val username = signedInData.username
val refreshToken = signedInData.cognitoUserPoolTokens.refreshToken
if (hostedUIClient == null) throw InvalidOauthConfigurationException()
if (refreshToken == null) throw UnknownException("Unable to refresh token due to missing refreshToken.")

val refreshedUserPoolTokens = hostedUIClient.fetchRefreshedToken(
signedInData.cognitoUserPoolTokens.refreshToken
).copy(
// A refresh does not provide a new refresh token,
// so we rebuild the new token with the old refresh token.
refreshToken = signedInData.cognitoUserPoolTokens.refreshToken
)

val updatedSignedInData = signedInData.copy(
userId = refreshedUserPoolTokens.accessToken?.let(SessionHelper::getUserSub) ?: signedInData.userId,
username = refreshedUserPoolTokens.accessToken?.let(SessionHelper::getUsername) ?: username,
cognitoUserPoolTokens = refreshedUserPoolTokens
)

if (configuration.identityPool != null) {
val logins = LoginsMapProvider.CognitoUserPoolLogins(
configuration.userPool?.region,
configuration.userPool?.poolId,
refreshedUserPoolTokens.idToken!!
)
RefreshSessionEvent(RefreshSessionEvent.EventType.RefreshAuthSession(updatedSignedInData, logins))
} else {
RefreshSessionEvent(RefreshSessionEvent.EventType.Refreshed(updatedSignedInData))
}
} catch (notAuthorized: aws.sdk.kotlin.services.cognitoidentityprovider.model.NotAuthorizedException) {
// TODO: identity not authorized exception from response
val error = SessionExpiredException(cause = notAuthorized)
AuthorizationEvent(AuthorizationEvent.EventType.ThrowError(error))
} catch (e: Exception) {
AuthorizationEvent(AuthorizationEvent.EventType.ThrowError(e))
}
logger.verbose("$id Sending event ${evt.type}")
dispatcher.send(evt)
}

override fun refreshAuthSessionAction(logins: LoginsMapProvider) =
Action<AuthEnvironment>("RefreshAuthSession") { id, dispatcher ->
logger.verbose("$id Starting execution")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import com.amplifyframework.statemachine.codegen.data.SignedInData

internal interface FetchAuthSessionActions {
fun refreshUserPoolTokensAction(signedInData: SignedInData): Action
fun refreshHostedUIUserPoolTokensAction(signedInData: SignedInData): Action
fun refreshAuthSessionAction(logins: LoginsMapProvider): Action
fun fetchIdentityAction(loginsMap: LoginsMapProvider): Action
fun fetchAWSCredentialsAction(identityId: String, loginsMap: LoginsMapProvider): Action
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import com.amplifyframework.statemachine.StateMachineResolver
import com.amplifyframework.statemachine.StateResolution
import com.amplifyframework.statemachine.codegen.actions.FetchAuthSessionActions
import com.amplifyframework.statemachine.codegen.data.AmplifyCredential
import com.amplifyframework.statemachine.codegen.data.SignInMethod
import com.amplifyframework.statemachine.codegen.data.SignedInData
import com.amplifyframework.statemachine.codegen.events.FetchAuthSessionEvent
import com.amplifyframework.statemachine.codegen.events.RefreshSessionEvent
Expand Down Expand Up @@ -82,16 +81,9 @@ internal sealed class RefreshSessionState : State {
return when (oldState) {
is NotStarted -> when (refreshSessionEvent) {
is RefreshSessionEvent.EventType.RefreshUserPoolTokens -> {
val action = when (refreshSessionEvent.signedInData.signInMethod) {
is SignInMethod.HostedUI -> {
fetchAuthSessionActions.refreshHostedUIUserPoolTokensAction(
refreshSessionEvent.signedInData
)
}
else -> {
fetchAuthSessionActions.refreshUserPoolTokensAction(refreshSessionEvent.signedInData)
}
}
val action = fetchAuthSessionActions.refreshUserPoolTokensAction(
refreshSessionEvent.signedInData
)
StateResolution(RefreshingUserPoolTokens(refreshSessionEvent.signedInData), listOf(action))
}
is RefreshSessionEvent.EventType.RefreshUnAuthSession -> {
Expand Down