diff --git a/amplify/backend/auth/lunchruna5e025e4/lunchruna5e025e4-cloudformation-template.yml b/amplify/backend/auth/lunchruna5e025e4/lunchruna5e025e4-cloudformation-template.yml new file mode 100644 index 0000000..d5050e9 --- /dev/null +++ b/amplify/backend/auth/lunchruna5e025e4/lunchruna5e025e4-cloudformation-template.yml @@ -0,0 +1,367 @@ +AWSTemplateFormatVersion: 2010-09-09 + +Parameters: + env: + Type: String + authRoleArn: + Type: String + unauthRoleArn: + Type: String + + + + + identityPoolName: + Type: String + + allowUnauthenticatedIdentities: + Type: String + + resourceNameTruncated: + Type: String + + userPoolName: + Type: String + + autoVerifiedAttributes: + Type: CommaDelimitedList + + mfaConfiguration: + Type: String + + mfaTypes: + Type: CommaDelimitedList + + smsAuthenticationMessage: + Type: String + + smsVerificationMessage: + Type: String + + emailVerificationSubject: + Type: String + + emailVerificationMessage: + Type: String + + defaultPasswordPolicy: + Type: String + + passwordPolicyMinLength: + Type: Number + + passwordPolicyCharacters: + Type: CommaDelimitedList + + requiredAttributes: + Type: CommaDelimitedList + + userpoolClientGenerateSecret: + Type: String + + userpoolClientRefreshTokenValidity: + Type: Number + + userpoolClientWriteAttributes: + Type: CommaDelimitedList + + userpoolClientReadAttributes: + Type: CommaDelimitedList + + userpoolClientLambdaRole: + Type: String + + userpoolClientSetAttributes: + Type: String + + sharedId: + Type: String + + resourceName: + Type: String + + authSelections: + Type: String + + useDefault: + Type: String + + userPoolGroupList: + Type: CommaDelimitedList + + dependsOn: + Type: CommaDelimitedList + +Conditions: + ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ] + +Resources: + + + # BEGIN SNS ROLE RESOURCE + SNSRole: + # Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process + Type: AWS::IAM::Role + Properties: + RoleName: !If [ShouldNotCreateEnvResources, 'lunchra5e025e4_sns-role', !Join ['',[ 'sns', 'a5e025e4', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Sid: "" + Effect: "Allow" + Principal: + Service: "cognito-idp.amazonaws.com" + Action: + - "sts:AssumeRole" + Condition: + StringEquals: + sts:ExternalId: lunchra5e025e4_role_external_id + Policies: + - + PolicyName: lunchra5e025e4-sns-policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - + Effect: "Allow" + Action: + - "sns:Publish" + Resource: "*" + # BEGIN USER POOL RESOURCES + UserPool: + # Created upon user selection + # Depends on SNS Role for Arn if MFA is enabled + Type: AWS::Cognito::UserPool + UpdateReplacePolicy: Retain + Properties: + UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]] + + Schema: + + - + Name: email + Required: true + Mutable: true + + + + + AutoVerifiedAttributes: !Ref autoVerifiedAttributes + + + EmailVerificationMessage: !Ref emailVerificationMessage + EmailVerificationSubject: !Ref emailVerificationSubject + + Policies: + PasswordPolicy: + MinimumLength: !Ref passwordPolicyMinLength + RequireLowercase: false + RequireNumbers: false + RequireSymbols: false + RequireUppercase: false + + MfaConfiguration: !Ref mfaConfiguration + SmsVerificationMessage: !Ref smsVerificationMessage + SmsConfiguration: + SnsCallerArn: !GetAtt SNSRole.Arn + ExternalId: lunchra5e025e4_role_external_id + + + UserPoolClientWeb: + # Created provide application access to user pool + # Depends on UserPool for ID reference + Type: "AWS::Cognito::UserPoolClient" + Properties: + ClientName: lunchra5e025e4_app_clientWeb + + RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity + UserPoolId: !Ref UserPool + DependsOn: UserPool + UserPoolClient: + # Created provide application access to user pool + # Depends on UserPool for ID reference + Type: "AWS::Cognito::UserPoolClient" + Properties: + ClientName: lunchra5e025e4_app_client + + GenerateSecret: !Ref userpoolClientGenerateSecret + RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity + UserPoolId: !Ref UserPool + DependsOn: UserPool + # BEGIN USER POOL LAMBDA RESOURCES + UserPoolClientRole: + # Created to execute Lambda which gets userpool app client config values + Type: 'AWS::IAM::Role' + Properties: + RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',['upClientLambdaRole', 'a5e025e4', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - 'sts:AssumeRole' + DependsOn: UserPoolClient + UserPoolClientLambda: + # Lambda which gets userpool app client config values + # Depends on UserPool for id + # Depends on UserPoolClientRole for role ARN + Type: 'AWS::Lambda::Function' + Properties: + Code: + ZipFile: !Join + - |+ + - - 'const response = require(''cfn-response'');' + - 'const aws = require(''aws-sdk'');' + - 'const identity = new aws.CognitoIdentityServiceProvider();' + - 'exports.handler = (event, context, callback) => {' + - ' if (event.RequestType == ''Delete'') { ' + - ' response.send(event, context, response.SUCCESS, {})' + - ' }' + - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' + - ' const params = {' + - ' ClientId: event.ResourceProperties.clientId,' + - ' UserPoolId: event.ResourceProperties.userpoolId' + - ' };' + - ' identity.describeUserPoolClient(params).promise()' + - ' .then((res) => {' + - ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});' + - ' })' + - ' .catch((err) => {' + - ' response.send(event, context, response.FAILED, {err});' + - ' });' + - ' }' + - '};' + Handler: index.handler + Runtime: nodejs10.x + Timeout: '300' + Role: !GetAtt + - UserPoolClientRole + - Arn + DependsOn: UserPoolClientRole + UserPoolClientLambdaPolicy: + # Sets userpool policy for the role that executes the Userpool Client Lambda + # Depends on UserPool for Arn + # Marked as depending on UserPoolClientRole for easier to understand CFN sequencing + Type: 'AWS::IAM::Policy' + Properties: + PolicyName: lunchra5e025e4_userpoolclient_lambda_iam_policy + Roles: + - !Ref UserPoolClientRole + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - 'cognito-idp:DescribeUserPoolClient' + Resource: !GetAtt UserPool.Arn + DependsOn: UserPoolClientLambda + UserPoolClientLogPolicy: + # Sets log policy for the role that executes the Userpool Client Lambda + # Depends on UserPool for Arn + # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing + Type: 'AWS::IAM::Policy' + Properties: + PolicyName: lunchra5e025e4_userpoolclient_lambda_log_policy + Roles: + - !Ref UserPoolClientRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - 'logs:CreateLogGroup' + - 'logs:CreateLogStream' + - 'logs:PutLogEvents' + Resource: !Sub + - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* + - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda} + DependsOn: UserPoolClientLambdaPolicy + UserPoolClientInputs: + # Values passed to Userpool client Lambda + # Depends on UserPool for Id + # Depends on UserPoolClient for Id + # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing + Type: 'Custom::LambdaCallout' + Properties: + ServiceToken: !GetAtt UserPoolClientLambda.Arn + clientId: !Ref UserPoolClient + userpoolId: !Ref UserPool + DependsOn: UserPoolClientLogPolicy + + + + + + + + # BEGIN IDENTITY POOL RESOURCES + + + IdentityPool: + # Always created + Type: AWS::Cognito::IdentityPool + Properties: + IdentityPoolName: !If [ShouldNotCreateEnvResources, 'lunchruna5e025e4_identitypool_a5e025e4', !Join ['',['lunchruna5e025e4_identitypool_a5e025e4', '__', !Ref env]]] + + CognitoIdentityProviders: + - ClientId: !Ref UserPoolClient + ProviderName: !Sub + - cognito-idp.${region}.amazonaws.com/${client} + - { region: !Ref "AWS::Region", client: !Ref UserPool} + - ClientId: !Ref UserPoolClientWeb + ProviderName: !Sub + - cognito-idp.${region}.amazonaws.com/${client} + - { region: !Ref "AWS::Region", client: !Ref UserPool} + + AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities + + + DependsOn: UserPoolClientInputs + + + IdentityPoolRoleMap: + # Created to map Auth and Unauth roles to the identity pool + # Depends on Identity Pool for ID ref + Type: AWS::Cognito::IdentityPoolRoleAttachment + Properties: + IdentityPoolId: !Ref IdentityPool + Roles: + unauthenticated: !Ref unauthRoleArn + authenticated: !Ref authRoleArn + DependsOn: IdentityPool + + +Outputs : + + IdentityPoolId: + Value: !Ref 'IdentityPool' + Description: Id for the identity pool + IdentityPoolName: + Value: !GetAtt IdentityPool.Name + + + + + UserPoolId: + Value: !Ref 'UserPool' + Description: Id for the user pool + UserPoolName: + Value: !Ref userPoolName + AppClientIDWeb: + Value: !Ref 'UserPoolClientWeb' + Description: The user pool app client id for web + AppClientID: + Value: !Ref 'UserPoolClient' + Description: The user pool app client id + AppClientSecret: + Value: !GetAtt UserPoolClientInputs.appSecret + + + + + + + diff --git a/amplify/backend/auth/lunchruna5e025e4/parameters.json b/amplify/backend/auth/lunchruna5e025e4/parameters.json new file mode 100644 index 0000000..74a18ba --- /dev/null +++ b/amplify/backend/auth/lunchruna5e025e4/parameters.json @@ -0,0 +1,51 @@ +{ + "identityPoolName": "lunchruna5e025e4_identitypool_a5e025e4", + "allowUnauthenticatedIdentities": false, + "resourceNameTruncated": "lunchra5e025e4", + "userPoolName": "lunchruna5e025e4_userpool_a5e025e4", + "autoVerifiedAttributes": [ + "email" + ], + "mfaConfiguration": "OFF", + "mfaTypes": [ + "SMS Text Message" + ], + "smsAuthenticationMessage": "Your authentication code is {####}", + "smsVerificationMessage": "Your verification code is {####}", + "emailVerificationSubject": "Your verification code", + "emailVerificationMessage": "Your verification code is {####}", + "defaultPasswordPolicy": false, + "passwordPolicyMinLength": 8, + "passwordPolicyCharacters": [], + "requiredAttributes": [ + "email" + ], + "userpoolClientGenerateSecret": true, + "userpoolClientRefreshTokenValidity": 30, + "userpoolClientWriteAttributes": [ + "email" + ], + "userpoolClientReadAttributes": [ + "email" + ], + "userpoolClientLambdaRole": "lunchra5e025e4_userpoolclient_lambda_role", + "userpoolClientSetAttributes": false, + "sharedId": "a5e025e4", + "resourceName": "lunchruna5e025e4", + "authSelections": "identityPoolAndUserPool", + "authRoleArn": { + "Fn::GetAtt": [ + "AuthRole", + "Arn" + ] + }, + "unauthRoleArn": { + "Fn::GetAtt": [ + "UnauthRole", + "Arn" + ] + }, + "useDefault": "default", + "userPoolGroupList": [], + "dependsOn": [] +} \ No newline at end of file diff --git a/amplify/backend/backend-config.json b/amplify/backend/backend-config.json index b7c2fce..1621796 100644 --- a/amplify/backend/backend-config.json +++ b/amplify/backend/backend-config.json @@ -1,20 +1,35 @@ { - "api": { - "lunchrun": { - "service": "AppSync", - "providerPlugin": "awscloudformation", - "output": { - "authConfig": { - "additionalAuthenticationProviders": [], - "defaultAuthentication": { - "authenticationType": "API_KEY", - "apiKeyConfig": { - "description": "lunchrunapikey", - "apiKeyExpirationDays": 7 - } - } - } - } - } - } + "api": { + "lunchrun": { + "service": "AppSync", + "providerPlugin": "awscloudformation", + "output": { + "authConfig": { + "additionalAuthenticationProviders": [], + "defaultAuthentication": { + "authenticationType": "API_KEY", + "apiKeyConfig": { + "description": "lunchrunapikey", + "apiKeyExpirationDays": 7 + } + } + } + } + } + }, + "auth": { + "lunchruna5e025e4": { + "service": "Cognito", + "providerPlugin": "awscloudformation", + "dependsOn": [], + "customAuth": false + } + }, + "hosting": { + "amplifyhosting": { + "service": "amplifyhosting", + "providerPlugin": "awscloudformation", + "type": "manual" + } + } } \ No newline at end of file diff --git a/amplify/backend/hosting/amplifyhosting/amplifyhosting-template.json b/amplify/backend/hosting/amplifyhosting/amplifyhosting-template.json new file mode 100644 index 0000000..27f1afd --- /dev/null +++ b/amplify/backend/hosting/amplifyhosting/amplifyhosting-template.json @@ -0,0 +1,39 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Branch stack creation for AWS Amplify Console", + "Parameters": { + "env": { + "Type": "String" + }, + "appId": { + "Type": "String" + }, + "type": { + "Type": "String" + } + }, + "Conditions": { + "isManual": { + "Fn::Equals": [ + { + "Ref": "type" + }, + "manual" + ] + } + }, + "Resources": { + "AmplifyBranch": { + "Condition": "isManual", + "Type": "AWS::Amplify::Branch", + "Properties": { + "BranchName": { + "Ref": "env" + }, + "AppId": { + "Ref": "appId" + } + } + } + } +} \ No newline at end of file diff --git a/amplify/team-provider-info.json b/amplify/team-provider-info.json index 7419a71..cc79419 100644 --- a/amplify/team-provider-info.json +++ b/amplify/team-provider-info.json @@ -10,6 +10,17 @@ "StackName": "amplify-lunchrun-dev-150502", "StackId": "arn:aws:cloudformation:us-east-1:358068280668:stack/amplify-lunchrun-dev-150502/ddc76030-9df9-11ea-be2d-0a726edfb5e3", "AmplifyAppId": "d69tbu39wvryc" + }, + "categories": { + "auth": { + "lunchruna5e025e4": {} + }, + "hosting": { + "amplifyhosting": { + "appId": "d69tbu39wvryc", + "type": "manual" + } + } } } } \ No newline at end of file diff --git a/src/App.js b/src/App.js index 4b87c0a..65c674d 100644 --- a/src/App.js +++ b/src/App.js @@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react' import { API, graphqlOperation } from 'aws-amplify' import { createTodo } from './graphql/mutations' import { listTodos } from './graphql/queries' +import { withAuthenticator } from '@aws-amplify/ui-react' const initialState = { name: '', description: '' } @@ -75,4 +76,4 @@ const styles = { button: { backgroundColor: 'black', color: 'white', outline: 'none', fontSize: 18, padding: '12px 0px' } } -export default App \ No newline at end of file +export default withAuthenticator(App) \ No newline at end of file