An example for using Amazon Cognito together with an external IdP
This example can be used as a starting point for using Amazon Cognito together with an external IdP (e.g. a SAML 2.0/OIDC provider or a social login provider). It shows how to use triggers in order to map IdP attributes (e.g. LDAP group membership passed on the SAML response as an attribute) to Amazon Cognito User Pools Groups and optionally also to IAM roles.
It contains all that is needed in order to create a serverless web application with Amazon Cognito, Amazon API Gateway, AWS Lambda and Amazon DynamoDB (with optionally an external IdP).
It handles fine-grained role-based access control and demonstrates how to associate users to roles/groups based on mapped attributes from an external IdP or social login provider.
It is using TypeScript for frontend, backend and infrastructure. (Using AWS CDK)
The example contains the following modules within these sub-folders:
This module is using AWS CDK
CDK is a software development framework for defining cloud infrastructure in code and provisioning it through AWS CloudFormation.
It defines all the resources needed in order to create the sample application
It defines the following resources
The backend of the example. This is a standard AWS Lambda application written as a node.js (express.js) application
In order to allow express.js to run in an AWS Lambda runtime, we include https://github.com/awslabs/aws-serverless-express
(see more examples here)
Some notable files
index.ts: this is a regular lambda handler that uses aws-serverless-express to map between a AWS Lambda Proxy Integration request/response structure and the express.js app
app.ts: this is the actual express.js app
local.ts: this can be used to launch the app locally as a regular express.js app.
services/authorizationMiddleware.ts: this is an example express.js middleware that does the following:
Adds type information to the request for simple auto-completion of available request information passed from Amazon API Gateway to the lambda function
A convenient / syntactic sugar that makes the claims and Amazon Cognito User Pool group available on the request object.
e.g. req.groups.has("admin-role")
will return true if the user is authenticated and is a member of group "admin-role"
and const email = req.claims ? req.claims.email : null;
will get the user's email if the user is logged in and has an email claim in the JWT
This is an Amazon Cognito User Pools Trigger that allows to add/remove claims from the JWT ID token before giving it to the user.
It is using a trigger named Pre Token Generation. It allows to do the following:
email
or custom:customAttributeName
)cognito:groups
)roles
and preferred_role
mapping.
These mappings are similar to assigning a role to a group in the AWS console.
This can be used to later give users fine grained, temporary AWS credentials based on their group.In this example we simply map from a custom attribute (that is mapped from an IdP attribute, e.g. a SAML attribute that represents for example the user's group memberships in the corporate directory) into a group claim in the token. Group claims are visible in both the id token and the access token generated by Amazon Cognito.
A simple React frontend that connects to the backend API.
It is using AWS Amplify, that provides, among others react components for simpler integration with various AWS services from web and mobile applications.
AWS Amplify can manage all aspects of a project, but since we used AWS CDK, we followed the manual setup
Some notable files
Do not add the aws.cognito.signin.user.admin
scope, (not added by default)
this will allow users to modify their own attributes directly with the access token.
Since the IdP is the source of truth, and we don't want users to change attributes
(especially those used for authorization) on their own, this scope should not be added.
Do not enable any non-OAuth 2.0 auth flows other than ALLOW_REFRESH_TOKEN_AUTH
(explicitAuthFlows
in cdk.ts) to ensure users can only use the OAuth 2.0 flows.
git clone [email protected]:aws-samples/amazon-cognito-example-for-external-idp.git
)env.sh.template
to env.sh
(not recommended to be pushed to your git repo, it's in .gitignore as a protection)env.sh
and set the values there based on your environment./install.sh
which does the following:
npm install
in all relevant sub-folders)tsc -b
in each relevant sub-folder - tsc is the TypeScript compiler)cdk bootstrap
- which creates a stack named CDKToolkit (if it was not created already) that helps simplify managing assets.
For more information about assets see here
NOTES:
export AWS_PROFILE=<profilename>
before the above commands, or AWS_PROFILE=<profilename> ./<command>.sh
$ npm i -g aws-cdk
(see here for more details)./deploy.sh
to deploy the backend stack. (For the first time as well as after making changes)cd ui-react && npm start
to run the UI in http://localhost:3000
Run ./diff.sh
to compare deployed stack with current state
Run ./synth.sh
to display the generated CloudFormation script from the CDK code
Run ./test.sh
to run all tests
Run ./build.sh
to compile all packages
Run ./clean.sh
to clean compiled packages
Windows command-line files will be coming soon, in the meantime you can use either of these solutions in order to run sh files
Okta:
ADFS:
AWS Security Blog Post: Role-based access control using Amazon Cognito and an external identity provider
AWS re:Inforce 2019: Identity and Access Control for Custom Enterprise Applications (SDD412) Video | Slides
Please note, Angular support was removed from this repo to simplify maintenance activities, currently only the react UI is supported. You can view the old Angular UI on the Angular Archive branch (this is static and receives no security updates)
This sample code is made available under the MIT-0 license. See the LICENSE file.