Skip to content

Instantly share code, notes, and snippets.

@wolfeidau
Last active January 28, 2020 04:22
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wolfeidau/70531fc1a593c0bad7fb9ebc9ae82580 to your computer and use it in GitHub Desktop.
Save wolfeidau/70531fc1a593c0bad7fb9ebc9ae82580 to your computer and use it in GitHub Desktop.
Cognito CFN stack with domain verification
AWSTemplateFormatVersion: 2010-09-09
Description: 'authentication: Resources for hosting authentication using AWS Cognito, a @wolfeidau template'
Parameters:
AppName:
Description: Name of application, used in signup emails and naming of aws resources.
Type: String
AllowedPattern: '^[a-zA-Z0-9]*$'
Environment:
Description: Suffix to be added to the pool name.
Type: String
Default: dev
AllowedValues: [ dev, tst, prd ]
WhitelistDomain:
Description: Accept cognito signups from this domain, and reject all others.
Type: String
Resources:
CognitoUserPool:
Type: "AWS::Cognito::UserPool"
Properties:
UserPoolName: !Sub ${AppName}_UserPool_${Environment}
LambdaConfig:
PreSignUp: !GetAtt PreSignupLambdaFunction.Arn
UsernameAttributes:
- email
AutoVerifiedAttributes:
- email
Schema:
- Name: name
AttributeDataType: String
Mutable: true
Required: true
- Name: email
AttributeDataType: String
Mutable: false
Required: true
EmailVerificationSubject: !Sub "Welcome to ${AppName}"
EmailVerificationMessage: !Sub "${AppName} says: Your activation code is {####}"
CognitoUserSPAClient:
Type: "AWS::Cognito::UserPoolClient"
Properties:
ClientName: !Sub ${AppName}UserSPAClient${Environment}
GenerateSecret: False
RefreshTokenValidity: 30
UserPoolId: !Ref CognitoUserPool
CognitoIdentityPool:
Type: "AWS::Cognito::IdentityPool"
Properties:
IdentityPoolName: !Sub ${AppName}IdentityPool${Environment}
AllowUnauthenticatedIdentities: False
CognitoIdentityProviders:
- ClientId: !Ref CognitoUserSPAClient
ProviderName: !GetAtt CognitoUserPool.ProviderName
CognitoUnauthRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: !Sub Cognito_${CognitoIdentityPool.Name}_Unauth_Role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Federated: cognito-identity.amazonaws.com
Action: [ 'sts:AssumeRoleWithWebIdentity' ]
Condition:
StringEquals:
cognito-identity.amazonaws.com:aud: !Ref CognitoIdentityPool
ForAnyValue:StringLike:
cognito-identity.amazonaws.com:amr: unauthenticated
Policies:
- PolicyName: CognitoUnauthorizedPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- mobileanalytics:PutEvents
- cognito-sync:*
Resource:
- "*"
CognitoAuthRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: !Sub Cognito_${CognitoIdentityPool.Name}_Auth_Role
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Federated: cognito-identity.amazonaws.com
Action: [ 'sts:AssumeRoleWithWebIdentity' ]
Condition:
StringEquals:
cognito-identity.amazonaws.com:aud: !Ref CognitoIdentityPool
ForAnyValue:StringLike:
cognito-identity.amazonaws.com:amr: authenticated
Policies:
- PolicyName: CognitoAuthorizedPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- mobileanalytics:PutEvents
- cognito-sync:*
Resource:
- "*"
IdentityPoolRoleAttachment:
DependsOn: [ CognitoIdentityPool, CognitoUnauthRole, CognitoAuthRole ]
Type: "AWS::Cognito::IdentityPoolRoleAttachment"
Properties:
IdentityPoolId: !Ref CognitoIdentityPool
Roles:
authenticated: !GetAtt CognitoAuthRole.Arn
unauthenticated: !GetAtt CognitoUnauthRole.Arn
PreSignupLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess
PreSignupLambdaFunction:
Type: "AWS::Lambda::Function"
Properties:
Handler: "index.handler"
Role:
Fn::GetAtt: PreSignupLambdaRole.Arn
Code:
ZipFile: |
exports.handler = (event, context, callback) => {
// Set the user pool autoConfirmUser flag after validating the email domain
event.response.autoConfirmUser = false;
// Split the email address so we can compare domains
const address = event.request.userAttributes.email.split("@")
// This tells Amazon Cognito to permit signup
if (address[1] === process.env.WHITELIST_DOMAIN) {
return callback(null, event);
}
// Return error to Amazon Cognito
callback("invalid email domain");
};
Runtime: "nodejs10.x"
Timeout: 30
Environment:
Variables:
WHITELIST_DOMAIN: !Ref WhitelistDomain
CognitoPreSignupLambaPermission:
Type: "AWS::Lambda::Permission"
Properties:
Action: "lambda:InvokeFunction"
FunctionName: !Ref PreSignupLambdaFunction
Principal: "cognito-idp.amazonaws.com"
SourceArn: !Sub "arn:aws:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/${CognitoUserPool}"
Outputs:
CognitoUserPool:
Description: "User pool ID"
Value: !Ref CognitoUserPool
CognitoIdentityPool:
Description: "Identity pool ID"
Value: !Ref CognitoIdentityPool
CognitoUserSPAClientId:
Description: "Client ID for the SPA client"
Value: !Ref CognitoUserSPAClient
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment