How to Create a Client in Keycloak to use with AWS Cognito Identity Federation

shonky linux user picture shonky linux user · Apr 13, 2018 · Viewed 7.5k times · Source

I have a user base with identity and authentication managed by keycloak. I would like to allow these users to login and use AWS API Gateway services with Cognito using an OpenID Connect federation.

The AWS documentation on using an OpenID Connect provider is somewhat lacking. I found an old reference using SAML but would prefer to avoid this and use OpenID Connect.

If anybody has achieved this would they mind writing up some simple instructions from the keycloak admin perspective?

Answer

shonky linux user picture shonky linux user · May 15, 2018

Answering my own question for future searchers based on advice I have received from AWS Support:

The question itself was based on a misunderstanding. AWS Cognito does not authenticate users with Keycloak - the client application does that.

Cognito Identity Federation is about granting access to AWS resources by creating AWS Access credentials to an identity with a token from an external identity provider.

The OpenID client in keycloak is the one and same client that is used by the end-user application. Redirection URLs send the user back to the application, which then passes the JWT token to AWS to exchange for AWS credentials.

Cognito relies on the client app first directing the user to the authentication provider of their choice (in this case Keycloak), and then passing the access token from Keycloak to Cognito which uses it to 1) create an identity if required, and 2) generate AWS credentials for access to the AWS role for "Authenticated" users in Cognito.

An example using the AWS CLI: (substitute ap-southeast-2 in the examples with your local region)

Prerequsite: client app obtains JWT access token for the end user using any OpenID authentication method

Create or retrieve an identity from cognito:

aws cognito-identity get-id --cli-input-json file://test.json

Returns the identity:

{
    "IdentityId": "ap-southeast-2:<identity_uuid>"
}

test.json contains the details of the AWS Account, the cognito pool and the user's JWT access token from keycloak:

{
    "AccountId": "123456789012",
    "IdentityPoolId": "ap-southeast-2:<cognito-identity-pool-uuid>",
    "Logins": {
        "keycloak.url/auth/realms/realmname": "<access_token_jwt>"
     }
}

The app can then use this returned identity, along with the JWT access token to obtain AWS Credentials with which to consume AWS services...

aws cognito-identity get-credentials-for-identity --identity-id ap-southeast-2:<identity_uuid> --cli-input-json file://test2.json

Returns an AccessKeyId, a SecretKey and an AWS SessionToken along with an expiry time. These can be used to access AWS services depending on the permissions of the authenticated role that was established in the setting for the Cognito Federated Identity Pool:

{
    "Credentials": {
        "SecretKey": "<secret_key>",
        "SessionToken": "<aws_cli_session_token>",
        "Expiration": 1567891234.0,
        "AccessKeyId": "<access_key>"
    },
    "IdentityId": "ap-southeast-2:<identity_uuid>"
}

The contents of test2.json

{
    "IdentityId": "ap-southeast-2:<identity_uuid>",
    "Logins": {
        "keycloak.url/auth/realms/realmname": "<keycloak_access_token_jwt>"
    }
}

I hope this provides context and assistance to people that stumble across this question in future.