Amplify.config() reads Auth.Cognito.loginWith hash as ordered and creates signup failure
Before opening, please confirm:
- [x] I have searched for duplicate or closed issues and discussions.
- [x] I have read the guide for submitting bug reports.
- [x] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
React
Amplify APIs
Not applicable
Amplify Version
v6
Amplify Categories
auth
Backend
Other
Environment information
# Put output below this line
System:
OS: macOS 15.5
CPU: (8) arm64 Apple M1
Memory: 82.66 MB / 16.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 25.2.1 - /opt/homebrew/bin/node
npm: 11.6.2 - /opt/homebrew/bin/npm
Browsers:
Chrome: 142.0.7444.176
Safari: 18.5
npmPackages:
%name%: 0.1.0
@aws-cdk/aws-apigateway: ^1.203.0 => 1.203.0
@aws-cdk/aws-cloudfront: ^1.203.0 => 1.203.0
@aws-cdk/aws-cloudfront-origins: ^1.203.0 => 1.203.0
@aws-cdk/aws-cognito: ^1.203.0 => 1.203.0
@aws-cdk/aws-dynamodb: ^1.203.0 => 1.203.0
@aws-cdk/aws-iam: ^1.203.0 => 1.203.0
@aws-cdk/aws-lambda: ^1.203.0 => 1.203.0
@aws-cdk/aws-lambda-python-alpha: ^2.225.0-alpha.0 => 2.225.0-alpha.0
@aws-cdk/aws-s3: ^1.203.0 => 1.203.0
@aws-cdk/aws-s3-deployment: ^1.203.0 => 1.203.0
@types/jest: ^29.5.14 => 29.5.14
@types/node: 22.7.9 => 22.7.9
aws-cdk: 2.1032.0 => 2.1032.0
aws-cdk-lib: ^2.225.0 => 2.225.0
constructs: ^10.0.0 => 10.4.3 (3.4.344)
jest: ^29.7.0 => 29.7.0
ts-jest: ^29.2.5 => 29.4.5
ts-node: ^10.9.2 => 10.9.2
typescript: ~5.9.3 => 5.9.3
npmGlobalPackages:
aws-cdk: 2.1032.0
npm-check-updates: 17.1.13
npm: 11.6.2
vite: 6.0.7
Describe the bug
I am trying to use the Amplify Gen 2 react libraries to authenticate with cognito but without using Amplify hosting. I want the userpool to allow self-signup with username and email.
To that end I am deploying a cognito user pool with CDK
//
// Cognito User Pool
//
const userPool = new cognito.UserPool(this, 'MyUserPool', {
selfSignUpEnabled: true,
// Users must provide a username + email
signInAliases: {
username: true,
email: true,
},
autoVerify: {
email: true,
},
standardAttributes: {
email: {
required: true,
mutable: false,
},
},
passwordPolicy: {
minLength: 8,
requireDigits: true,
requireLowercase: true,
requireUppercase: true,
requireSymbols: false,
},
accountRecovery: cognito.AccountRecovery.EMAIL_ONLY,
email: cognito.UserPoolEmail.withCognito(),
deletionProtection: false, // set to true for production environments
removalPolicy: cdk.RemovalPolicy.DESTROY, // set to RETAIN for production environments
});
const userPoolClient = new cognito.UserPoolClient(this, "UserPoolClient", {
userPool,
generateSecret: false,
authFlows: { userPassword: true, userSrp: true },
preventUserExistenceErrors: true,
});
and connecting to it by following the Use existing Cognito resources documentation and additional inputs from google/ChatGPT.
The following combination fails account creation. Because loginWith is read as ordered hash, the library shows input fields in the order email/username/password/password. It correctly validates the email field format but then passes the email field as 'username' to the cognito backend which fails validation with "Username cannot be of email format, since user pool is configured for email alias"
export const config = {
Auth: {
Cognito: {
userPoolId: "POOLID",
userPoolClientId: "CLIENTID",
identityPoolId: "",
loginWith: {
email: true,
username: true,
},
signUpVerificationMethod: "code",
allowGuestAccess: false,
passwordFormat: {
minLength: 8,
requireLowercase: true,
requireUppercase: true,
requireNumbers: true,
requireSpecialCharacters: true,
},
},
},
}
Simply reversing the order succeeds
export const config = {
Auth: {
Cognito: {
userPoolId: "POOLID",
userPoolClientId: "CLIENTID",
identityPoolId: "",
loginWith: {
username: true,
email: true,
},
signUpVerificationMethod: "code",
allowGuestAccess: false,
passwordFormat: {
minLength: 8,
requireLowercase: true,
requireUppercase: true,
requireNumbers: true,
requireSpecialCharacters: true,
},
},
},
}
Now the UI renders the fields in the order username/email/password/password and correctly passes fields to the cognito backend.
Expected behavior
JSON hashes should not be ordered. At a minimum this should be mentioned in the documentation. Even if the hash is read as ordered and the order is used for layout purposes, the library should not make the assumption that the first entry is the "username" and should correctly order attributes and their contents when calling the cognito backend.
Reproduction steps
- install CDK, create user pool (see configuration above), copy pool ID and client ID into Amplify config for Cognito Auth.
- create vite react app for js
- update App.jsx based on https://docs.amplify.aws/react/build-a-backend/auth/use-existing-cognito-resources/ - see code snippets below
- start local server with
npm run dev - navigate to localhost:5173
- try to create an account
Code Snippet
vite-frontend/src/config.js
export const config = {
Auth: {
Cognito: {
userPoolId: "POOLID",
userPoolClientId: "CLIENTID",
identityPoolId: "",
loginWith: {
email: true,
username: true,
},
signUpVerificationMethod: "code",
allowGuestAccess: false,
passwordFormat: {
minLength: 8,
requireLowercase: true,
requireUppercase: true,
requireNumbers: true,
requireSpecialCharacters: true,
},
},
},
}
vite-frontend/src/App.jsx
// You will likely need these imports in your app
import { React } from "react";
import { useState, Component } from "react";
// Amplify and Authenticator imports. This could likely be optimized to only
// import scoped packages
import { Amplify } from "aws-amplify";
import { Authenticator } from "@aws-amplify/ui-react";
import "@aws-amplify/ui-react/styles.css";
// App specific CSS
import "./App.css";
// We are moving config to a separate file to make it easier to
// auto-generate it from deployment scripts.
import { config } from "./config.js";
Amplify.configure(config);
export default function App() {
return (
<>
<h1>Put public content here</h1>
Some public content outside Authenticator
{/*
* If you find the nesting of a function into the body of the
* Authenticator confusing, read up on react render props pattern.
* It should be safe to just leave it as is and put all your content
* into <main></main> */}
<Authenticator hideSignUp={false}>
{({ signOut, user }) => (
<main>
<h1>Hello {user.username}</h1>
{"Attributes: name=" + user.username + ", id=" + user.userId }
{"Test: " + JSON.stringify(user.attributes)}
<button onClick={signOut}>Sign out</button>
{/* Your authenticated content goes here */}
<h1>Put private content here</h1>
Some private content inside Authenticator
</main>
)}
</Authenticator>
</>
);
}
cdk/lib/infra-stack.ts
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as apigw from "aws-cdk-lib/aws-apigateway";
import * as cognito from "aws-cdk-lib/aws-cognito";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as s3deploy from "aws-cdk-lib/aws-s3-deployment";
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
import * as origins from "aws-cdk-lib/aws-cloudfront-origins";
import * as acm from "aws-cdk-lib/aws-certificatemanager";
import { PythonFunction } from "@aws-cdk/aws-lambda-python-alpha";
export class InfraStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
//
// Cognito User Pool
//
const userPool = new cognito.UserPool(this, 'MyUserPool', {
selfSignUpEnabled: true,
// Users must provide a username + email
signInAliases: {
username: true,
email: true,
},
autoVerify: {
email: true,
},
standardAttributes: {
email: {
required: true,
mutable: false,
},
},
passwordPolicy: {
minLength: 8,
requireDigits: true,
requireLowercase: true,
requireUppercase: true,
requireSymbols: false,
},
accountRecovery: cognito.AccountRecovery.EMAIL_ONLY,
email: cognito.UserPoolEmail.withCognito(),
deletionProtection: false, // set to true for production environments
removalPolicy: cdk.RemovalPolicy.DESTROY, // set to RETAIN for production environments
});
const userPoolClient = new cognito.UserPoolClient(this, "UserPoolClient", {
userPool,
generateSecret: false,
authFlows: { userPassword: true, userSrp: true },
preventUserExistenceErrors: true,
});
//
// Outputs for the frontend
//
new cdk.CfnOutput(this, "UserPoolId", { value: userPool.userPoolId });
new cdk.CfnOutput(this, "UserPoolClientId", {
value: userPoolClient.userPoolClientId,
});
}
}
Log output
Console logs
// Put your logs below this line
POST https://cognito-idp.us-west-2.amazonaws.com/ 400 (Bad Request)
fetchTransferHandler | @ | chunk-ENMHY7NY.js?v=d66f5d43:4858
-- | -- | --
| composedHandler | @ | chunk-ENMHY7NY.js?v=d66f5d43:4833
| amzSdkRequestHeaderMiddleware | @ | chunk-ENMHY7NY.js?v=d66f5d43:4811
| retryMiddleware | @ | chunk-ENMHY7NY.js?v=d66f5d43:4739
| amzSdkInvocationIdHeaderMiddleware | @ | chunk-ENMHY7NY.js?v=d66f5d43:4802
| userAgentMiddleware | @ | chunk-ENMHY7NY.js?v=d66f5d43:4824
| (anonymous) | @ | chunk-ENMHY7NY.js?v=d66f5d43:4839
| composedHandler | @ | chunk-ENMHY7NY.js?v=d66f5d43:4833
| disableCacheMiddleware | @ | chunk-ENMHY7NY.js?v=d66f5d43:7343
| (anonymous) | @ | chunk-ENMHY7NY.js?v=d66f5d43:4839
| (anonymous) | @ | chunk-ENMHY7NY.js?v=d66f5d43:4626
| await in (anonymous) | |
| signUp | @ | chunk-ENMHY7NY.js?v=d66f5d43:10900
| handleSignUp | @ | @aws-amplify_ui-reac…js?v=d66f5d43:13947
| Interpreter2._exec | @ | @aws-amplify_ui-react.js?v=d66f5d43:7248
| handleAction | @ | @aws-amplify_ui-react.js?v=d66f5d43:6380
| processBlock | @ | @aws-amplify_ui-react.js?v=d66f5d43:6403
| resolveActions | @ | @aws-amplify_ui-react.js?v=d66f5d43:6425
| StateNode2.resolveTransition | @ | @aws-amplify_ui-react.js?v=d66f5d43:8933
| StateNode2.transition | @ | @aws-amplify_ui-react.js?v=d66f5d43:8873
| (anonymous) | @ | @aws-amplify_ui-react.js?v=d66f5d43:7751
| provide | @ | @aws-amplify_ui-react.js?v=d66f5d43:6431
| Interpreter2._nextState | @ | @aws-amplify_ui-react.js?v=d66f5d43:7750
| (anonymous) | @ | @aws-amplify_ui-react.js?v=d66f5d43:7129
| Scheduler2.process | @ | @aws-amplify_ui-react.js?v=d66f5d43:6965
| Scheduler2.schedule | @ | @aws-amplify_ui-react.js?v=d66f5d43:6949
| Interpreter2.send | @ | @aws-amplify_ui-react.js?v=d66f5d43:7127
| _a2.id.id | @ | @aws-amplify_ui-react.js?v=d66f5d43:7890
| Promise.then | |
| Interpreter2.spawnPromise | @ | @aws-amplify_ui-react.js?v=d66f5d43:7886
| Interpreter2.spawn | @ | @aws-amplify_ui-react.js?v=d66f5d43:7825
| Interpreter2._exec | @ | @aws-amplify_ui-react.js?v=d66f5d43:7263
| handleAction | @ | @aws-amplify_ui-react.js?v=d66f5d43:6380
| processBlock | @ | @aws-amplify_ui-react.js?v=d66f5d43:6403
| resolveActions | @ | @aws-amplify_ui-react.js?v=d66f5d43:6425
| StateNode2.resolveTransition | @ | @aws-amplify_ui-react.js?v=d66f5d43:8933
| StateNode2.transition | @ | @aws-amplify_ui-react.js?v=d66f5d43:8873
| (anonymous) | @ | @aws-amplify_ui-react.js?v=d66f5d43:7751
| provide | @ | @aws-amplify_ui-react.js?v=d66f5d43:6431
| Interpreter2._nextState | @ | @aws-amplify_ui-react.js?v=d66f5d43:7750
| (anonymous) | @ | @aws-amplify_ui-react.js?v=d66f5d43:7129
| Scheduler2.process | @ | @aws-amplify_ui-react.js?v=d66f5d43:6965
| Scheduler2.schedule | @ | @aws-amplify_ui-react.js?v=d66f5d43:6949
| Interpreter2.send | @ | @aws-amplify_ui-react.js?v=d66f5d43:7127
| Interpreter2.update | @ | @aws-amplify_ui-react.js?v=d66f5d43:7359
| (anonymous) | @ | @aws-amplify_ui-react.js?v=d66f5d43:7130
| Scheduler2.process | @ | @aws-amplify_ui-react.js?v=d66f5d43:6965
| Scheduler2.schedule | @ | @aws-amplify_ui-react.js?v=d66f5d43:6949
| Interpreter2.send | @ | @aws-amplify_ui-react.js?v=d66f5d43:7127
| (anonymous) | @ | @aws-amplify_ui-reac…js?v=d66f5d43:10169
| (anonymous) | @ | @aws-amplify_ui-reac…js?v=d66f5d43:30672
| executeDispatch | @ | react-dom_client.js?v=d66f5d43:13622
| runWithFiberInDEV | @ | react-dom_client.js?v=d66f5d43:997
| processDispatchQueue | @ | react-dom_client.js?v=d66f5d43:13658
| (anonymous) | @ | react-dom_client.js?v=d66f5d43:14071
| batchedUpdates$1 | @ | react-dom_client.js?v=d66f5d43:2626
| dispatchEventForPluginEventSystem | @ | react-dom_client.js?v=d66f5d43:13763
| dispatchEvent | @ | react-dom_client.js?v=d66f5d43:16784
| dispatchDiscreteEvent | @ | react-dom_client.js?v=d66f5d43:16765
Request
curl 'https://cognito-idp.us-west-2.amazonaws.com/' \
-H 'accept: */*' \
-H 'accept-language: en-US,en;q=0.9' \
-H 'amz-sdk-invocation-id: 268386ed-b1aa-4ea9-9d6e-82affc94dabc' \
-H 'amz-sdk-request: attempt=1; max=3' \
-H 'cache-control: no-store' \
-H 'content-type: application/x-amz-json-1.1' \
-H 'origin: http://localhost:5174' \
-H 'priority: u=1, i' \
-H 'referer: http://localhost:5174/' \
-H 'sec-ch-ua: "Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "macOS"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: cross-site' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36' \
-H 'x-amz-target: AWSCognitoIdentityProviderService.SignUp' \
-H 'x-amz-user-agent: aws-amplify/6.15.8 auth/1 framework/1 Authenticator ui-react/6.13.1' \
--data-raw '{"Username":"[email protected]","Password":"P@ssw0rd","UserAttributes":[{"Name":"email","Value":"[email protected]"}],"ClientId":"CLIENTID"}'
aws-exports.js
No response
Manual configuration
{
Auth: {
Cognito: {
userPoolId: "POOLID",
userPoolClientId: "CLIENTID",
identityPoolId: "",
loginWith: {
email: true,
username: true,
},
signUpVerificationMethod: "code",
allowGuestAccess: false,
passwordFormat: {
minLength: 8,
requireLowercase: true,
requireUppercase: true,
requireNumbers: true,
requireSpecialCharacters: true,
},
},
},
}
Additional configuration
{
"UserPool": {
"Id": "POOLID",
"Name": "MyUserPoolD09D1D74-b9WgGyXa5WH8",
"Policies": {
"PasswordPolicy": {
"MinimumLength": 8,
"RequireUppercase": true,
"RequireLowercase": true,
"RequireNumbers": true,
"RequireSymbols": false,
"TemporaryPasswordValidityDays": 7
},
"SignInPolicy": {
"AllowedFirstAuthFactors": [
"PASSWORD"
]
}
},
"DeletionProtection": "INACTIVE",
"LambdaConfig": {},
"LastModifiedDate": "2025-12-01T23:39:22.405000-07:00",
"CreationDate": "2025-12-01T23:39:22.405000-07:00",
"SchemaAttributes": [
{
"Name": "profile",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "address",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "birthdate",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "10",
"MaxLength": "10"
}
},
{
"Name": "gender",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "preferred_username",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "updated_at",
"AttributeDataType": "Number",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"NumberAttributeConstraints": {
"MinValue": "0"
}
},
{
"Name": "website",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "picture",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "identities",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {}
},
{
"Name": "sub",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": false,
"Required": true,
"StringAttributeConstraints": {
"MinLength": "1",
"MaxLength": "2048"
}
},
{
"Name": "phone_number",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "phone_number_verified",
"AttributeDataType": "Boolean",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false
},
{
"Name": "zoneinfo",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "locale",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "email",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": false,
"Required": true,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "email_verified",
"AttributeDataType": "Boolean",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false
},
{
"Name": "given_name",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "family_name",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "middle_name",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "name",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
},
{
"Name": "nickname",
"AttributeDataType": "String",
"DeveloperOnlyAttribute": false,
"Mutable": true,
"Required": false,
"StringAttributeConstraints": {
"MinLength": "0",
"MaxLength": "2048"
}
}
],
"AutoVerifiedAttributes": [
"email"
],
"AliasAttributes": [
"email"
],
"SmsVerificationMessage": "The verification code to your new account is {####}",
"EmailVerificationMessage": "The verification code to your new account is {####}",
"EmailVerificationSubject": "Verify your new account",
"VerificationMessageTemplate": {
"SmsMessage": "The verification code to your new account is {####}",
"EmailMessage": "The verification code to your new account is {####}",
"EmailSubject": "Verify your new account",
"DefaultEmailOption": "CONFIRM_WITH_CODE"
},
"UserAttributeUpdateSettings": {
"AttributesRequireVerificationBeforeUpdate": []
},
"MfaConfiguration": "OFF",
"EstimatedNumberOfUsers": 1,
"EmailConfiguration": {
"EmailSendingAccount": "COGNITO_DEFAULT"
},
"UserPoolTags": {},
"AdminCreateUserConfig": {
"AllowAdminCreateUserOnly": false,
"UnusedAccountValidityDays": 7
},
"Arn": "arn:aws:cognito-idp:us-west-2:123412341234:userpool/POOLID",
"AccountRecoverySetting": {
"RecoveryMechanisms": [
{
"Priority": 1,
"Name": "verified_email"
}
]
},
"UserPoolTier": "ESSENTIALS"
}
}
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
Hello @frumpel , thanks for reporting this issue. We will look into it and provide you with an update.
Hi @frumpel,
This issue has been resolved and is now available in version @aws-amplify/[email protected]. Please upgrade to this version to receive the fix.
You can find the full release notes here: https://github.com/aws-amplify/amplify-ui/releases/tag/%40aws-amplify/ui%406.13.0
I'm closing this issue now, but please don't hesitate to reopen it if you encounter any problems or have additional questions.
Thank you for reporting this!