Notes On AWS Cognito
OAuth is a protocol to allow user via an authentication provider to give another website/service a limited access authentication token for authorization to additional resources. It is primarily authorization framework, not authentication.
Authentication deals information about "who one is". Authorization deals information about "who grants what permissions to whom". Authorization flow contains authentication as its first step.
There are many libraries and services that use OAuth 2.0 for authentication. It is often called "social login". If you see "OAuth authentication" (not "OAuth authorization"), it is a solution using OAuth for authentication.
OAuth says absolutely nothing about the user, nor does it say how the user proved their presence or even if they're still there. As far as an OAuth client is concerned, it asked for a token, got a token, and eventually used that token to access some API. The token is opaque.
You can build an authentication and identity protocol on top of OAuth delegation and authorization protocol. And in fact, there are a number of well-known recipes out there for doing this with specific providers, like Facebook Connect, Sign In With Twitter, and OpenID Connect (which powers Google's sign-in system, among others). These recipes each add a number of items, such as a common profile API, to OAuth to create an authentication protocol.
General OAuth does not define a specific format or structure for the access token itself, protocols like OpenID Connect's ID Token and Facebook Connect's Signed Response provide a secondary token along side the access token that communicates the authentication information directly to the client. This allows the primary access token to remain opaque to the client, just like in regular OAuth.
See Also:
OAuth 2.0 is a framework where a user of a service can allow a third-party application to access his/her data hosted in the service without revealing his/her credentials (ID & password) to the application.
OAuth2.0 provides following compared to OAuth 1:
OAuth 2.0 is a flexible authorization framework, not a protocol.
The authorization endpoint is used to interact with the resource owner and obtain an authorization grant. The authorization server MUST first verify the identity of the resource owner. The way in which the authorization server authenticates the resource owner (e.g., username and password login, session cookies) is beyond the scope of this specification.
Client needs access token which can be used to access an API endpoint.
It describes 5 methods(grants) for client application to acquire access token:
Authorization code grant:
- client_id, client_secret, scope, code, redirect_url,
access-token, refresh-token
- grant_type is "authorization code"
Implicit grant
- For Single Page App client.
- Similar to above but Single step get access-token.
- No client_secret, No refresh token
Resource owner credentials grant
- client_id, client_secret, scope,
username, password, access-token, refresh-token
- No redirect_uri
- grant_type is "password"
Client credentials grant
- Simplest and for machine to machine trusted authentication
- client_id, client_secret, scope, access-token
- No refresh token, redirect_uri
- grant_type is "client_credentials"
Refresh token grant
- submit refresh token and get new access token
- grant_type is "refresh token"
OAuth scope is a list of permissions. e.g. "READ WRITE" OpenID connect uses scope values: profile, email, address, and phone, etc (which means access to email or phone information etc)
OAuth defines no specific token format, defines no common set of scopes for the access token, and does not at all address how a protected resource validates an access token. OpenID-Connect fills that gap.
OpenID Connect also uses the JSON Object Signing And Encryption (JOSE) suite of specifications.
OpenID Connect defines an important component called ID Token:
See https://stackoverflow.com/questions/33702826/oauth-authorization-vs-authentication/33704657 https://security.stackexchange.com/questions/44611/difference-between-oauth-openid-and-openid-connect-in-very-simple-term
In OpenID, authentication is delegated: server A wants to authenticate user U, but U's credentials (e.g. U's name and password) are sent to another server, B, that A trusts (at least, trusts for authenticating users). Indeed, server B makes sure that U is indeed U, and then tells to A: "ok, that's the genuine U".
In OAuth, authorization is delegated: entity A obtains from entity B an "access right" which A can show to server S to be granted access; B can thus deliver temporary, specific access keys to A without giving them too much power. You can imagine an OAuth server as the key master in a big hotel; he gives to employees keys which open the doors of the rooms that they are supposed to enter, but each key is limited (it does not give access to all rooms); furthermore, the keys self-destruct after a few hours.
To some extent, authorization can be abused into some pseudo-authentication, on the basis that if entity A obtains from B an access key through OAuth, and shows it to server S, then server S may infer that B authenticated A before granting the access key. So some people use OAuth where they should be using OpenID.
Secure Remote Password Protocol. See http://srp.stanford.edu/ This protocol resists both passive and active network attacks. Involves a strong derived session key as result of sequence of exchanges of short messages as per protocol.
Add authentication information in HTTP header or query string itself using a signing key which is derived from shared key plus timestamp plus payload. Most aws cli commands use this style.
If you have middleware server which interacts with AWS cognito, you would probably use this as well.
Cognito access tokens are JWT, which are signed with JWK (Jason Web Key). The JWT contains standard claims, but can also be extended to contain custom claims. The reserved standard claims are:
iss (issuer): Issuer of the JWT
sub (subject): Subject of the JWT (the user)
aud (audience): Recipient for which the JWT is intended
exp (expiration time): Time after which the JWT expires
nbf (not before time): Time before which JWT must not be accepted.
iat (issued at time): Time at which the JWT was issued;
jti (JWT ID): Unique identifier; Allows a token to be used only once.
Resource server is a place holder for scopes (permissions)
There can be multiple resource servers associated with a single User Pool.
By the time the request makes it to the Resource Server, it has an access token which reveals user and the session.
An example Resource Server called transactions in which we define 2 scopes called get and post transactions :
aws> cognito-idp create-resource-server --name transactions --identifier
transactions --user-pool-id us-east-1_0Pe***** --scopes
ScopeName=get,ScopeDescription=get_tx ScopeName=post,ScopeDescription=post_tx
{
"ResourceServer": {
"UserPoolId": "us-east-1_0Pe*****",
"Identifier": "transactions",
"Name": "transactions",
"Scopes": [
{
"ScopeName": "post",
"ScopeDescription": "post_tx"
},
{
"ScopeName": "get",
"ScopeDescription": "get_tx"
}
]
}
}
Mobile or Web client authentication Involves 2 steps :
Instead of client side app, if you have backend server side App, the authentication flow is :
Initiate AdminInitiateAuth API (instead of InitiateAuth). This requires AWS admin credentials.
AdminRespondToAuthChallenge API (instead of RespondToAuthChallenge), which also requires AWS admin credentials.
For server side App it is not mandtory to use AdminInitiateAuth. However, it is recommended.
The request looks like :
AdminInitiateAuth Request {
"AuthFlow":"ADMIN_NO_SRP_AUTH",
"AuthParameters":{
"USERNAME":"<username>",
"PASSWORD":"<password>"
},
"ClientId":"<clientId>",
"UserPoolId":"<userPoolId>"
}
S3 is a simple key value store. Each object supports :
Key – The file path
Version ID – You can have different versions of same object!
Value – The content that you are storing.
Metadata – A set of name-value pairs. Both system and your own.
Subresources – Example: ACL
Both S3 bucket and IAM Policy follows standard AWS policy syntax. S3 bucket policy contains "Principal", but IAM policy does not. Both contains "Resource" pointing to bucket/objects. A policy is represented as "Statement".
Sample S3 Bucket policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
/* Use "Principal" : "*" for public access */
"Principal": {
"AWS": ["arn:aws:iam::111122223333:user/Alice",
"arn:aws:iam::111122223333:root"]
},
"Action": "s3:*",
"Resource": ["arn:aws:s3:::my_bucket",
"arn:aws:s3:::my_bucket/*"]
}
]
}
Sample IAM policy:
{
"Version": "2012-10-17",
"Statement":[{
"Effect": "Allow",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::my_bucket",
"arn:aws:s3:::my_bucket/*"]
}
]
}
Using ACL, you give permission using User UUID or GROUP, etc. ACL is a "subresource" attached to S3 bucket and objects. Default ACL is created to grant full-control only for the owner of the bucket/object.
Sample bucket ACL:
{
"Owner": { "DisplayName": "thavamuni", "ID": "78a2..." },
"Grants": [
{
"Grantee": {
"Type": "CanonicalUser",
// "Type": "CanonicalUser"|"AmazonCustomerByEmail"|"Group",
"DisplayName": "thavamuni",
"ID": "78a2170...b8a993"
},
"Permission": "FULL_CONTROL"
},
{
"Grantee": {
"Type": "Group",
"URI": "http://acs.amazonaws.com/groups/global/AllUsers"
},
"Permission": "READ"
}
]
}
<Directory /var/www/html>
Order Allow,Deny
Allow from all
AllowOverride all
Header set Access-Control-Allow-Origin "*"
</Directory>
# Add/activate module
a2enmod headers
GetId
GetCredentialsForIdentity
Using cli:
# Step 0. It is handled by User pool.
aws cognito-idp initiate-auth --client-id 1jtj0a0peedlgfdhml3dr5t8j
--auth-flow USER_SRP_AUTH --auth-parameters USERNAME=myuser,PASSWORD='xxx'
See https://github.com/capless/warrant
from warrant import Cognito
u = Cognito('your-user-pool-id','your-client-id', username='bob')
u.authenticate(password='bobs-password')
# This is done by Identity pool. You submit pool-name and IdToken
# If you do not pass logins, you can "unauthenticated" IndentityId
aws cognito-identity get-id --identity-pool-id <value> --logins <value>
# Submit IdentityId and poolname, IdToken.
aws cognito-identity get-credentials-for-identity --identity-id <value>
--logins <value> # STS Service
::
print("Current user: " + boto3.resource('iam').CurrentUser().arn)
User: arn:aws:sts::749340585813:assumed-role/golfnow-start-job/dev-StartJobLambda-HZO22Z5IMTFB
get_caller_identity() method in boto3. This is under sts service. It will return the ARN of the entity attached to the Lambda function
While using temporary credentials acquired through cognito user pool ... :
"requestContext": {
"resourceId": "n1wvn3",
"resourcePath": "/hello",
"httpMethod": "GET",
"extendedRequestId": "Y2rf7FeAIAMF0YQ=",
"path": "/dev/hello",
"accountId": "027212312845",
"stage": "dev",
"domainPrefix": "dbp1ufswd1",
"requestId": "17993b5a-69c6-11e9-a87a-b306e5d12fd3",
"identity": {
"cognitoIdentityPoolId": "us-east-1:bde2164e-cd74-4ca6-a0dc-13adcc08f449",
"accountId": "027212312845",
"cognitoIdentityId": "us-east-1:63f46f9e-87df-4350-93ee-012705073a5e",
"caller": "AROAQMVP26EG5FSTO67ZH:CognitoIdentityCredentials",
"sourceIp": "162.216.143.81",
"accessKey": "ASIAQMVP26EGZ3FQBPJH",
"cognitoAuthenticationType": "authenticated",
"cognitoAuthenticationProvider": "cognito-idp.us-east-1.amazonaws.com/
us-east-1_KrWqAV47M,cognito-idp.us-east-1.amazonaws.com/
us-east-1_KrWqAV47M:CognitoSignIn:
5a9226ef-6805-4297-a00e-cc9716d8f82d",
"userArn": "arn:aws:sts::027212312845:assumed-role/
hdemo-group-admin-iam/CognitoIdentityCredentials",
"user": "AROAQMVP26EG5FSTO67ZH:CognitoIdentityCredentials"
},
"domainName": "dbp1ufswd1.execute-api.us-east-1.amazonaws.com",
"apiId": "dbp1ufswd1"
}
"identity": {
"cognitoIdentityPoolId": "us-east-1:bde2164e-cd74-4ca6-a0dc-13adcc08f449",
"accountId": "027212312845",
"cognitoIdentityId": "us-east-1:5f17db2c-56da-49d3-b649-4ab822f423e5",
"caller": "AROAQMVP26EG44Z3WPNY5:CognitoIdentityCredentials",
"sourceIp": "162.216.143.81",
"accessKey": "ASIAQMVP26EG5DRXOJEO",
"cognitoAuthenticationType": "unauthenticated",
"cognitoAuthenticationProvider": null,
"userArn": "arn:aws:sts::027212312845:assumed-role/
hdemo-20190419151145-unauthRole/CognitoIdentityCredentials",
"user": "AROAQMVP26EG44Z3WPNY5:CognitoIdentityCredentials"
}
"identity": {
"cognitoIdentityPoolId": null,
"accountId": "027212312845",
"cognitoIdentityId": null,
"caller": "027212312845",
"sourceIp": "162.216.143.81",
"accessKey": "AKIAIGODE5VFHYMUCXQQ",
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": "arn:aws:iam::027212312845:root",
"userAgent": "insomnia/6.4.1",
"user": "027212312845"
},
"identity": {
"cognitoIdentityPoolId": null,
"accountId": "027212312845",
"cognitoIdentityId": null,
"caller": "AIDAQMVP26EGTDG6WOJ5K", // IAM User Id
"sourceIp": "162.216.143.81",
"accessKey": "AKIAQMVP26EGRMWMGQOD",
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": "arn:aws:iam::027212312845:user/hdemo-iam",
"user": "AIDAQMVP26EGTDG6WOJ5K"
}
"Message": "User: arn:aws:sts::027212312845:assumed-role/
hdemo-20190419151145-unauthRole/CognitoIdentityCredentials
is not authorized to perform: execute-api:Invoke on resource:
arn:aws:execute-api:us-east-1:********2845:dbp1ufswd1/dev/GET/hello"
Action Syntax For Invoking API :
execute-api:Invoke
execute-api:InvalidateCache
Resource Syntax:
"arn:aws:execute-api:us-east-1:account-id:api-id/*/GET/pets"
Action Syntax For Managing API end points::
apigateway:GET apigateway:*
Consider automatic invocation of Lambda on S3 upload to create thumbnail images into another S3 bucket.
There are various permissions involved:
Note: Who will be the owner of the bucket when Lambda creates S3 bucket ?
A source bucket with a notification configuration that invokes the Lambda function.
A target bucket where the function saves resized images.
s3.listBuckets(function(err,data) {
if (!err) canonicalAccountId = data.Owner.ID;
}
AWS assigns two unique IDs to each AWS account:
Users, Groups, Roles, Policies, Identity Providers
Example: my-iam-user1, my-ec-admin, my-s3-admin
Users inherit permissions from Group Policies and directly attached inline policies.
Example User ARN arn:aws:iam::571600550186:user/my-iam-user1
Example: my-admins, my-testers
Groups can be associated with one or more policies.
There are more than 500 total Built-in AWS managed policies exist.
Example policy is Administrator Access :
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
FORM_BASED_LOGIN_ENTRY_POINT = "/api/auth/login";
TOKEN_BASED_AUTH_ENTRY_POINT = "/api/**";
TOKEN_REFRESH_ENTRY_POINT = "/api/auth/token";
You have tools for Cognito, API Gateway, etc
const jwt = require('jsonwebtoken');
decode: (token) => {
return jwt.decode(token, {complete: true});
}
import _ from "lodash";
window.lodash = _;
// ------------------------------------
fetch('https://cdn.jsdelivr.net/npm/lodash@4.17.4/lodash.min.js')
.then(response => response.text())
.then(text => eval(text))
Session :: { idToken, accessToken, refreshToken }
"refreshToken": {
"token": "eyJj..."
},
"accessToken": {
"jwtToken": "eyJraWQ...",
"payload": {
"sub": "5a9226ef-6805-4297-a00e-cc9716d8f82d",
"cognito:groups": [
"uspool"
],
"event_id": "6e6f0754-6467-11e9-9e9c-39924d903840",
"token_use": "access",
"scope": "aws.cognito.signin.user.admin",
"auth_time": 1555873101,
"iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_KrWqAV47M",
"exp": 1555876703,
"iat": 1555873103,
// JWT ID : Unique ID for the JWT
"jti": "1f69a0c7-0827-4923-9c5b-ac5591053f19",
"client_id": "33kcb9cvhdlncombg68a6q68un",
"username": "zelestica"
}
},
"clockDrift": -5 // Clock difference between server and client.
}
Login Id/User Pool Id:
cognito-idp.us-east-1.amazonaws.com/us-east-1_KrWqAV47M
JWT Id Token: {
"header": {
// kid is key id, Public Key used to sign.
"kid": "vn4iEO9s4nJNzqRdriSrMS9MWa25sltC42Wy5PGdFLw=",
"alg": "RS256" // Algorithm used.
},
"payload": {
// sub is Cognito User UniqueID.
"sub": "5a9226ef-6805-4297-a00e-cc9716d8f82d",
// Associated Groups ...
"cognito:groups": [
"uspool"
],
"email_verified": true,
// Effective IAM Role ...
"cognito:preferred_role": "arn:aws:iam::027212312845:role/hdemo-group-admin-iam",
// Issuing User Pool ID
"iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_KrWqAV47M",
"phone_number_verified": true,
"cognito:username": "zelestica",
// All associated IAM Roles
"cognito:roles": [
"arn:aws:iam::027212312845:role/hdemo-group-admin-iam"
],
// "aud" is audience. ie. App Client ID
"aud": "33kcb9cvhdlncombg68a6q68un",
"event_id": "6e6f0754-6467-11e9-9e9c-39924d903840",
// Implies it is ID Token
"token_use": "id",
"auth_time": 1555873101,
"phone_number": "+919731595054",
// Expiry time. 3600 seconds later. i.e. 1 hour
"exp": 1555876703, // Expiry claim.
"iat": 1555873103, // Issued-At claim
"email": "zelestica@gmail.com"
},
"signature": "pBTFc....UYA"
}
Followin packages/libraries are now part of AWS amplify. Some of them used to exist separately before:
Build serverless React App using aws amplify :
See https://github.com/dabit3/aws-amplify-workshop-react Excellent example to create react app with cognito.
The README is very informative.
Run express based framework for using with Lambda.
Highlights:
aws cloudformation deploy --template-file hosting.yaml --stack-name
ember-serverless-hosting --capabilities CAPABILITY_IAM
hosting.yaml:
AWSTemplateFormatVersion: '2010-09-09'
Description: Ember Serverless Hosting
Resources:
WebsiteBucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: index.html
...
aws cloudformation describe-stacks --stack-name ember-serverless-api
# Outputs bucket names and such.
# Now deploy API gateway REST API endpoints using .yaml file.
./deploy.sh --stack ember-serverless-api --template api.yaml --bucket
<<bucket-name-from-above-output>>
Cognito auth, etc. Blue prints and examples. spacefinder conference room booking application.
Token based authentication schema's became immensely popular in recent times as they provide important benefits when compared to sessions/cookies:
CORS
No need for CSRF protection
Better integration with mobile
Reduced load on authorization server
No need for distributed session store
Some trade-offs have to be made with this approach:
More vulnerable to XSS attacks.
Access token can contain outdated authorization claims --
(e.g when some of the user privileges are revoked).
Access tokens can grow in size in case of increased number of claims.
File download API can be tricky to implement.
True statelessness and revocation are mutually exclusive.
JWT Authentication flow is very simple:
Users in user pool do have username/password and they authenticate with cognito user pool using SRP (secure remote protocol). As a response to SRP, user gets identity-token, access-token, refresh-token as part of JWT token. This protocol is compliant to OpenId Connect Open Standard.
Identity JWT Token looks like:
Header: alg:RS256,
kid:xxx, (Key id used to sign the token)
payload: email:...,
iss:cognito...,
"cognito:username":...,
given_name:Test,
token_use:id, (Indicates this is ID token)
aud:_client-id_ (audience claim)
email_verified:true, ...
Signature
Access JWT Token looks like :
Header: Key-Id and alg
Payload:
{
"auth_time": 1500009400,
"exp": 1500013000,
"iat": 1500009400,
"iss": "https://cognito-idp...azonaws.com/us-east-1_example",
"scope": "aws.cognito.signin.user.admin",
"sub": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
// Subject is unique UUID for the user. Temp identity ???
// Probably unique across userpools ???
"token_use": "access",
"username": "janedoe@example.com"
}
Signature
Refresh JWT Token looks like :
Header { "alg": "HS512" }
Claims
{
"sub": "svlada@gmail.com",
"scopes": [ "ROLE_REFRESH_TOKEN" ],
"iss": "http://svlada.com",
// JWT ID(jti) claim used to uniquey identify Refresh token
"jti": "90afe78c-1d2e-4869-a77e-1d754b60e0ce",
"iat": 1472033308,
"exp": 1472036908
}
Signature (base64 encoded)
There are 3rd party Identity provider alternatives which can replace cognito's role here. e.g. Auth0, Google, Facebook, etc. i.e. Submit your password using SRP and get some token.
Amazon Federated Identity Pool is used to exchange this token, for AWS IAM credentials. (This is called a bearer token). The protocol involves Get Identity ID request and gets the same. Then it submits Identity ID (as JWT) and requests Get Credentials,
If you are using Cognito, you can skip this step unless you want to login using google/facebook password. (Verify this)
Open question: How to map between UserPool and Federated Identity Pool (e.g. Google Login) ?
Signout operation revokes all tokens for the user: Identity, Access and Refresh tokens all are revoked. Authorization server is informed of this Signout operation, however Resource servers are not aware of this revocation, so until the life of access token it will remain valid??? Singout done by using the GlobalSignOut and AdminUserGlobalSignOut APIs.
----------------------------------------------------------------------
.
.
. User| --- Username/passwd using SRP -------> | Authorization Server
. | <---Gets Id, Access, Refresh Tokens--- | (e.g. Cognito)
. | Id Token: 1 hour valid |
. | |
. | |
. | ----Submit Access Token --Req Access-> | Resource Server
. | (Operation Done if Token is valid) | (Application Specific)
. | |
. | ---- Submit Refresh Token -----------> | Authorization Server
. | <---Gets Id, Access, Refresh Tokens--- | (e.g. Cognito)
. | |
. | ---- Submit Identity Token ----------> | Federated Identity
. | <--- Gets AWS Identity ID ----------- | Server (AWS)
. | ---- Submit AWS Identity ID ---------> | (Using STS Security
. | <--- Gets Temp AWS Credentials ------ | Token Service)
. | (Access Key ID, Secret Key) |
. | |
. | |
. | --- Get Access to AWS Resource ------> | AWS Resource
. | (using temp AWS Credentials) |
. | (Request signed by Sig V4 algo) |
. | |
. | --- Signout Operation ---------------> | Authorization Server
. | Can not use Refresh Token to renew. | (Revokes All Tokens)
. | Must use SRP to get fresh tokens. |
. | Current tokens remain valid until |
. | expiration. They have short validity.|
. | |
. | |
var crypto = require("crypto-js");
function getSignatureKey(key, dateStamp, regionName, serviceName) {
var kDate = crypto.HmacSHA256(dateStamp, "AWS4" + key);
var kRegion = crypto.HmacSHA256(regionName, kDate);
var kService = crypto.HmacSHA256(serviceName, kRegion);
var kSigning = crypto.HmacSHA256("aws4_request", kService);
return kSigning;
}
Example Signature:
POST https://iam.us-east-1.amazonaws.com/?Action=xyz&Version=2010-05-08 HTTP/1.1
Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/cn-north-1
/iam/aws4_request, SignedHeaders=content-type;host; x-amz-date,
Signature=d37af66cc90d.....
content-type: application/x-www-form-urlencoded; charset=utf-8
host: iam.cn-north-1.amazonaws.com.cn.cn
x-amz-date: 20150830T123600Z
Cognito User pools support following kinds of Roles:
AWS Services :
Cloudwatch Monitoring and automation service for admins and dev.
CloudTrail Operational auditing and compliance, logging.
(Mainly to log API calls history for limited services only)
Glue ETL and Crawlers can generate data catalogs.
Athena SQL Service on top of S3
QuickSight PowerBI and Tableu alternative
X-Ray Distributed Tracing System. Works with Lambda, EC2, ECS,
Elastic Bean Stack.
Macie Security service using ML to protect sensitive data.
Kinesis Stream Processing
Direct Dedicated network connection from on-premise data
Connect center to AWS VPC
EMR Amazon Elastic MapReduce (EMR) is Apache Spark and Hadoop
Step Functions Build distributed applications using visual workflows
Synopsis :
aws cognito-idp <action> ....
Supported options are :
create-group
create-identity-provider
create-resource-server
create-user-import-job
create-user-pool
create-user-pool-client
create-user-pool-domain
admin-list-groups-for-user
list-groups
list-identity-providers
list-resource-servers
list-tags-for-resource
list-user-import-jobs
list-user-pool-clients
list-user-pools
list-users
list-users-in-group
add-custom-attributes
admin-add-user-to-group
admin-confirm-sign-up
admin-create-user
admin-delete-user
admin-delete-user-attributes
admin-disable-provider-for-user
admin-disable-user
admin-enable-user
admin-forget-device
admin-get-device
admin-get-user
admin-initiate-auth
admin-link-provider-for-user
admin-list-devices
admin-list-user-auth-events
admin-remove-user-from-group
admin-reset-user-password
admin-respond-to-auth-challenge
admin-set-user-mfa-preference
admin-set-user-settings
admin-update-auth-event-feedback
admin-update-device-status
admin-update-user-attributes
admin-user-global-sign-out
associate-software-token
change-password
confirm-device
confirm-forgot-password
confirm-sign-up
delete-group
delete-identity-provider
delete-resource-server
delete-user
delete-user-attributes
delete-user-pool
delete-user-pool-client
delete-user-pool-domain
describe-identity-provider
describe-resource-server
describe-risk-configuration
describe-user-import-job
describe-user-pool
describe-user-pool-client
describe-user-pool-domain
forget-device
forgot-password
get-csv-header
get-device
get-group
get-identity-provider-by-identifier
get-signing-certificate
get-ui-customization
get-user
get-user-attribute-verification-code
get-user-pool-mfa-config
global-sign-out
initiate-auth
list-devices
resend-confirmation-code
respond-to-auth-challenge
set-risk-configuration
set-ui-customization
set-user-mfa-preference
set-user-pool-mfa-config
set-user-settings
sign-up
start-user-import-job
stop-user-import-job
tag-resource
untag-resource
update-auth-event-feedback
update-device-status
update-group
update-identity-provider
update-resource-server
update-user-attributes
update-user-pool
update-user-pool-client
update-user-pool-domain
verify-software-token
verify-user-attribute
User Pool API:
Identity Pool API:
Following User Pool actions are supported ...
Following Identity Pool actions are supported ... :
CreateIdentityPool, DeleteIdentityPool, UpdateIdentityPool, DescribeIdentityPool
GetId, DeleteIdentities, DescribeIdentity, ListIdentities, ListIdentityPools
GetCredentialsForIdentity
SetIdentityPoolRoles, GetIdentityPoolRoles
GetOpenIdToken, GetOpenIdTokenForDeveloperIdentity
LookupDeveloperIdentity, MergeDeveloperIdentities
TagResource, ListTagsForResource, UntagResource
UnlinkIdentity, UnlinkDeveloperIdentity
And more User Pool and Identity Pool API ... :
AdminDeleteUserAttributes
AdminDisableProviderForUser
AdminDisableUser
AdminEnableUser
AdminForgetDevice
AdminGetDevice
AdminGetUser
AdminLinkProviderForUser
AdminListDevices
AdminListUserAuthEvents
AdminRespondToAuthChallenge
AdminSetUserMFAPreference
AdminSetUserSettings
AdminUpdateAuthEventFeedback
AdminUpdateDeviceStatus
ConfirmDevice
ConfirmForgotPassword
ConfirmSignUp
CreateResourceServer
CreateUserImportJob
DeleteIdentityProvider
DeleteResourceServer
DeleteUser
DeleteUserAttributes
DeleteUserPool
DeleteUserPoolClient
DeleteUserPoolDomain
DescribeIdentityProvider
DescribeResourceServer
DescribeRiskConfiguration
DescribeUserImportJob
DescribeUserPool
DescribeUserPoolClient
DescribeUserPoolDomain
ForgetDevice
ForgotPassword
GetCSVHeader
GetDevice
GetGroup
GetSigningCertificate
GetUICustomization
GetUserAttributeVerificationCode
GetUserPoolMfaConfig
GlobalSignOut
InitiateAuth
ListDevices
ListIdentityProviders
ListResourceServers
ListTagsForResource
ListUserImportJobs
ListUserPoolClients
ListUserPools
ResendConfirmationCode
RespondToAuthChallenge
SetRiskConfiguration
SetUICustomization
SetUserMFAPreference
SetUserPoolMfaConfig
SetUserSettings
SignUp
StartUserImportJob
StopUserImportJob
TagResource
UntagResource
UpdateAuthEventFeedback
UpdateDeviceStatus
UpdateIdentityProvider
UpdateResourceServer
UpdateUserAttributes
UpdateUserPool
UpdateUserPoolClient
UpdateUserPoolDomain
VerifySoftwareToken
VerifyUserAttribute
The signup event looks like below :
{
"version": "1",
"region": "ap-southeast-1",
"userPoolId": "ap-southeast-1_userPoolId",
"userName": "manhvu(=)orgos.net",
"callerContext": {
"awsSdkVersion": "aws-sdk-unknown-unknown",
"clientId": "1cf6c9pm555ku9phsblle7o0eu"
},
"triggerSource": "CustomMessage_SignUp",
"request": {
"userAttributes": {
"sub": "user-id-b6f2-19670da03c67",
"email_verified": "false",
"cognito:user_status": "UNCONFIRMED",
"email": "manh.vv.htth@gmail.com"
},
"codeParameter": "{####}",
"linkParameter": "{##Click Here##}",
"usernameParameter": null
},
"response": {
"smsMessage": null,
"emailMessage": null,
"emailSubject": null
}
}
A lambda custom trigger may look like below :
module.exports.handler = (event, context, callback) => {
// Identify why was this function invoked
// console.log('---- event object', JSON.stringify(event));
// console.log('---- context object', JSON.stringify(context));
const {
triggerSource
} = event;
if (triggerSource === 'CustomMessage_SignUp') {
const {
request: {
userAttributes
},
response
} = event;
if (userAttributes['cognito:user_status'] === 'UNCONFIRMED') {
const baseUrl = process.env.app__base_url;
const confirmationPath = process.env.app__confirmation_path;
const email = encodeURI(userAttributes.email);
const confimationUrl = `${baseUrl}${confirmationPath}?email=${email}&confirmationCode={####}`;
const emailMessage = `<h1> Hello ${email} </h1> <p> Here is activation link <a href="${confimationUrl}" target="_blank">Confirm your account</a> </p>`
response.emailMessage = emailMessage;
response.emailSubject = 'Confirm your CryptoBadge account';
}
}
callback(null, event);
};
Note: The context has details such as cognito identity of the request. See https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html
Context Properties :
functionName – The name of the Lambda function.
memoryLimitInMB – The amount of memory configured on the function.
...
identity – (mobile apps) Information about the Amazon Cognito identity
cognitoIdentityId – The authenticated Amazon Cognito identity.
cognitoIdentityPoolId – Cognito identity pool that authorized the invocation.
clientContext – (mobile apps) Client context
client.app_title
client.app_version_name
...
aws cognito-idp create-user-pool --pool-name myblog
aws cognito-idp list-user-pools --max-results 10
{
"UserPools": [
{
"Id": "us-east-1_0Pe*****",
"Name": "myblog",
"LambdaConfig": {},
"LastModifiedDate": 1527786443.052,
"CreationDate": 1527786443.052
}
]
}
// The Id of the user pool is very important, we need it for reference.
// Note that user pool name is not unique across users, but Id is unique.
// Create a Resource Server
aws> cognito-idp create-resource-server
--name transactions --identifier transactions
--user-pool-id us-east-1_0Pe*****
--scopes ScopeName=get,ScopeDescription=get_tx
ScopeName=post,ScopeDescription=post_tx
{
"ResourceServer": {
"UserPoolId": "us-east-1_0Pe*****",
"Identifier": "transactions",
"Name": "transactions",
"Scopes": [
{
"ScopeName": "post",
"ScopeDescription": "post_tx"
},
{
"ScopeName": "get",
"ScopeDescription": "get_tx"
}
]
}
}
// Create a Client App
aws> cognito-idp create-user-pool-client --user-pool-id us-east-1_0Pe*****
--allowed-o-auth-flows client_credentials --client-name test --generate-secret
--allowed-o-auth-scopes transactions/post
--allowed-o-auth-flows-user-pool-client
{
"UserPoolClient": {
"UserPoolId": "us-east-1_0Pe*****",
"ClientName": "test",
"ClientId": "14aq5ll5b1it6f62uefe******",
"ClientSecret": "j22a2ha9httcbord******e4k29ra7s8026agrc89nhjg******",
"LastModifiedDate": 1527806667.264,
"CreationDate": 1527806667.264,
"RefreshTokenValidity": 30,
"AllowedOAuthFlows": [
"client_credentials"
],
"AllowedOAuthScopes": [
"transactions/post"
],
"AllowedOAuthFlowsUserPoolClient": true
}
}
// Note the ClientId and ClientSecret in the response
// we’d need this to request an access token.
// Add a Domain so we can get a URL for /oauth2/token endpoint.
aws> cognito-idp create-user-pool-domain --domain lobster1234 --user-pool-id
us-east-1_0Pe*****
{
"DomainDescription": {
"UserPoolId": "us-east-1_0Pe*****",
"AWSAccountId": "***431494***",
"Domain": "lobster1234",
"S3Bucket": "aws-cognito-prod-iad-assets",
"CloudFrontDistribution": "d3oia8etllorh5.cloudfront.net",
"Version": "20180531225618",
"Status": "ACTIVE"
}
}
// OAuth2 URL is https://lobster1234.auth.us-east-1.amazoncognito.com/oauth2/token
// Get an Access Token
// Notice that I am using HTTP Basic to send the client_id and client_secret.
// This is base64(ClientId:ClientSecret).
$ AUTH_HEADER=$(echo -n 'ClientId:ClientSecret' | openssl base64)
$ curl -X POST \
https://lobster1234.auth.us-east-1.amazoncognito.com/oauth2/token \
-H 'authorization: Basic ********' \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&scope=transactions%2Fpost'
// This should return an access_token, which is a JWT.
{
"access_token": "******************.eyJzdWIiO",
"expires_in": 3600,
"token_type": "Bearer"
}