26
votes

I want to use AWS cognito as a OpenId connect provider.My AWS cognito IDP will intern call my another OpenId provider to authenticate the user. It will then create its new token and hand over to callers as its own.

The OpenID provider used internally by AWS cognito pool is transparent to user. User only configures AWS cognito as its IDP provider.

User case

  • User authenticates with My AWS IDP provider
  • My IDP provider authenticates the user agains Googles IDP provider
  • My IDP decodes the token returned by Google IDP.
  • My IDP Creates new token and add additional claims.
  • My IDP hands over my JWT to user.

Question

  • Is this possible in AWS cognito?
  • Does AWS user pool expose OpenID connect endpoint?
3

3 Answers

21
votes

Cognito does provide an OpenId connect endpoint, as detailed in this blog post by @Badri

The formula for the authority is:

https://cognito-idp.{region}.amazonaws.com/{userPoolId}

And you can verify by checking the metadata URL that something is there

https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/openid-configuration

Then during client pool setup, you can federate with other OIDC providers, and also enable the OIDC provider in the app client settings. Which should enable your scenario which sounds very similar to what I would like to do. However, the blog post misses one crucial piece of configuration, which is setting a domain name for the app integration. This StackOverflow question shows the error you will receive if you do not configure this domain and links to the solution in an answer. Once I set the domain, Badri's code worked for me.

10
votes

To give a more detailed answer on Cognito's OpenID Connect support.

Discovery Endpoint

Cognito exposes an OpenID Connect Discovery endpoint as described at https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest at the following location:

https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/openid-configuration

Response Types

The above endpoint returns the following three response_types:

"response_types_supported":["code","token","token id_token"]
  • code: defined in https://tools.ietf.org/html/rfc6749#section-11.3.2 - this worked for us, but only when a domain was specified as below.

  • token: this value is forbidden by OpenID Connect at https://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthRequest - "NOTE: While OAuth 2.0 also defines the token Response Type value for the Implicit Flow, OpenID Connect does not use this Response Type, since no ID Token would be returned." - OpenID Connect libraries will ignore this response.

  • token id_token: this value triggers a redirect to an error page with the code "invalid_request". There is no indication given as to what is invalid with the request. AWS technical support claim that only "code" and "token" are supported by authorize endpoint, it is however not clear why this response_type is advertised if not supported.

Domain

Cognito gives the option to specify a domain that will prefix the hostname of the Cognito endpoint.

Without a domain being specified, Cognito will advertise generic URLs at the OpenID Connect discovery endpoint such as https://cognito-idp.eu-west-2.amazonaws.com/{userPoolId}/authorize, but all attempts to log in at these URLs return the error message:

{"code":"BadRequest","message":"The server did not understand the operation that was requested.","type":"client"}

The error message does not indicate what is bad about the request, so this appears to be a bug in Cognito.

With a domain specified, Cognito will advertise URLs that include the domain prefix, and the response_type "code" returns a login page as expected.

Logout

OpenID Connect Session Management at https://openid.net/specs/openid-connect-session-1_0.html#RPLogout describes how an OpenID Connect logout must be initiated, and requires as per https://openid.net/specs/openid-connect-session-1_0.html#OPMetadata that the end_session_endpoint parameter be included in the discovery metadata.

In the case of Cognito end_session_endpoint is omitted from the metadata.

RP-Initiated Logout at https://openid.net/specs/openid-connect-session-1_0.html#RPLogout describes how the logout endpoint works. If an attempt is made to pass the logout endpoint manually to the OpenID Connect client implementation, logout fails as follows:

{"code":"BadRequest","message":"The server did not understand the operation that was requested.","type":"client"}

Again, the error message gives no indication of the error, however the description of the logout endpoint at https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html shows no compatibility with OpenID Connect.

While you can log into Cognito using OpenID Connect, there is no option to log out.

Cloudformation

Cognito Cloudformation support is incomplete, and affects OpenID Connect as follows:

  • There is no way to specify a domain using Cloudformation, and the domain is required for OpenID Connect to work.
  • The callback URL is required by OpenID Connect, but cannot be set using Cloudformation.

Summary

To access Cognito using OpenID Connect, ensure that a domain is specified, and use the response_type "code" only. OpenID Connect logout is not possible. Other options violate the OpenID Connect specification, or were released broken.

4
votes

I'm having a little trouble following your use case, but I'll explain some points that might help.

You can use Cognito User Pools to authenticate users through Google, and then issue JWT tokens from the Cognito User Pool. See the Developer Guide.

Cognito User Pools is not currently a full OpenID identity provider, but that is on our roadmap. User Pools do support OAuth2.0 flows, and they do provide OpenID standard JWT tokens.