Skip to content

Commit 2f0253d

Browse files
committed
Update AuthProvider to create/get passkeys and check available factors
1 parent 7ec52c3 commit 2f0253d

File tree

1 file changed

+65
-0
lines changed
  • authenticator/src/main/java/com/amplifyframework/ui/authenticator/util

1 file changed

+65
-0
lines changed

authenticator/src/main/java/com/amplifyframework/ui/authenticator/util/AuthProvider.kt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,33 @@
1515

1616
package com.amplifyframework.ui.authenticator.util
1717

18+
import android.app.Activity
19+
import aws.sdk.kotlin.services.cognitoidentityprovider.getUserAuthFactors
20+
import aws.sdk.kotlin.services.cognitoidentityprovider.model.AuthFactorType as KotlinAuthFactorType
1821
import com.amplifyframework.auth.AWSCognitoAuthMetadataType
1922
import com.amplifyframework.auth.AuthChannelEventName
2023
import com.amplifyframework.auth.AuthCodeDeliveryDetails
2124
import com.amplifyframework.auth.AuthException
25+
import com.amplifyframework.auth.AuthFactorType
2226
import com.amplifyframework.auth.AuthSession
2327
import com.amplifyframework.auth.AuthUser
2428
import com.amplifyframework.auth.AuthUserAttribute
2529
import com.amplifyframework.auth.AuthUserAttributeKey
2630
import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin
31+
import com.amplifyframework.auth.cognito.AWSCognitoAuthSession
2732
import com.amplifyframework.auth.cognito.PasswordProtectionSettings
2833
import com.amplifyframework.auth.cognito.UsernameAttribute
2934
import com.amplifyframework.auth.cognito.VerificationMechanism as AmplifyVerificationMechanism
35+
import com.amplifyframework.auth.cognito.exceptions.configuration.InvalidUserPoolConfigurationException
36+
import com.amplifyframework.auth.exceptions.UnknownException
3037
import com.amplifyframework.auth.options.AuthConfirmSignInOptions
3138
import com.amplifyframework.auth.options.AuthSignInOptions
3239
import com.amplifyframework.auth.options.AuthSignUpOptions
3340
import com.amplifyframework.auth.result.AuthResetPasswordResult
3441
import com.amplifyframework.auth.result.AuthSignInResult
3542
import com.amplifyframework.auth.result.AuthSignOutResult
3643
import com.amplifyframework.auth.result.AuthSignUpResult
44+
import com.amplifyframework.auth.result.AuthWebAuthnCredential
3745
import com.amplifyframework.core.Amplify
3846
import com.amplifyframework.hub.HubChannel
3947
import com.amplifyframework.hub.HubEvent
@@ -81,6 +89,10 @@ internal interface AuthProvider {
8189

8290
suspend fun fetchAuthSession(): AmplifyResult<AuthSession>
8391

92+
suspend fun createPasskey(activity: Activity): AmplifyResult<Unit>
93+
94+
suspend fun getPasskeys(): AmplifyResult<List<AuthWebAuthnCredential>>
95+
8496
suspend fun fetchUserAttributes(): AmplifyResult<List<AuthUserAttribute>>
8597

8698
suspend fun confirmUserAttribute(key: AuthUserAttributeKey, confirmationCode: String): AmplifyResult<Unit>
@@ -89,6 +101,8 @@ internal interface AuthProvider {
89101

90102
suspend fun getCurrentUser(): AmplifyResult<AuthUser>
91103

104+
suspend fun getAvailableAuthFactors(): AmplifyResult<List<AuthFactorType>>
105+
92106
fun authStatusEvents(): Flow<HubEvent<*>>
93107

94108
suspend fun getConfiguration(): AuthConfigurationResult
@@ -197,6 +211,21 @@ internal class RealAuthProvider : AuthProvider {
197211
)
198212
}
199213

214+
override suspend fun createPasskey(activity: Activity) = suspendCoroutine { continuation ->
215+
Amplify.Auth.associateWebAuthnCredential(
216+
activity,
217+
{ continuation.resume(AmplifyResult.Success(Unit)) },
218+
{ continuation.resume(AmplifyResult.Error(it)) }
219+
)
220+
}
221+
222+
override suspend fun getPasskeys(): AmplifyResult<List<AuthWebAuthnCredential>> = suspendCoroutine { continuation ->
223+
Amplify.Auth.listWebAuthnCredentials(
224+
{ continuation.resume(AmplifyResult.Success(it.credentials)) },
225+
{ continuation.resume(AmplifyResult.Error(it)) }
226+
)
227+
}
228+
200229
override suspend fun fetchUserAttributes() = suspendCoroutine { continuation ->
201230
Amplify.Auth.fetchUserAttributes(
202231
{ continuation.resume(AmplifyResult.Success(it)) },
@@ -230,6 +259,42 @@ internal class RealAuthProvider : AuthProvider {
230259
)
231260
}
232261

262+
override suspend fun getAvailableAuthFactors(): AmplifyResult<List<AuthFactorType>> {
263+
// Get the identity provider client from Amplify
264+
val client = getCognitoPlugin()?.escapeHatch?.cognitoIdentityProviderClient ?: return AmplifyResult.Error(
265+
InvalidUserPoolConfigurationException()
266+
)
267+
268+
// Get the user's access token
269+
val token = when (val authSession = fetchAuthSession()) {
270+
is AmplifyResult.Error -> return authSession
271+
is AmplifyResult.Success -> {
272+
val cognitoSession = authSession.data as AWSCognitoAuthSession
273+
cognitoSession.accessToken
274+
}
275+
}
276+
277+
// Fetch the list of auth factors
278+
val response = try {
279+
client.getUserAuthFactors { accessToken = token }
280+
} catch (e: Exception) {
281+
return AmplifyResult.Error(UnknownException("Could not fetch auth factors", e))
282+
}
283+
284+
// Map the factors to Amplify types
285+
val factors = response.configuredUserAuthFactors?.mapNotNull { factor ->
286+
when (factor) {
287+
KotlinAuthFactorType.EmailOtp -> AuthFactorType.EMAIL_OTP
288+
KotlinAuthFactorType.Password -> AuthFactorType.PASSWORD
289+
KotlinAuthFactorType.SmsOtp -> AuthFactorType.SMS_OTP
290+
KotlinAuthFactorType.WebAuthn -> AuthFactorType.WEB_AUTHN
291+
else -> null
292+
}
293+
} ?: emptyList()
294+
295+
return AmplifyResult.Success(factors)
296+
}
297+
233298
override fun authStatusEvents(): Flow<HubEvent<*>> = callbackFlow {
234299
val filter = HubEventFilter {
235300
it.name == AuthChannelEventName.SIGNED_OUT.name || it.name == AuthChannelEventName.SIGNED_IN.name

0 commit comments

Comments
 (0)