Cognito emulator for tests

Run AWS Cognito User Pools locally for integration tests with fakecloud. 122 operations, full auth flows (USER_PASSWORD_AUTH, USER_SRP_AUTH, CUSTOM_AUTH), MFA, identity providers, triggers.

Need a Cognito emulator for integration tests? Use fakecloud. Not a mock library — a real server that speaks the Cognito wire protocol.

curl -fsSL https://raw.githubusercontent.com/faiscadev/fakecloud/main/install.sh | bash
fakecloud

Point your AWS SDK at http://localhost:4566.

Why fakecloud for Cognito

Create a user pool

import boto3
cog = boto3.client('cognito-idp',
    endpoint_url='http://localhost:4566',
    aws_access_key_id='test',
    aws_secret_access_key='test',
    region_name='us-east-1')

pool = cog.create_user_pool(PoolName='my-pool', AutoVerifiedAttributes=['email'])
client = cog.create_user_pool_client(
    UserPoolId=pool['UserPool']['Id'],
    ClientName='web',
    ExplicitAuthFlows=['ALLOW_USER_PASSWORD_AUTH', 'ALLOW_REFRESH_TOKEN_AUTH'])

Sign up + confirm + authenticate

# Sign up
cog.sign_up(
    ClientId=client['UserPoolClient']['ClientId'],
    Username='alice@example.com',
    Password='Str0ng!Passw0rd',
    UserAttributes=[{'Name': 'email', 'Value': 'alice@example.com'}])

# Fetch the confirmation code from the test introspection endpoint
import requests
codes = requests.get('http://localhost:4566/_fakecloud/cognito/confirmation-codes').json()
code = codes['codes'][0]['code']

cog.confirm_sign_up(
    ClientId=client['UserPoolClient']['ClientId'],
    Username='alice@example.com',
    ConfirmationCode=code)

# Authenticate
auth = cog.initiate_auth(
    ClientId=client['UserPoolClient']['ClientId'],
    AuthFlow='USER_PASSWORD_AUTH',
    AuthParameters={'USERNAME': 'alice@example.com', 'PASSWORD': 'Str0ng!Passw0rd'})

# auth['AuthenticationResult'] has real AccessToken, IdToken, RefreshToken

The tokens are real signed JWTs — your application's JWT verification (with jwks_uri pointing at the fakecloud public key endpoint) works unchanged.

SRP authentication

# USER_SRP_AUTH — real SRP handshake, same as AWS
auth = cog.initiate_auth(
    ClientId=client['UserPoolClient']['ClientId'],
    AuthFlow='USER_SRP_AUTH',
    AuthParameters={'USERNAME': 'alice@example.com', 'SRP_A': '<srp-A value>'})

# Returns SRP_B + challenge params
# Client responds with PASSWORD_VERIFIER challenge
auth2 = cog.respond_to_auth_challenge(
    ClientId=client['UserPoolClient']['ClientId'],
    ChallengeName='PASSWORD_VERIFIER',
    ChallengeResponses={
        'USERNAME': 'alice@example.com',
        'PASSWORD_CLAIM_SIGNATURE': '<signature>',
        'PASSWORD_CLAIM_SECRET_BLOCK': auth['ChallengeParameters']['SECRET_BLOCK'],
        'TIMESTAMP': '<timestamp>',
    })

Real crypto — same SRP-6a parameters AWS uses.

MFA

TOTP and SMS MFA. Verification codes readable from /_fakecloud/cognito/confirmation-codes with type filter.

Triggers (Lambda)

cog.update_user_pool(
    UserPoolId=pool['UserPool']['Id'],
    LambdaConfig={
        'PreSignUp': 'arn:aws:lambda:us-east-1:000000000000:function:pre-signup',
        'PostConfirmation': 'arn:aws:lambda:us-east-1:000000000000:function:post-confirmation',
        'PreTokenGeneration': 'arn:aws:lambda:us-east-1:000000000000:function:pre-token',
    })

Triggers invoke your Lambda with the Cognito event shape. Not stubbed — the function runs in a real runtime container.

Assertions

import { FakeCloud } from 'fakecloud';
const fc = new FakeCloud();

// Alice just signed up
const { codes } = await fc.cognito.getConfirmationCodes({ username: 'alice@example.com' });
expect(codes).toHaveLength(1);

// Your app should have called the pre-signup Lambda
const { invocations } = await fc.lambda.getInvocations({ functionName: 'pre-signup' });
expect(invocations).toHaveLength(1);

How it differs from alternatives

ToolMulti-languageFull SRPReal JWT signingTriggers executePrice
fakecloudAnyYesYesYes (real Lambda runs)Free
LocalStack CommunityAnyPaid only (post Mar 2026)
cognito-localNode onlyPartialYesNoFree
Moto (mock_cognitoidp)Python onlyStubbedStubbedStubbedFree