-
Navigate to AWS Console > Cognito > User Pools
-
Click "Create user pool"
-
Configure sign-in experience:
- Enable email and username sign-in
- Enable self-service account recovery
- Set password policy (minimum 8 characters, require numbers and special characters)
-
Configure security requirements:
- Enable MFA (Optional)
- Set account recovery method (Email)
-
Configure sign-up experience:
- Required attributes: email, name
- Custom attributes (if needed):
- role (string)
- organization (string)
-
Configure message delivery:
- Use Cognito defaults for email
- Customize email templates if needed
-
Integrate your app:
- Create app client
- Disable client secret generation
- Configure OAuth settings:
{
"AllowedOAuthFlows": ["implicit"],
"AllowedOAuthScopes": ["email", "openid", "profile"],
"CallbackURLs": ["https://your-domain.com/callback"],
"LogoutURLs": ["https://your-domain.com"]
}Install required dependencies:
npm install aws-amplify @aws-amplify/ui-reactCreate authentication configuration (src/auth/cognito-config.js):
export const cognitoConfig = {
Auth: {
region: process.env.REACT_APP_AWS_REGION,
userPoolId: process.env.REACT_APP_COGNITO_USER_POOL_ID,
userPoolWebClientId: process.env.REACT_APP_COGNITO_CLIENT_ID,
mandatorySignIn: true,
signUpVerificationMethod: 'code',
oauth: {
domain: `${process.env.REACT_APP_COGNITO_DOMAIN}.auth.${process.env.REACT_APP_AWS_REGION}.amazoncognito.com`,
scope: ['email', 'profile', 'openid'],
redirectSignIn: process.env.REACT_APP_REDIRECT_SIGN_IN,
redirectSignOut: process.env.REACT_APP_REDIRECT_SIGN_OUT,
responseType: 'token'
}
}
};Create authentication service (src/auth/auth-service.js):
import { Auth } from 'aws-amplify';
export class AuthService {
static async signIn(username, password) {
try {
const user = await Auth.signIn(username, password);
return {
success: true,
user: user
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
static async signUp(username, password, email, name) {
try {
const { user } = await Auth.signUp({
username,
password,
attributes: {
email,
name
}
});
return {
success: true,
user: user
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
static async getCurrentSession() {
try {
const session = await Auth.currentSession();
return {
success: true,
session: session
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
}- Create S3 bucket:
aws s3api create-bucket \
--bucket your-app-frontend \
--region us-east-1- Enable static website hosting:
aws s3api put-bucket-website \
--bucket your-app-frontend \
--website-configuration file://website-config.jsonwebsite-config.json:
{
"IndexDocument": {
"Suffix": "index.html"
},
"ErrorDocument": {
"Key": "index.html"
}
}- Bucket policy for public access:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-app-frontend/*"
}
]
}- Create distribution:
aws cloudfront create-distribution \
--origin-domain-name your-app-frontend.s3.amazonaws.com \
--default-root-object index.html- Configure distribution settings:
{
"DistributionConfig": {
"Origins": {
"Items": [
{
"Id": "S3-your-app-frontend",
"DomainName": "your-app-frontend.s3.amazonaws.com",
"S3OriginConfig": {
"OriginAccessIdentity": ""
}
}
],
"Quantity": 1
},
"DefaultCacheBehavior": {
"TargetOriginId": "S3-your-app-frontend",
"ForwardedValues": {
"QueryString": false,
"Cookies": {
"Forward": "none"
}
},
"ViewerProtocolPolicy": "redirect-to-https",
"MinTTL": 0,
"DefaultTTL": 86400,
"MaxTTL": 31536000
},
"Enabled": true
}
}- Create REST API:
aws apigateway create-rest-api \
--name "YourAppAPI" \
--description "API for Your App" \
--endpoint-configuration types=REGIONAL- Create resource and method:
aws apigateway create-resource \
--rest-api-id YOUR_API_ID \
--parent-id YOUR_PARENT_ID \
--path-part "users"
aws apigateway put-method \
--rest-api-id YOUR_API_ID \
--resource-id YOUR_RESOURCE_ID \
--http-method POST \
--authorization-type COGNITO_USER_POOLS \
--authorizer-id YOUR_AUTHORIZER_ID- Create IAM role for Lambda:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"rds:*"
],
"Resource": "arn:aws:rds:region:account-id:db:*"
}
]
}- Create Lambda function:
const mysql = require('mysql2/promise');
const AWS = require('aws-sdk');
const secrets = new AWS.SecretsManager();
let connection = null;
async function getDBCredentials() {
const data = await secrets.getSecretValue({
SecretId: process.env.DB_SECRETS_ARN
}).promise();
return JSON.parse(data.SecretString);
}
async function getConnection() {
if (connection) return connection;
const credentials = await getDBCredentials();
connection = await mysql.createConnection({
host: credentials.host,
user: credentials.username,
password: credentials.password,
database: credentials.dbname
});
return connection;
}
exports.handler = async (event) => {
try {
const conn = await getConnection();
const [rows] = await conn.execute('SELECT * FROM users');
return {
statusCode: 200,
body: JSON.stringify(rows),
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
};
} catch (error) {
return {
statusCode: 500,
body: JSON.stringify({ error: error.message }),
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
};
}
};- Create parameter group:
aws rds create-db-parameter-group \
--db-parameter-group-name your-app-params \
--db-parameter-group-family mysql8.0 \
--description "Parameters for Your App"- Create RDS instance:
aws rds create-db-instance \
--db-instance-identifier your-app-db \
--db-instance-class db.t3.micro \
--engine mysql \
--master-username admin \
--master-user-password YOUR_PASSWORD \
--allocated-storage 20 \
--db-parameter-group-name your-app-params{
"GroupName": "rds-security-group",
"Description": "Security group for RDS",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 3306,
"ToPort": 3306,
"IpRanges": [
{
"CidrIp": "YOUR_VPC_CIDR",
"Description": "Allow MySQL access from VPC"
}
]
}
]
}- Lambda Error Rate Alarm:
aws cloudwatch put-metric-alarm \
--alarm-name lambda-errors \
--alarm-description "Lambda error rate > 1%" \
--metric-name Errors \
--namespace AWS/Lambda \
--statistic Sum \
--period 300 \
--threshold 1 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 2 \
--alarm-actions YOUR_SNS_TOPIC_ARN- API Gateway Latency Alarm:
aws cloudwatch put-metric-alarm \
--alarm-name api-latency \
--alarm-description "API Gateway latency > 1000ms" \
--metric-name Latency \
--namespace AWS/ApiGateway \
--statistic Average \
--period 300 \
--threshold 1000 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 2 \
--alarm-actions YOUR_SNS_TOPIC_ARN