From e0fca26712e5973ba17dcf07745c21d42e5ccd6d Mon Sep 17 00:00:00 2001 From: Matt Creaser Date: Mon, 18 Mar 2024 14:24:25 -0300 Subject: [PATCH] Expose AuthConfiguration directly --- .../auth/cognito/AWSCognitoAuthPlugin.kt | 4 + .../auth/cognito/RealAWSCognitoAuthPlugin.kt | 2 +- .../codegen/data/AuthConfiguration.kt | 73 ++++++++++++++++++- .../codegen/data/IdentityPoolConfiguration.kt | 21 ++++-- .../codegen/data/OauthConfiguration.kt | 6 +- .../codegen/data/UserPoolConfiguration.kt | 34 ++++++--- 6 files changed, 113 insertions(+), 27 deletions(-) diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthPlugin.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthPlugin.kt index 6e5ad9173c..8f8f479b93 100644 --- a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthPlugin.kt +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthPlugin.kt @@ -100,10 +100,14 @@ class AWSCognitoAuthPlugin : AuthPlugin() { private lateinit var pluginConfigurationJSON: JSONObject @InternalAmplifyApi + @Deprecated("Use getAuthConfiguration instead", replaceWith = ReplaceWith("getAuthConfiguration()")) fun getPluginConfiguration(): JSONObject { return pluginConfigurationJSON } + @InternalAmplifyApi + fun getAuthConfiguration() = realPlugin.configuration + @InternalAmplifyApi fun addToUserAgent(type: AWSCognitoAuthMetadataType, value: String) { realPlugin.addToUserAgent(type, value) diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt index 90a1ce6043..1d6770da2c 100644 --- a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt @@ -173,7 +173,7 @@ import kotlinx.coroutines.async import kotlinx.coroutines.launch internal class RealAWSCognitoAuthPlugin( - private val configuration: AuthConfiguration, + val configuration: AuthConfiguration, private val authEnvironment: AuthEnvironment, private val authStateMachine: AuthStateMachine, private val logger: Logger diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/AuthConfiguration.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/AuthConfiguration.kt index e354ef05e7..17e3571190 100644 --- a/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/AuthConfiguration.kt +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/AuthConfiguration.kt @@ -15,28 +15,70 @@ package com.amplifyframework.statemachine.codegen.data +import androidx.annotation.IntRange +import com.amplifyframework.annotations.InternalAmplifyApi +import com.amplifyframework.auth.AuthUserAttributeKey import com.amplifyframework.auth.cognito.options.AuthFlowType +import org.json.JSONArray import org.json.JSONObject +private const val configName = "Default" + +@InternalAmplifyApi +enum class VerificationMechanism { + PhoneNumber, Email +} + +@InternalAmplifyApi +data class PasswordProtectionSettings( + @IntRange(from = 6, to = 99) val length: Int, + val requiresNumber: Boolean, + val requiresSpecial: Boolean, + val requiresUpper: Boolean, + val requiresLower: Boolean +) + /** * Configuration options for [AWSCognitoAuthPlugin]. */ -internal data class AuthConfiguration internal constructor( +@InternalAmplifyApi +data class AuthConfiguration internal constructor( val userPool: UserPoolConfiguration?, val identityPool: IdentityPoolConfiguration?, val oauth: OauthConfiguration?, val authFlowType: AuthFlowType, + val signUpAttributes: List, + val usernameAttributes: List, + val verificationMechanisms: List, + val passwordProtectionSettings: PasswordProtectionSettings? ) { - companion object { + internal companion object { /** * Returns an AuthConfiguration instance from JSON * @return populated AuthConfiguration instance. */ - internal fun fromJson( + fun fromJson( pluginJson: JSONObject, configName: String = "Default" ): AuthConfiguration { + val authConfig = pluginJson.optJSONObject("Auth")?.optJSONObject(configName) + + val signUpAttributes = authConfig?.optJSONArray("signupAttributes")?.map { + AuthUserAttributeKey.custom(getString(it).lowercase()) + } ?: emptyList() + + val usernameAttributes = authConfig?.optJSONArray("usernameAttributes")?.map { + AuthUserAttributeKey.custom(getString(it).lowercase()) + } ?: emptyList() + + val verificationMechanisms = authConfig?.optJSONArray("verificationMechanisms")?.map { + when (getString(it)) { + "EMAIL" -> VerificationMechanism.Email + else -> VerificationMechanism.PhoneNumber + } + } ?: emptyList() + return AuthConfiguration( userPool = pluginJson.optJSONObject("CognitoUserPool")?.getJSONObject(configName)?.let { UserPoolConfiguration.fromJson(it).build() @@ -55,7 +97,11 @@ internal data class AuthConfiguration internal constructor( pluginJson.optJSONObject("Auth") ?.optJSONObject(configName) ?.optString("authenticationFlowType") - ) + ), + signUpAttributes = signUpAttributes, + usernameAttributes = usernameAttributes, + verificationMechanisms = verificationMechanisms, + passwordProtectionSettings = getPasswordProtectionSettings(authConfig) ) } private fun getAuthenticationFlowType(authType: String?): AuthFlowType { @@ -64,5 +110,24 @@ internal data class AuthConfiguration internal constructor( else AuthFlowType.USER_SRP_AUTH } + + private fun getPasswordProtectionSettings(authConfig: JSONObject?): PasswordProtectionSettings? { + val passwordSettings = authConfig?.optJSONObject("passwordProtectionSettings") ?: return null + val passwordLength = passwordSettings.optInt("passwordPolicyMinLength") + val passwordRequirements = passwordSettings.optJSONArray("passwordPolicyCharacters")?.map { + getString(it) + } ?: emptyList() + return PasswordProtectionSettings( + length = passwordLength, + requiresNumber = passwordRequirements.contains("REQUIRES_NUMBERS"), + requiresSpecial = passwordRequirements.contains("REQUIRES_SYMBOLS"), + requiresLower = passwordRequirements.contains("REQUIRES_LOWER"), + requiresUpper = passwordRequirements.contains("REQUIRES_UPPER") + ) + } + + private inline fun JSONArray.map(func: JSONArray.(Int) -> T) = List(length()) { + func(it) + } } } diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/IdentityPoolConfiguration.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/IdentityPoolConfiguration.kt index f89fbd2b2a..0a48f6dee6 100644 --- a/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/IdentityPoolConfiguration.kt +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/IdentityPoolConfiguration.kt @@ -15,16 +15,18 @@ package com.amplifyframework.statemachine.codegen.data +import com.amplifyframework.annotations.InternalAmplifyApi import org.json.JSONObject /** * Configuration options for specifying cognito identity pool. */ -internal data class IdentityPoolConfiguration internal constructor(val builder: Builder) { - val region: String? = builder.region - val poolId: String? = builder.poolId - - companion object { +@InternalAmplifyApi +data class IdentityPoolConfiguration internal constructor( + val region: String?, + val poolId: String? +) { + internal companion object { private const val DEFAULT_REGION = "us-east-1" /** @@ -40,7 +42,7 @@ internal data class IdentityPoolConfiguration internal constructor(val builder: * Returns a builder object populated from JSON. * @return populated builder instance. */ - internal fun fromJson(configJson: JSONObject): Builder { + fun fromJson(configJson: JSONObject): Builder { return Builder(configJson) } @@ -50,7 +52,7 @@ internal data class IdentityPoolConfiguration internal constructor(val builder: /** * Builder class for constructing [IdentityPoolConfiguration]. */ - class Builder constructor( + internal class Builder( configJson: JSONObject? = null ) { var region: String? = DEFAULT_REGION @@ -65,7 +67,10 @@ internal data class IdentityPoolConfiguration internal constructor(val builder: fun region(region: String) = apply { this.region = region } fun poolId(poolId: String) = apply { this.poolId = poolId } - fun build() = IdentityPoolConfiguration(this) + fun build() = IdentityPoolConfiguration( + region = region, + poolId = poolId + ) } private enum class Config(val key: String) { diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/OauthConfiguration.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/OauthConfiguration.kt index 7f403e86f8..0372be1e04 100644 --- a/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/OauthConfiguration.kt +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/OauthConfiguration.kt @@ -15,9 +15,11 @@ package com.amplifyframework.statemachine.codegen.data +import com.amplifyframework.annotations.InternalAmplifyApi import org.json.JSONObject -internal data class OauthConfiguration internal constructor( +@InternalAmplifyApi +data class OauthConfiguration internal constructor( val appClient: String, val appSecret: String?, val domain: String, @@ -25,7 +27,7 @@ internal data class OauthConfiguration internal constructor( val signInRedirectURI: String, val signOutRedirectURI: String ) { - companion object { + internal companion object { fun fromJson(jsonObject: JSONObject?): OauthConfiguration? { return jsonObject?.run { diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/UserPoolConfiguration.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/UserPoolConfiguration.kt index 9aff9df7a8..6d2fa8a131 100644 --- a/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/UserPoolConfiguration.kt +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/statemachine/codegen/data/UserPoolConfiguration.kt @@ -15,21 +15,24 @@ package com.amplifyframework.statemachine.codegen.data +import com.amplifyframework.annotations.InternalAmplifyApi import com.amplifyframework.auth.AuthException import org.json.JSONObject /** * Configuration options for specifying cognito user pool. */ -internal data class UserPoolConfiguration internal constructor(val builder: Builder) { - val region: String? = builder.region - val endpoint: String? = builder.endpoint - val poolId: String? = builder.poolId - val appClient: String? = builder.appClientId - val appClientSecret: String? = builder.appClientSecret - val pinpointAppId: String? = builder.pinpointAppId - - companion object { +@InternalAmplifyApi +data class UserPoolConfiguration internal constructor( + val region: String?, + val endpoint: String?, + val poolId: String?, + val appClient: String?, + val appClientSecret: String?, + val pinpointAppId: String? +) { + + internal companion object { private const val DEFAULT_REGION = "us-east-1" /** @@ -45,7 +48,7 @@ internal data class UserPoolConfiguration internal constructor(val builder: Buil * Returns a builder object populated from JSON. * @return populated builder instance. */ - internal fun fromJson(configJson: JSONObject): Builder { + fun fromJson(configJson: JSONObject): Builder { return Builder(configJson) } @@ -55,7 +58,7 @@ internal data class UserPoolConfiguration internal constructor(val builder: Buil /** * Builder class for constructing [UserPoolConfiguration]. */ - class Builder constructor( + internal class Builder constructor( configJson: JSONObject? = null ) { var region: String? = DEFAULT_REGION @@ -82,7 +85,14 @@ internal data class UserPoolConfiguration internal constructor(val builder: Buil fun appClientId(appClientId: String) = apply { this.appClientId = appClientId } fun appClientSecret(appClientSecret: String) = apply { this.appClientSecret = appClientSecret } fun pinpointAppId(pinpointAppId: String) = apply { this.pinpointAppId = pinpointAppId } - fun build() = UserPoolConfiguration(this) + fun build() = UserPoolConfiguration( + region = region, + endpoint = endpoint, + poolId = poolId, + appClient = appClientId, + appClientSecret = appClientSecret, + pinpointAppId = pinpointAppId + ) @Throws(AuthException::class) private fun validateEndpoint(endpoint: String?): String? {