loading...

Using Cognito User Pool as an OpenID Connect Provider

namuny profile image Daniel Kim ・7 min read

Couple of weeks ago I was involved in a hackathon which involved integrating two Cognito user pools together. During my investigation I discovered that Cognito user pool supports OAuth2 for user authentication. This post will outline how you can use Cognito user pool as an OIDC provider as well as how you can connect two user pools together.

Who is this post for?

This post is for you if you:

  • Have basic understanding of AWS Cognito user pools
  • Want to know how Cognito user pools can be used as a OIDC provider
  • How to associate two user pools together through federated identity providers

Sections

What is OpenID Connect?

OpenID is a protocol which provides a mechanism to authenticate users through a third party. This means that users can login to your application with existing accounts on other platforms. When a user completes the OIDC flow, your application can gain access to some of their information from the third party in the form of an id_token which is a JWT token.

User Pool Setup

In this section we'll create two Cognito user pools and configure them so they can integrate together. oidc-pool-1 will be the master user pool which uses oidc-pool-2 as a federated identity provider. We'll create a user in oidc-pool-2 and keep oidc-pool-1 empty.

Alt Text

Search for Cognito on the AWS console and click on Manage User Pools. Click Create a user pool on the top right corner.

Alt Text

After entering the name of your user pool, you are presented with two options. I'll be clicking Review defaults for the purpose of this demo but you're welcome to step through the settings. This option will let you specify some crucial settings for your user pool such as required attributes for a user. Note that this information cannot be changed once you create your user pool.

Alt Text
Once you've created a user pool, navigate to App clients.

Alt Text
An app client has access to invoke certain endpoints on your user pool while being unauthenticated. Decide on a name and create the app client. We'll leave rest of the settings as is.

Alt Text
Head over to the Domain name page and register a domain for your user pool. Take note of the domain that you enter here.

Alt Text
Repeat the process above and create another user pool. Apply the exact same configuration as the first user pool. Take note of the App client id and App client secret as well as the Pool Id for the second user pool, we will need this when we integrate the two user pools together.

Alt Text
If you followed the post up to this point, you'll now have two Cognito user pools, each with an app client and a domain. If you're satisfied with your setup, navigate to App client settings of your second user pool.

Alt Text
This is where the integration begins. Choose Select all for Enabled Identity Providers and set the Callback URL(s) in the following format:

https://${USER_POOL_DOMAIN}/oauth2/idpresponse

This allows users authenticated with the second user pool to be redirected to the master user pool.

Since I didn't prepare any web app to demo this integration, I'm setting a random value on the Sign out URL(s).

Alt Text
Select Authorization code grant and openid under OAuth 2.0 and click Save changes.

Configuring Federated Identity Provider

Cognito user pools support integration with federated identity providers such as Google and Facebook. We'll use this feature to integrate our user pools together.

Alt Text
Navigate to Identity providers on the first user pool. Select OpenID Connect and you'll see the form below.

Alt Text

Here's how you should fill in the form:

Provider name: Arbitrary name
Client ID: App client id of the second user pool
Client secret: App client secret of the second user pool
Attributes request method: GET
Authorize scope: openid
Issuer: https://cognito-idp.${REGION}.amazonaws.com/${SECOND_USER_POOL_ID}

User pool ID can be found on the General settings menu. Click on Run discovery once you've filled in the form.

Alt Text
Don't be worried if you see this warning.

Open a new tab in your browser and navigate to https://cognito-idp.${REGION}.amazonaws.com/${SECOND_USER_POOL_ID}/.well-known/openid-configuration. You'll see a JSON response with a set of properties. This information can be used to fill in the rest of the form.

Authorization endpoint: https://${SECOND_USER_POOL_DOMAIN}/oauth2/authorize
Token endpoint: https://${SECOND_USER_POOL_DOMAIN}/oauth2/token
Userinfo endpoint: https://${SECOND_USER_POOL_DOMAIN}/oauth2/userInfo
Jwks uri: https://cognito-idp.${REGION}.amazonaws.com/${SECOND_USER_POOL_ID}/.well-known/jwks.json

Click on Create provider Once you've filled in the form completely.

Alt Text
Navigate to App client settings on your master user pool. Select the name of the federated identity provider that you just added (and Cognito User Pool if you want to support direct login through this client). Add suitable URLs for callback and sign out. Check Authorization code grant and openid in OAuth 2.0 and click on Save changes. There is only one step left to integrate the two user pools.

Alt Text
Navigate to Attribute mapping page of the master user pool. Click on the OIDC tab. This form indicates how the attributes of the second user pool maps to the attributes of the master user pool.

When you land on this page for the first time, you'll only see a sub attribute. This is a built-in mapping which acts as a unique identifier of the user. If you're using the default user pool configurations you can add the email related mappings as can be seen above. Otherwise you'll want to map whatever attribute makes sense for your use case. Note that you must add attributes that are marked as required on your master user pool. Click on Save changes once you're happy with the attribute mapping.

This marks the end of this integration! Continue to the next section if you want to find out how you can test it using Cognito Hosted UI.

Testing

To simply the testing process, we'll be using Cognito Hosted UI. This is a built-in set of UI elements that allows users to perform basic auth flows such as sign-in, sign-up and sign-out. In reality, you might be using a custom web app with a library such as AWS Amplify to simplify the authentication process.

Alt Text
Navigate to Users and groups on the second user pool and create a user. For the sake of this post I'll have Mark email as verified ticked. If you're using the same user pool configuration as I am, your user will be in FORCE_CHANGE_PASSWORD state.

Alt Text
Navigate to App client settings on your master user pool and click on Launch Hosted UI.

Alt Text
If you selected both YOUR_OIDC_PROVIDER_NAME and Cognito User Pool on your *App client settings, you'll see the same page as I do. Click on the button below Sign in with your corporate ID.

Alt Text
From this page you can sign in as the user you've created on your second user pool.

Alt Text
Depending on your user pool configurations, you might see this page when you sign in. Simply enter a new password for your user. After this step you may notice that your user in the second user pool is now in a CONFIRMED state. Try logging in again on the Hosted UI.

Alt Text
If you're redirected to google.com (or whatever your redirect URL on the master user pool is) with the code in the query parameter, you've set everything up correctly and the integration is working as expected! Head over to Users and groups on your master user pool to confirm that a new user has been created (it was previously empty). This user should have correct attributes pulled from the second user pool.

Conclusion

We've seen how Cognito user pool can be used as an OIDC provider as well as how we can use this concept to associate two user pools together. If you want to integrate your user pool with another service, you can use the same endpoints provided on this post.

Lastly if you want to integrate this flow with a web app, I again recommend looking into AWS Amplify and how it handles authentication.

Discussion

pic
Editor guide
Collapse
wywarren profile image
Warren Wang

We’ve currently built our own login screens using amplify, but with the flow demonstrated in this post, it only allows redirecting to the aws hosted UI interface. How can we set it up so that it redirects to our custom built front end url? Thanks!