This repository describes how to integrate Amazon Cognito User Pool(OAuth 2.0 Client credentials grant) and Amazon API Gateway(Cognito Authorizer) using AWS CDK. This sample is applicable to a usecase for machine to machine authorization rather than user-login authentication. All resources and configuration is provided through AWS CDK(typescript codes).
Among Authorization Grant OAuth 2.0 authorization framework proivdes, Client credentials grant is used for machine to machine communication for here. We can use this flow to request an access token to access our own resources.
Amazon Cognito user pool supports the OAuth 2.0. Since the client credentials flow is not used on behalf of a user, only custom scopes can be used with this flow. A custom scope is one that you define for your own Resource servers
in Cognito user pool. An access token returned from Cognito authorization server includes what kind of custom scopes we can access. Detail guide: cognito-user-pools-app-idp-settings
- Create Cognito
User Pool
- Create
Domain name
in the user pool - Create
Resource servers
andcustom scopes
in the user pool - Create
App client
in the user pool, - Enable OAuth 2.0 Client credentials in the
App client
- Allow custom scopes in
OAuth 2.0 settings
inApp client
We can control access to a REST API of Amazon API Gateway using Amazon Cognito user pools as authorizer. Cognito Authizaer in Amazon API Gateway verifies the token on our behalf. The access token is used to authorize API calls based on the custom scopes of specified access-protected resources. Detail guide: apigateway-integrate-with-cognito
- Create Amazon API Gateway(REST API)
- Create Authorizaer in the REST API with type = Cognito & with Cognito user pool created in Cognito User pool
- Create some resources in the REST API
- Create method in the resources with Cognito Authorizer and OAuth Scopes created in Cognito User pool
All the resources described above are implemented and provided through AWS CDK ver2. Because this CDK project is built on top of AWS CDK Project Template for DevOps , please refer to that repository for details.
And other "Using AWS CDK" series can be found at:
- AWS Serverless Using AWS CDK
- Amazon SageMaker Model Serving Using AWS CDK
- AWS ECS DevOps using AWS CDK
- AWS IoT Greengrass Ver2 using AWS CDK
- Amazon SageMaker Built-in Algorithms MLOps Pipeline Using AWS CDK
First of all, AWS Account and IAM User is required. And then the following modules must be installed.
AWS CLI: aws configure --profile [profile name] Node.js: node --version AWS CDK: cdk --version jq: jq --version curl: curl --version
Caution: This solution contains not-free tier AWS services. So be careful about the possible costs.
vim config/app-config-demo.json # change project's AWS Account/Region/Profile
export APP_CONFIG=config/app-config-demo.json
sh script/setup_initial.sh config/app-config-demo.json
sh script/destroy_stacks.sh config/app-config-demo.json
export CLIENT_ID=....... # check app client in Cognito WebConsole
export CLIENT_SECRETE=....... # check app client in Cognito WebConsole
export DOMAIN_NAME=....... # check cdk deploy output: OAuthCognitoStack.OutputCognitoUserPoolDomainName
curl -X POST --user $CLIENT_ID:$CLIENT_SECRETE $DOMAIN_NAME/oauth2/token?grant_type=client_credentials -H "Content-Type: application/x-www-form-urlencoded"
{"access_token":".......","expires_in":86400,"token_type":"Bearer"}
book
related requests only will be successful!
export API_ENDPOINT=....... # check cdk deploy output: RestApigatewayStack.RESTAPIsEndpoint
export ACCESS_TOKEN=....... # check client_credential's output: "access_token":"......."
curl -X GET "${API_ENDPOINT}book" -H "Authorization:${ACCESS_TOKEN}"
{"Result":"Success","Description":"your GET for /book is completed"}
curl -X POST "${API_ENDPOINT}book" -H "Authorization:${ACCESS_TOKEN}"
{"Result":"Success","Description":"your POST for /book is completed"}
curl -X GET "${API_ENDPOINT}user" -H "Authorization:${ACCESS_TOKEN}"
{"message":"Unauthorized"}
curl -X POST "${API_ENDPOINT}user" -H "Authorization:${ACCESS_TOKEN}"
{"message":"Unauthorized"}
Change Allow options in config/app-config-demo.json
file. In this example, user
-related Scope Allow: false -> true.
"OAuthCognito": {
"Name": "OAuthCognitoStack",
"UserPoolName": "UserPool",
"UserPoolClientName": "OAuthClient",
"CognitoDomainPrefix": "api",
"ResourceServerIdentifier": "API",
"ResourceServerScopes": [
{"Key": "ScopeBookGet", "Scope":"book.get", "Allow": true},
{"Key": "ScopeBookPost", "Scope":"book.post", "Allow": true},
{"Key": "ScopeUserGet", "Scope":"user.get", "Allow": false},
{"Key": "ScopeUserPost", "Scope":"user.post", "Allow": false}
]
},
And then re-deploy OAuthCognitoStack
Stack like this command.
cdk deploy *OAuthCognitoStack --profile [your-profile]
Before request user
resource again, you must request access-token first!
curl -X POST --user $CLIENT_ID:$CLIENT_SECRETE $DOMAIN_NAME/oauth2/token?grant_type=client_credentials -H "Content-Type: application/x-www-form-urlencoded"
{"access_token":".......","expires_in":86400,"token_type":"Bearer"}
export ACCESS_TOKEN=....... # check client_credential's output: "access_token":"......."
curl -X GET "${API_ENDPOINT}user" -H "Authorization:${ACCESS_TOKEN}"
{"Result":"Success","Description":"your GET for /user is completed"}
curl -X POST "${API_ENDPOINT}user" -H "Authorization:${ACCESS_TOKEN}"
{"Result":"Success","Description":"your POST for /user is completed"}
sh script/destroy_stacks.sh config/app-config-demo.json
Caution: You must delete
Amazon Cognito User Pools manually because of removal policy.
See CONTRIBUTING for more information.
This library is licensed under the MIT-0 License. See the LICENSE file.