aws-amplify / amplify-flutter

A declarative library with an easy-to-use interface for building Flutter applications on AWS.
https://docs.amplify.aws
Apache License 2.0
1.3k stars 239 forks source link

cognitoPlugin.federateToIdentityPool() failed with ODIC provider. #3478

Closed kyeongyeonsong closed 10 months ago

kyeongyeonsong commented 11 months ago

I got an error while registering to Cognito Identity Pool after logging in to Kakao OIDC.

final cognitoPlugin = Amplify.Auth.getPlugin(AmplifyAuthCognito.pluginKey); final result = await cognitoPlugin.federateToIdentityPool( token: token, provider: provider, );

In this case, token is the ID Token received after logging in to Kakao, and provider is passed like below. AuthProvider.oidc('kauth.kakao.com', 'https://kauth.kakao.com')

"https://kauth.kakao.com" is the exact same value with the iss value in the token.

At this time, the following Exception occurred. flutter: SessionExpiredException { "message": "The AWS credentials could not be retrieved", "recoverySuggestion": "Invoke Amplify.Auth.signIn to re-authenticate the user", "underlyingException": "NotAuthorizedException {\n message=Invalid login token. Issuer doesn't match providerName,\n}" }

I configured the Cognito Identity Pool as follows. Identity provider: kauth.kakao.com Identity provider type: OpenID Connect (OIDC)

dnys1 commented 11 months ago

Hi @kyeongyeonsong sorry you are facing this issue.

Can you confirm you have followed the steps here for adding the OIDC provider to your identity pool? Can you also review the all of the bullets under the Validating an OpenID Connect token section and see if any apply here?

kyeongyeonsong commented 11 months ago

Hi @kyeongyeonsong sorry you are facing this issue.

Can you confirm you have followed the steps here for adding the OIDC provider to your identity pool? Can you also review the all of the bullets under the Validating an OpenID Connect token section and see if any apply here?

Yes, I have checked iss value is the same as logins map, and also validated signature using the following code. const keyRes = await axios.get('https://kauth.kakao.com/.well-known/jwks.json'); const keys = keyRes.data.keys; let key; // The key that will be used to verify the token // Find the correct key to use for verification for(let i=0; i<keys.length; i++) { if(keys[i].kid === jwt.decode(token, {complete: true}).header.kid) { key = keys[i]; break; } }

  if(!key) {
      return {
          statusCode: 401,
          body: JSON.stringify({message: 'Could not find matching Kakao key to verify token'})
      };
  } else {
    console.log('key: ', key);
  }

  // Convert the JWK to a PEM
  let pem = jwkToPem(key);

  // Verify the identity token
  const decodedToken = jwt.verify(token, pem);

  const cognitoRes = await cognitoidentity.getId(params).promise();

  const credentials = await cognitoidentity.getCredentialsForIdentity({
    IdentityId: cognitoRes.IdentityId,
    Logins: {
      'kauth.kakao.com': token
    }
  }).promise();

Using this code, I have checked the iss value and aud value in decodedToken is valid, and cognitoidentity.getId() successfully resuturns valid cognitoRes, and also checked the identity is registered in the identity pool, but getCredentialsForIdentity() throws an exception, InvalidIdentityPoolConfigurationException: Invalid identity pool configuration. Check assigned IAM roles for this pool.

dnys1 commented 11 months ago

Given that it is failing using the JS AWS SDK as well, I don't believe it's an issue with the Amplify Flutter library.

Can you see if following these steps helps? It seems like there may be a missing trust relationship in your identity pool roles.

dnys1 commented 10 months ago

Hi @kyeongyeonsong are you still experiencing this issue? Please let me know. I'll be closing out this issue if we don't hear back from you in 7 days.

alexboulay commented 4 months ago

Hi I am having the same issue as OP but in my case, the Identity Pool and Identity Provider seem to be correctly configured since I am able to exchange token using the aws-sdk library, not sure what is going on.

this does not work:

Future<void> _configureAmplify() async {
  try {
    final auth = AmplifyAuthCognito();
    await Amplify.addPlugin(auth);

    // call Amplify.configure to use the initialized categories in your app
    await Amplify.configure(amplifyconfig);
  } on Exception catch (e) {
    safePrint('An error occurred configuring Amplify: $e');
  }
}
 try {
    final cognitoPlugin = Amplify.Auth.getPlugin(AmplifyAuthCognito.pluginKey);
    final token = authController.idToken!;

    final session = await cognitoPlugin.federateToIdentityPool(
      token: token,
      provider: AuthProvider.oidc(
       name,
       iss,
      ),
    );
  } catch (e) {
    print("error in cognito login");
    print(e);
  }
const amplifyconfig = ''' {
    "UserAgent": "aws-amplify-cli/2.0",
    "Version": "1.0",
    "auth": {
        "plugins": {
            "awsCognitoAuthPlugin": {
                "IdentityManager": {
                    "Default": {}
                },
                "CredentialsProvider": {
                    "CognitoIdentity": {
                        "Default": {
                            "PoolId": "my-pool-id",
                            "Region": "region"
                        }
                    }
                }
            }
        }
    }
}''';

this does work:

const getCredentials = async () => {
     const cognitoidentity = new CognitoIdentityClient({
          credentials : fromCognitoIdentityPool({
              client : new CognitoIdentityClient(),
              identityPoolId : IdentityPoolId,
              logins: {
                [name] : jwtIdToken
              }
           }),
      });
      const credentials = await cognitoidentity.config.credentials()
      console.log(credentials)
     return credentials
}

Also, I wonder why does the JS api doesn't require me to give the iss like the Flutter API does? (just curious)

alexboulay commented 4 months ago

So I made it work by matching iss with the name, so it was basically the same but without https:// prefix and trailing /