Skip to content
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

feat(Auth): provide AuthConfiguration from plugin #3566

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ public final class AWSCognitoAuthPlugin: AWSCognitoAuthPluginBehavior {
var queue: OperationQueue!

/// Configuration for the auth plugin
var authConfiguration: AuthConfiguration!
@_spi(InternalAmplifyConfiguration)
internal(set) public var authConfiguration: AuthConfiguration!

/// Handles different auth event send through hub
var hubEventHandler: AuthHubEventBehavior!
Expand All @@ -35,6 +36,7 @@ public final class AWSCognitoAuthPlugin: AWSCognitoAuthPluginBehavior {
/// The user network preferences for timeout and retry
let networkPreferences: AWSCognitoNetworkPreferences?

@available(*, deprecated, message: "Use `authConfiguration`")
@_spi(InternalAmplifyConfiguration)
internal(set) public var jsonConfiguration: JSONValue?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

import Foundation

enum AuthConfiguration {
@_spi(InternalAmplifyConfiguration)
public enum AuthConfiguration {
case userPools(UserPoolConfigurationData)
case identityPools(IdentityPoolConfigurationData)
case userPoolsAndIdentityPools(UserPoolConfigurationData, IdentityPoolConfigurationData)
Expand All @@ -21,7 +22,7 @@ extension AuthConfiguration: Codable {
case identityPools
}

func encode(to encoder: Encoder) throws {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

switch self {
Expand All @@ -35,7 +36,7 @@ extension AuthConfiguration: Codable {
}
}

init(from decoder: Decoder) throws {
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)

let userConfigData = try? values.decode(UserPoolConfigurationData.self, forKey: .userPools)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

struct IdentityPoolConfigurationData: Equatable {
lawmicha marked this conversation as resolved.
Show resolved Hide resolved
public struct IdentityPoolConfigurationData: Equatable {
let poolId: String
let region: String

Expand All @@ -25,7 +25,7 @@ extension IdentityPoolConfigurationData: CustomDebugDictionaryConvertible {
}

extension IdentityPoolConfigurationData: CustomDebugStringConvertible {
var debugDescription: String {
public var debugDescription: String {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing @spi

Suggested change
public var debugDescription: String {
@_spi(InternalAmplifyConfiguration)
public var debugDescription: String {

debugDictionary.debugDescription
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation
import Amplify

@_spi(InternalAmplifyConfiguration)
public struct PasswordProtectionSettings: Equatable, Codable {
public var minLength: Int?
lawmicha marked this conversation as resolved.
Show resolved Hide resolved
public var characterPolicy: [PasswordCharacterPolicy]

public init(minLength: Int?,
characterPolicy: [PasswordCharacterPolicy]) {
self.minLength = minLength
self.characterPolicy = characterPolicy
}
}

@_spi(InternalAmplifyConfiguration)
public enum PasswordCharacterPolicy: String, Codable {
case lowercase = "REQUIRES_LOWERCASE"
case uppercase = "REQUIRES_UPPERCASE"
case numbers = "REQUIRES_NUMBERS"
case symbols = "REQUIRES_SYMBOLS"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation

@_spi(InternalAmplifyConfiguration)
public enum SignUpAttributeType: String, Codable {
case address = "ADDRESS"
case birthDate = "BIRTHDATE"
case email = "EMAIL"
case familyName = "FAMILY_NAME"
case gender = "GENDER"
case givenName = "GIVEN_NAME"
case middleName = "MIDDLE_NAME"
case name = "NAME"
case nickname = "NICKNAME"
case phoneNumber = "PHONE_NUMBER"
case preferredUsername = "PREFERRED_USERNAME"
case profile = "PROFILE"
case website = "WEBSITE"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation
import Amplify

@_spi(InternalAmplifyConfiguration)
public enum UsernameAttribute: String, Codable {
case username = "USERNAME"
case email = "EMAIL"
case phoneNumber = "PHONE_NUMBER"

public init?(from authUserAttributeKey: AuthUserAttributeKey) {
switch authUserAttributeKey {
case .email:
self = .email
case .phoneNumber:
self = .phoneNumber
default:
return nil
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

import ClientRuntime

struct UserPoolConfigurationData: Equatable {
@_spi(InternalAmplifyConfiguration)
public struct UserPoolConfigurationData: Equatable {

let poolId: String
let clientId: String
Expand All @@ -17,6 +18,14 @@ struct UserPoolConfigurationData: Equatable {
let pinpointAppId: String?
let hostedUIConfig: HostedUIConfigurationData?
let authFlowType: AuthFlowType
@_spi(InternalAmplifyConfiguration)
public let passwordProtectionSettings: PasswordProtectionSettings?
@_spi(InternalAmplifyConfiguration)
public let usernameAttributes: [UsernameAttribute]
@_spi(InternalAmplifyConfiguration)
public let signUpAttributes: [SignUpAttributeType]
@_spi(InternalAmplifyConfiguration)
public let verificationMechanisms: [VerificationMechanism]

init(
poolId: String,
Expand All @@ -26,7 +35,11 @@ struct UserPoolConfigurationData: Equatable {
clientSecret: String? = nil,
pinpointAppId: String? = nil,
authFlowType: AuthFlowType = .userSRP,
hostedUIConfig: HostedUIConfigurationData? = nil
hostedUIConfig: HostedUIConfigurationData? = nil,
passwordProtectionSettings: PasswordProtectionSettings? = nil,
usernameAttributes: [UsernameAttribute] = [],
signUpAttributes: [SignUpAttributeType] = [],
verificationMechanisms: [VerificationMechanism] = []
) {
self.poolId = poolId
self.clientId = clientId
Expand All @@ -36,6 +49,10 @@ struct UserPoolConfigurationData: Equatable {
self.pinpointAppId = pinpointAppId
self.hostedUIConfig = hostedUIConfig
self.authFlowType = authFlowType
self.passwordProtectionSettings = passwordProtectionSettings
self.usernameAttributes = usernameAttributes
self.signUpAttributes = signUpAttributes
self.verificationMechanisms = verificationMechanisms
}

/// Amazon Cognito user pool: cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>,
Expand All @@ -62,7 +79,8 @@ extension UserPoolConfigurationData: CustomDebugDictionaryConvertible {
}

extension UserPoolConfigurationData: CustomDebugStringConvertible {
var debugDescription: String {
@_spi(InternalAmplifyConfiguration)
public var debugDescription: String {
debugDictionary.debugDescription
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation

@_spi(InternalAmplifyConfiguration)
public enum VerificationMechanism: String, Codable {
case email = "EMAIL"
case phoneNumber = "PHONE_NUMBER"
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct ConfigurationHelper {
return nil
}

// parse `pinpointId`
var pinpointId: String?
if case .string(let pinpointIdFromConfig) = cognitoUserPoolJSON.value(at: "PinpointAppId") {
pinpointId = pinpointIdFromConfig
Expand All @@ -44,6 +45,7 @@ struct ConfigurationHelper {
return nil
}()

// parse `authFlowType`
var authFlowType: AuthFlowType
if case .boolean(let isMigrationEnabled) = cognitoUserPoolJSON.value(at: "MigrationEnabled"),
isMigrationEnabled == true {
Expand All @@ -56,22 +58,97 @@ struct ConfigurationHelper {
authFlowType = .userSRP
}

// parse `clientSecret`
var clientSecret: String?
if case .string(let clientSecretFromConfig) = cognitoUserPoolJSON.value(at: "AppClientSecret") {
clientSecret = clientSecretFromConfig
}

// parse `hostedUIConfig`
let hostedUIConfig = parseHostedConfiguration(
configuration: config.value(at: "Auth.Default.OAuth"))

// parse `passwordProtectionSettings`
let cognitoConfiguration = config.value(at: "Auth.Default")
var passwordProtectionSettings: PasswordProtectionSettings?
if case .object(let passwordSettings) = cognitoConfiguration?.value(at: "passwordProtectionSettings") {

// parse `minLength`
var minLength: Int?
if case .number(let value) = passwordSettings["passwordPolicyMinLength"] {
minLength = Int(value)
} else if case .string(let value) = passwordSettings["passwordPolicyMinLength"],
let intValue = Int(value) {
minLength = intValue
}

// parse `characterPolicy`
var characterPolicy: [PasswordCharacterPolicy] = []
if case .array(let characters) = passwordSettings["passwordPolicyCharacters"] {
characterPolicy = characters.compactMap { value in
guard case .string(let string) = value else {
return nil
}

return .init(rawValue: string)
}
}

passwordProtectionSettings = PasswordProtectionSettings(
minLength: minLength,
characterPolicy: characterPolicy
)
}

// parse `usernameAttributes`
var usernameAttributes: [UsernameAttribute] = []
if case .array(let attributes) = cognitoConfiguration?["usernameAttributes"] {
usernameAttributes = attributes.compactMap { value in
guard case .string(let string) = value else {
return nil
}

return .init(rawValue: string)
}
}

// parse `signUpAttributes`
var signUpAttributes: [SignUpAttributeType] = []
if case .array(let attributes) = cognitoConfiguration?["signupAttributes"] {
signUpAttributes = attributes.compactMap { value in
guard case .string(let string) = value else {
return nil
}

return .init(rawValue: string)
}
}

// parse `verificationMechanisms`
var verificationMechanisms: [VerificationMechanism] = []
if case .array(let attributes) = cognitoConfiguration?["verificationMechanisms"] {
verificationMechanisms = attributes.compactMap { value in
guard case .string(let string) = value else {
return nil
}

return .init(rawValue: string)
}
}

return UserPoolConfigurationData(poolId: poolId,
clientId: appClientId,
region: region,
endpoint: endpoint,
clientSecret: clientSecret,
pinpointAppId: pinpointId,
authFlowType: authFlowType,
hostedUIConfig: hostedUIConfig)
hostedUIConfig: hostedUIConfig,
passwordProtectionSettings: passwordProtectionSettings,
usernameAttributes: usernameAttributes,
signUpAttributes: signUpAttributes,
verificationMechanisms: verificationMechanisms)

}

static func parseHostedConfiguration(configuration: JSONValue?) -> HostedUIConfigurationData? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import XCTest
import AWSCognitoIdentity
@testable import Amplify
@testable import AWSCognitoAuthPlugin
@_spi(InternalAmplifyConfiguration) @testable import AWSCognitoAuthPlugin
import AWSCognitoIdentityProvider
import ClientRuntime

Expand Down