amplify-swift icon indicating copy to clipboard operation
amplify-swift copied to clipboard

[iOS] Config Amplify for Multi Environments

Open AdiPomelo opened this issue 2 years ago • 14 comments

Describe the bug

Currently we are using amplify iOS SDK(1.26.1) working fine with staging environment. But we have requirement to setup preprod and prod environment.

So I am trying fetch the json amplifyconfiguration.json file based on the environment and passing amplify configuration and no error throwing during the first-time initialization.

similarly we have awsconfiguration.json file based on environment I am trying to pass JSONValue and no error throwing during the first-time initialization.

After renamed amplify and aws configuration file names then only the issue is happening , but without renaming the file how to handle for multiple environment's like stage, preprod and prod

PROBLEM But when I am trying to login facebook, google, apple sigin , email and phone number app is crashing.

Here is code:

private func initAmplify() {
    do {
#if DEBUG
        Amplify.Logging.logLevel = .verbose
#endif
        let awsCognitoAuthPlugin = AWSCognitoAuthPlugin()
        let awsConfiguration: JSONValue = getAwsJsonConfiguration(fileName: "awsconfiguration.preprod")
        try awsCognitoAuthPlugin.configure(using: awsConfiguration)
        try Amplify.add(plugin: awsCognitoAuthPlugin)
        let amplifyJsonPath = getAmplifyJsonFilePath()
        try Amplify.add(plugin: AWSCognitoAuthPlugin())
        if amplifyJsonPath != nil {
            let amplifyConfig = try AmplifyConfiguration(configurationFile: URL(fileURLWithPath: amplifyJsonPath!))
            try Amplify.configure(amplifyConfig)
        }
    } catch {
        helpers.logger?.error("Failed initializing Amplify", error: error, attributes: nil)
    }
}
func getAwsJsonConfiguration(fileName: String) -> JSONValue {
    if let path: String = Bundle.main.path(forResource: fileName, ofType: "json") {
        if let data = NSData(contentsOfFile: path) {
            if let rawString = JSON(data).rawString() {
                do {
                    let jsonValue = try JSONDecoder().decode(JSONValue.self, from: rawString.data(using: .utf8)!)
                    return jsonValue
                } catch {
                    return [:]
                }
            }
        }
    }
    return [:]
}
func getAmplifyJsonFilePath() -> URL? {
    guard let file = Bundle.main.url(forResource: "amplifyconfiguration.preprod", withExtension: ".json") else {
        return nil
    }
    return file
}
Screen Shot 2565-07-26 at 19 32 15

Steps To Reproduce

  1. Lunch iOS app
  2. Call initAmplify() didFinishLaunchingWithOptions from Appdelegate.
  3. Dynamically configure AWSCognitoAuthPlugin with JSONValue
  4. Get the Json file path from bundle and pass to Amplify configuration.

Expected behavior

It should work with all accounts(socials, email & iPhone number) when do to configure dynamically.

Amplify Framework Version

1.26.2

Amplify Categories

Auth

Dependency manager

Cocoapods

Swift version

5.0

CLI version

9.1.0

Xcode version

13.4

Relevant log output

No response

Is this a regression?

No

Regression additional context

No response

Device

Iphone 13

iOS Version

15.5

Specific to simulators

Iphone 13 Pro

Additional context

Below attached error screenshots for reference: Screen Shot 2565-07-26 at 19 43 05 Screen Shot 2565-07-26 at 19 43 09 Screen Shot 2565-07-26 at 19 43 13 Screen Shot 2565-07-26 at 19 43 22 Screen Shot 2565-07-26 at 19 43 24 Screen Shot 2565-07-26 at 19 43 27

AdiPomelo avatar Jul 26 '22 12:07 AdiPomelo

Hi @AdiPomelo, thanks for opening this issue. Dynamic configuration like you're doing here is supported and should work. Let's try to figure out what's going on here. Can you please post the contents of the four configuration files you're using? Please make sure to strip out any confidential information. Once we know what those look like, we can try to reproduce what you're experiencing. Thanks!

atierian avatar Jul 26 '22 13:07 atierian

@atierian Thank you for quick reply.

Here is amplify json file looks like.

amplifyconfiguration.json

{
    "UserAgent": "aws-amplify-cli/2.0",
    "Version": "1.0",
    "auth": {
        "plugins": {
            "awsCognitoAuthPlugin": {
                "UserAgent": "aws-amplify/cli",
                "Version": "0.1.0",
                "IdentityManager": {
                    "Default": {}
                },
                "CredentialsProvider": {
                    "CognitoIdentity": {
                        "Default": {
                            "PoolId": "XXXXXXX",
                            "Region": "ap-southeast-1"
                        }
                    }
                },
                "CognitoUserPool": {
                    "Default": {
                        "PoolId": "XXXXXXXX",
                        "AppClientId": "XXXXXXXX",
                        "Region": "ap-southeast-1"
                    }
                },
                "Auth": {
                    "Default": {
                        "OAuth": {
                            "WebDomain": "XXXXXXXXX",
                            "AppClientId": "XXXXXXXXXX",
                            "SignInRedirectURI": "XXXX://auth/login",
                            "SignOutRedirectURI": "XXXXX://auth/logout",
                            "Scopes": [
                                "phone",
                                "email",
                                "openid",
                                "profile",
                                "aws.cognito.signin.user.admin"
                            ]
                        },
                        "authenticationFlowType": "CUSTOM_AUTH"
                    }
                }
            }
        }
    }
}

awsconfiguration.json

{
    "UserAgent": "aws-amplify/cli",
    "Version": "0.1.0",
    "IdentityManager": {
        "Default": {}
    },
    "CredentialsProvider": {
        "CognitoIdentity": {
            "Default": {
                "PoolId": "XXXXXXX",
                "Region": "ap-southeast-1"
            }
        }
    },
    "CognitoUserPool": {
        "Default": {
            "PoolId": "XXXXXX",
            "AppClientId": "XXXXXXXXX",
            "Region": "ap-southeast-1"
        }
    },
    "Auth": {
        "Default": {
            "OAuth": {
                "WebDomain": "auth.pre-production.XXX.co",
                "AppClientId": "XXXXXXXXXX",
                "SignInRedirectURI": "XXXX://auth/login",
                "SignOutRedirectURI": "XXXXX://auth/logout",
                "Scopes": [
                    "phone",
                    "email",
                    "openid",
                    "profile",
                    "aws.cognito.signin.user.admin"
                ]
            },
            "authenticationFlowType": "CUSTOM_AUTH"
        }
    }
}

Below mentioned key values will be changed based on environment.

CredentialsProvider -> CognitoIdentity -> Default -> PoolId
Auth -> Default -> OAuth ->  WebDomain
Auth -> Default -> OAuth ->  AppClientId
CognitoUserPool -> PoolId
CognitoUserPool -> AppClientId

AdiPomelo avatar Jul 26 '22 13:07 AdiPomelo

Thanks for the info. We'll work on reproducing your issue and follow up here with any updates.

atierian avatar Jul 26 '22 20:07 atierian

@AdiPomelo I created an example of how to support multiple build variants previously which I have now shared here on GitHub.

Normally Amplify and the AWS SDK just have a single .json file for each one. You also would not want to include the staging and preprod configuration files in the prod build. It would reveal those endpoints in your app bundle. The sample project shows how you can use Build Schemes and Xcode configuration files to support build variants. Individual developers could even create their own named environments.

See the section on Cloud Configuration. You can create a folder for each build variant you want to support and place the .json files in those folders with the default names. Once you have this set up you can just change the selected Build Scheme in Xcode to build and run the app for the environment you want. Since you can set a unique App ID for each build you can have each app installed on a device or simulator concurrently with a different cloud configuration. And the tool linked in that repo will give you way to easily create app icons for the staging and prepared environments.

You could also set up an environment for integration testing which you run with CI/CD. Having isolated resources for this purpose would make your build automation more reliable and prevent interference with staging and preprod.

Let us know if this helps simplify your setup.

brennanMKE avatar Jul 27 '22 02:07 brennanMKE

@brennanMKE Thank you for quick replay with sample project. I will try the solution suggested by you and let you know. I am assuming it will work 100%.

Once again thank you 🙏

AdiPomelo avatar Jul 27 '22 07:07 AdiPomelo

@atierian Any update ?

AdiPomelo avatar Jul 27 '22 10:07 AdiPomelo

Your initAmplify function is making some unnecessary, and incorrect, actions that are most likely the cause behind this. If you change the function to this, does it resolve your issue?

private func initAmplify() {
    do {
        #if DEBUG
        Amplify.Logging.logLevel = .verbose
        #endif
        let awsCognitoAuthPlugin = AWSCognitoAuthPlugin()
        try Amplify.add(plugin: awsCognitoAuthPlugin)
        let amplifyJsonPath = getAmplifyJsonFilePath()
        
        if let configFilePath = amplifyJsonPath {
            let amplifyConfig = try AmplifyConfiguration(configurationFile: URL(fileURLWithPath: configFilePath))
            try Amplify.configure(amplifyConfig)
        } else {
            assertionFailure("amplifyconfiguration file couldn't be found")
        }
    } catch {
        helpers.logger?.error("Failed initializing Amplify", error: error, attributes: nil)
    }
}

atierian avatar Jul 27 '22 14:07 atierian

@atierian Thank you for reply. I don't think so it will work with the code provided by you. The code will work for amplifyconfiguration.json file and what about configuring the awsconfiguration.json using json object?

AdiPomelo avatar Jul 28 '22 10:07 AdiPomelo

You don't need to use awsconfiguration.json when configuring Amplify.

atierian avatar Jul 30 '22 21:07 atierian

Hey @AdiPomelo, just checking in. Did the snippet above resolve your issue?

atierian avatar Aug 04 '22 17:08 atierian

@atierian No.

AdiPomelo avatar Aug 05 '22 04:08 AdiPomelo

Sorry to hear that. Is the error you're experiencing the same that you outlined in the original issue?

atierian avatar Aug 05 '22 11:08 atierian

@atierian Yes

AdiPomelo avatar Aug 07 '22 13:08 AdiPomelo

Based on the information you provided and using the altered code snippet for configuring Amplify that I posted above, I am not able to reproduce the issue you're experiencing here. If you're still experiencing this issue, I suggest isolating it down to a small reproducible example that you can share so we can test it.

atierian avatar Sep 30 '22 19:09 atierian

Closing due to inactivity.

atierian avatar Oct 28 '22 19:10 atierian