amazon-web-servicesrustaws-lambdaamazon-cognitoaws-identitypools

Identity '[]' not found when calling get_credentials_for_identity AWS identity pool endpoint


Hi :) hope you're doing great.

I am trying to retrieve an STS token using an unauthenticated user that tries to retrieve the token from an Identity Pool by calling the get_credentials_for_identity endpoint. Here is m code:

let unauth_credentials = aws_config::defaults(aws_config::BehaviorVersion::latest())
        .region("eu-central-1")
        .no_credentials()
        .load().await;

        let identity_client = aws_sdk_cognitoidentity::Client::new(&unauth_credentials);

        let cred_res = identity_client
        .get_credentials_for_identity()
        .identity_id("eu-central-1:b1c4f066-8cfe-44ae-9809-a938905a45fc")
        .logins("cognito-idp.eu-central-1.amazonaws.com/eu-central-1_vexpZDVTF", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c")
        .send()
        .await;

        match cred_res {
            Ok(credentials) => {
                if let Some(cred) = credentials.credentials {
                    // s3_config.() = c;
                    std::env::set_var("AWS_ACCESS_KEY_ID", cred.access_key_id.unwrap_or("".to_string()));
                    std::env::set_var("AWS_SECRET_ACCESS_KEY", cred.secret_key.unwrap_or("".to_string()));
                };
                eprintln!("no credentials returned by identity pool");
            },
            Err(err) => {
                err.map_service_error(|err| {
                    match err {
                        aws_sdk_cognitoidentity::operation::get_credentials_for_identity::GetCredentialsForIdentityError::ExternalServiceException(err) => eprintln!("error retriveing identity pool credentials: {}", err),
                        aws_sdk_cognitoidentity::operation::get_credentials_for_identity::GetCredentialsForIdentityError::InternalErrorException(err) => eprintln!("error retriveing identity pool credentials: {}", err),
                        aws_sdk_cognitoidentity::operation::get_credentials_for_identity::GetCredentialsForIdentityError::InvalidIdentityPoolConfigurationException(err) => eprintln!("error retriveing identity pool credentials: {}", err),
                        aws_sdk_cognitoidentity::operation::get_credentials_for_identity::GetCredentialsForIdentityError::InvalidParameterException(err) => eprintln!("error retriveing identity pool credentials: {}", err),
                        aws_sdk_cognitoidentity::operation::get_credentials_for_identity::GetCredentialsForIdentityError::NotAuthorizedException(err) => eprintln!("error retriveing identity pool credentials: {}", err),
                        aws_sdk_cognitoidentity::operation::get_credentials_for_identity::GetCredentialsForIdentityError::ResourceConflictException(err) => eprintln!("error retriveing identity pool credentials: {}", err),
                        aws_sdk_cognitoidentity::operation::get_credentials_for_identity::GetCredentialsForIdentityError::ResourceNotFoundException(err) => eprintln!("error retriveing identity pool credentials: {}", err),
                        aws_sdk_cognitoidentity::operation::get_credentials_for_identity::GetCredentialsForIdentityError::TooManyRequestsException(err) => eprintln!("error retriveing identity pool credentials: {}", err),
                        aws_sdk_cognitoidentity::operation::get_credentials_for_identity::GetCredentialsForIdentityError::Unhandled(_) => eprintln!("error retriveing identity pool credentials: Unhandled"),
                        err => eprintln!("error retriveing identity pool credentials: {}", err),
                    }
                });
            }
        }

        // Instantiate the client SFTER the ENV vaiables have been RESET
        let config = aws_config::load_from_env().await;
        let s3_client = aws_sdk_s3::Client::new(&config);
        json_bytes = get_object(s3_client, "etisreal-cognito-bucket", req_obj).await.unwrap();

I've tried it ALL. I tried making the call setting up the aws_config using the load_from_env function and also as you can see with no credentials set, kind of inline with this issue I saw.

I also tried adding these role to my lambda function (where this code is getting executed), in accordance with this stackoverflow question.

Still nothing.

The 'identity_id' is my Identity Pool ID and I double, triple checked it, copying and pasting directly form the AWS console so that is 100% correct.

Same for the 'logins' identity, the region is correct as well as the cognito pool id, although since I set up unauthenticated user access it shouldn't be necessary right?

But anyway, I'd just love to make this work and would really appreciate if anyone could unveil to me what the hell am I missing :/

Thank you very much in advance and have a nice day


Solution

  • Ok, got it figured it out. Will post here so that hopefully it saves someone else an heart attack.

    Here is the thing, you first need to call the get_id function to get either an anonymous (if enabled) or authenticated identityId

    if let Some(token) = jwt_token {
                identity_id = match identity_client
                .get_id()
                .identity_pool_id("REGION:GUID")
                .logins("cognito-idp.<region>.amazonaws.com/ID", token)
                .send()
                .await {
                    Ok(id) => id.identity_id.unwrap_or(String::from("REGION:GUID")),
                    Err(err) => {
                        eprintln!("error getting id: {}", err.meta());
                        String::from("REGION:GUID")
                    },
                };
            } else {
                identity_id = match identity_client
                .get_id()
                .identity_pool_id("REGION:GUID")
                .send()
                .await {
                    Ok(id) => id.identity_id.unwrap_or(String::from("REGION:GUID")),
                    Err(err) => {
                        eprintln!("error getting id: {}", err.meta());
                        String::from("REGION:GUID")
                    },
                };
            }
    

    then you ask for the credentials based on the identity you retrieved (again, anonymous or authenticated) for a given IdentityPool - CognitoPool combo wombo.

    The call to retrieve the credentials will look something like this:

    let cred_res = identity_client
            .get_credentials_for_identity()
            .identity_id(identity_id)
            .send()
            .await;
    
            match cred_res {
                Ok(credentials) => {
                    if let Some(cred) = credentials.credentials {
                        std::env::set_var("AWS_ACCESS_KEY_ID", cred.access_key_id().unwrap_or(""));
                        std::env::set_var("AWS_SECRET_ACCESS_KEY", cred.secret_key().unwrap_or(""));
                        std::env::set_var("AWS_SESSION_TOKEN", cred.session_token().unwrap_or(""));
                    } else {
                        eprintln!("no credentials returned by identity pool");
                    }
                },
       ...
    
    

    Cheers :)