|
| 1 | +/* |
| 2 | + * Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| 3 | + * |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"). |
| 5 | + * You may not use this file except in compliance with the License. |
| 6 | + * A copy of the License is located at |
| 7 | + * |
| 8 | + * http://aws.amazon.com/apache2.0 |
| 9 | + * |
| 10 | + * or in the "license" file accompanying this file. This file is distributed |
| 11 | + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| 12 | + * express or implied. See the License for the specific language governing |
| 13 | + * permissions and limitations under the License. |
| 14 | + */ |
| 15 | + |
| 16 | +package com.amplifyframework.auth.cognito |
| 17 | + |
| 18 | +import androidx.annotation.IntRange |
| 19 | +import com.amplifyframework.annotations.InternalAmplifyApi |
| 20 | +import com.amplifyframework.auth.AuthUserAttributeKey |
| 21 | +import com.amplifyframework.auth.cognito.options.AuthFlowType |
| 22 | +import com.amplifyframework.statemachine.codegen.data.IdentityPoolConfiguration |
| 23 | +import com.amplifyframework.statemachine.codegen.data.OauthConfiguration |
| 24 | +import com.amplifyframework.statemachine.codegen.data.UserPoolConfiguration |
| 25 | +import org.json.JSONArray |
| 26 | +import org.json.JSONObject |
| 27 | + |
| 28 | +@InternalAmplifyApi |
| 29 | +enum class UsernameAttribute { |
| 30 | + Username, |
| 31 | + Email, |
| 32 | + PhoneNumber |
| 33 | +} |
| 34 | + |
| 35 | +@InternalAmplifyApi |
| 36 | +enum class VerificationMechanism { |
| 37 | + Email, |
| 38 | + PhoneNumber |
| 39 | +} |
| 40 | + |
| 41 | +@InternalAmplifyApi |
| 42 | +data class PasswordProtectionSettings( |
| 43 | + @IntRange(from = 6, to = 99) val length: Int, |
| 44 | + val requiresNumber: Boolean, |
| 45 | + val requiresSpecial: Boolean, |
| 46 | + val requiresUpper: Boolean, |
| 47 | + val requiresLower: Boolean |
| 48 | +) |
| 49 | + |
| 50 | +/** |
| 51 | + * Configuration options for [AWSCognitoAuthPlugin]. |
| 52 | + */ |
| 53 | +@InternalAmplifyApi |
| 54 | +data class AuthConfiguration internal constructor( |
| 55 | + val userPool: UserPoolConfiguration?, |
| 56 | + val identityPool: IdentityPoolConfiguration?, |
| 57 | + val oauth: OauthConfiguration?, |
| 58 | + val authFlowType: AuthFlowType, |
| 59 | + val signUpAttributes: List<AuthUserAttributeKey>, |
| 60 | + val usernameAttributes: List<UsernameAttribute>, |
| 61 | + val verificationMechanisms: List<VerificationMechanism>, |
| 62 | + val passwordProtectionSettings: PasswordProtectionSettings? |
| 63 | +) { |
| 64 | + |
| 65 | + internal companion object { |
| 66 | + /** |
| 67 | + * Returns an AuthConfiguration instance from JSON |
| 68 | + * @return populated AuthConfiguration instance. |
| 69 | + */ |
| 70 | + fun fromJson( |
| 71 | + pluginJson: JSONObject, |
| 72 | + configName: String = "Default" |
| 73 | + ): AuthConfiguration { |
| 74 | + val authConfig = pluginJson.optJSONObject("Auth")?.optJSONObject(configName) |
| 75 | + |
| 76 | + val signUpAttributes = authConfig?.optJSONArray("signupAttributes")?.map { |
| 77 | + AuthUserAttributeKey.custom(getString(it).lowercase()) |
| 78 | + } ?: emptyList() |
| 79 | + |
| 80 | + val usernameAttributes = authConfig?.optJSONArray("usernameAttributes")?.map { |
| 81 | + when (getString(it)) { |
| 82 | + "EMAIL" -> UsernameAttribute.Email |
| 83 | + "PHONE_NUMBER" -> UsernameAttribute.PhoneNumber |
| 84 | + else -> UsernameAttribute.Username |
| 85 | + } |
| 86 | + } ?: emptyList() |
| 87 | + |
| 88 | + val verificationMechanisms = authConfig?.optJSONArray("verificationMechanisms")?.map { |
| 89 | + when (getString(it)) { |
| 90 | + "EMAIL" -> VerificationMechanism.Email |
| 91 | + else -> VerificationMechanism.PhoneNumber |
| 92 | + } |
| 93 | + } ?: emptyList() |
| 94 | + |
| 95 | + return AuthConfiguration( |
| 96 | + userPool = pluginJson.optJSONObject("CognitoUserPool")?.getJSONObject(configName)?.let { |
| 97 | + UserPoolConfiguration.fromJson(it).build() |
| 98 | + }, |
| 99 | + identityPool = pluginJson.optJSONObject("CredentialsProvider") |
| 100 | + ?.getJSONObject("CognitoIdentity") |
| 101 | + ?.getJSONObject(configName)?.let { |
| 102 | + IdentityPoolConfiguration.fromJson(it).build() |
| 103 | + }, |
| 104 | + oauth = authConfig?.optJSONObject("OAuth")?.let { OauthConfiguration.fromJson(it) }, |
| 105 | + authFlowType = getAuthenticationFlowType(authConfig?.optString("authenticationFlowType")), |
| 106 | + signUpAttributes = signUpAttributes, |
| 107 | + usernameAttributes = usernameAttributes, |
| 108 | + verificationMechanisms = verificationMechanisms, |
| 109 | + passwordProtectionSettings = getPasswordProtectionSettings(authConfig) |
| 110 | + ) |
| 111 | + } |
| 112 | + private fun getAuthenticationFlowType(authType: String?): AuthFlowType { |
| 113 | + return if (!authType.isNullOrEmpty() && AuthFlowType.values().any { it.name == authType }) { |
| 114 | + AuthFlowType.valueOf(authType) |
| 115 | + } else { |
| 116 | + AuthFlowType.USER_SRP_AUTH |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + private fun getPasswordProtectionSettings(authConfig: JSONObject?): PasswordProtectionSettings? { |
| 121 | + val passwordSettings = authConfig?.optJSONObject("passwordProtectionSettings") ?: return null |
| 122 | + val passwordLength = passwordSettings.optInt("passwordPolicyMinLength") |
| 123 | + val passwordRequirements = passwordSettings.optJSONArray("passwordPolicyCharacters")?.map { |
| 124 | + getString(it) |
| 125 | + } ?: emptyList() |
| 126 | + return PasswordProtectionSettings( |
| 127 | + length = passwordLength, |
| 128 | + requiresNumber = passwordRequirements.contains("REQUIRES_NUMBERS"), |
| 129 | + requiresSpecial = passwordRequirements.contains("REQUIRES_SYMBOLS"), |
| 130 | + requiresLower = passwordRequirements.contains("REQUIRES_LOWER"), |
| 131 | + requiresUpper = passwordRequirements.contains("REQUIRES_UPPER") |
| 132 | + ) |
| 133 | + } |
| 134 | + |
| 135 | + private inline fun <T> JSONArray.map(func: JSONArray.(Int) -> T) = List(length()) { |
| 136 | + func(it) |
| 137 | + } |
| 138 | + } |
| 139 | +} |
0 commit comments