You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不存储AppClientSecret的情况下实现AWS Cognito自定义登录?

How to Implement Custom Login with AWS Cognito Without Storing App Client Secret

Great question! Storing an App Client Secret in a mobile app is a critical security risk—reverse engineering tools can easily extract it, putting your user pool at risk. Let's walk through the correct approach to implement custom login without exposing this secret.

1. Use a Secret-Free App Client (Mandatory First Step)

AWS Cognito explicitly recommends creating an App Client without a secret for mobile apps. Here's how to set this up:

  • Go to your Cognito User Pool in the AWS Console.
  • Navigate to App integration > App clients and analytics.
  • Create a new App Client, and make sure the Generate client secret checkbox is unchecked.
  • Use this new App Client's ID in your code—you won't need a secret at all.

Update your initialization code to remove the client secret:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 
    let serviceConfiguration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: nil) 
    // Remove the clientSecret parameter or set it to nil
    let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(
        clientId: CognitoIdentityUserPoolAppClientId, 
        clientSecret: nil, 
        poolId: CognitoIdentityUserPoolIdCognito
    ) 
    AWSCognitoIdentityUserPool.register(
        with: serviceConfiguration, 
        userPoolConfiguration: userPoolConfiguration, 
        forKey: AWSCognitoUserPoolsSignInProviderKey
    ) 
    pool = AWSCognitoIdentityUserPool(forKey: AWSCognitoUserPoolsSignInProviderKey) 
    let credentialsProvider = AWSCognitoCredentialsProvider(
        regionType: .USEast1, 
        identityPoolId: CognitoIdentityUserFederatedId, 
        identityProviderManager: pool
    ) 
    let configuration = AWSServiceConfiguration(
        region:.USEast1, 
        credentialsProvider: credentialsProvider
    ) 
    AWSServiceManager.default().defaultServiceConfiguration = configuration 
    pool?.delegate = self 
    return true 
}

2. Implement Custom Login with Cognito's Custom Authentication Flow

If you need custom login logic (e.g., validating against your own backend, custom MFA, or non-standard credentials), use Cognito's Custom Authentication Flow powered by Lambda triggers. This keeps all sensitive validation logic on the backend, so your app never handles secrets.

Key Lambda Triggers to Configure

You'll need to set up these three Lambda functions in your Cognito User Pool (under Integrations > Lambda triggers):

  • Define Auth Challenge: Determines what challenge the user needs to complete (e.g., password verification, SMS code).
  • Create Auth Challenge: Generates the challenge (e.g., sends an SMS code to the user's phone).
  • Verify Auth Challenge Response: Checks if the user's response to the challenge is valid.

Example Custom Login Code

Here's how to initiate the custom auth flow from your iOS app:

func customLogin(username: String, password: String) {
    let authParams: [String: String] = [
        "USERNAME": username,
        "PASSWORD": password // Or any custom parameters your Lambda expects
    ]
    
    let authRequest = AWSCognitoIdentityInitiateAuthRequest()
    authRequest?.clientId = CognitoIdentityUserPoolAppClientId
    authRequest?.authFlow = .customAuth
    authRequest?.authParameters = authParams
    
    pool?.initiateAuth(authRequest!).continueWith { task in
        DispatchQueue.main.async {
            if let error = task.error {
                print("Login failed: \(error.localizedDescription)")
                // Handle error (e.g., show alert to user)
                return
            }
            
            guard let result = task.result else {
                print("No auth result returned")
                return
            }
            
            if let authResult = result.authenticationResult {
                // Login successful! Use the tokens
                print("Access Token: \(authResult.accessToken!)")
                print("ID Token: \(authResult.idToken!)")
                // Proceed to navigate to your app's main screen
            } else if let challengeName = result.challengeName {
                // Handle the challenge (e.g., prompt user for SMS code)
                switch challengeName {
                case .smsMfa:
                    // Prompt user to enter SMS code, then respond to the challenge
                    self.respondToSMSChallenge(session: result.session!, username: username)
                case .passwordVerifier:
                    // Handle password verification challenge (if needed)
                    break
                default:
                    print("Unknown challenge: \(challengeName.rawValue)")
                }
            }
        }
        return nil
    }
}

// Example: Respond to SMS MFA challenge
func respondToSMSChallenge(session: String, username: String, smsCode: String) {
    let challengeResponse: [String: String] = [
        "USERNAME": username,
        "SMS_MFA_CODE": smsCode
    ]
    
    let responseRequest = AWSCognitoIdentityRespondToAuthChallengeRequest()
    responseRequest?.clientId = CognitoIdentityUserPoolAppClientId
    responseRequest?.challengeName = .smsMfa
    responseRequest?.session = session
    responseRequest?.challengeResponses = challengeResponse
    
    pool?.respondToAuthChallenge(responseRequest!).continueWith { task in
        DispatchQueue.main.async {
            if let error = task.error {
                print("Challenge response failed: \(error.localizedDescription)")
                return
            }
            
            guard let result = task.result else {
                print("No challenge result returned")
                return
            }
            
            if let authResult = result.authenticationResult {
                // Challenge passed, login successful
                print("Access Token: \(authResult.accessToken!)")
            }
        }
        return nil
    }
}

3. Critical Security Notes

  • Never hardcode secrets: Even with a secret-free App Client, avoid hardcoding sensitive values like User Pool ID or Identity Pool ID if possible—use environment variables or secure configuration management.
  • Validate Lambda inputs: Ensure your Lambda triggers validate all incoming parameters to prevent injection attacks.
  • Use HTTPS exclusively: All communication between your app and Cognito/Lambda must use HTTPS to prevent man-in-the-middle attacks.

内容的提问来源于stack exchange,提问作者Rekd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:22:55