Description
Before opening, please confirm:
- I have searched for duplicate or closed issues and discussions.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
Next.js
Amplify APIs
Authentication
Amplify Version
v6
Amplify Categories
No response
Backend
None
Environment information
# Put output below this line
System:
OS: macOS 15.5
CPU: (16) arm64 Apple M4 Max
Memory: 66.25 MB / 64.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.16.0 - ~/.nvm/versions/node/v22.16.0/bin/node
npm: 10.9.2 - ~/.nvm/versions/node/v22.16.0/bin/npm
pnpm: 10.5.2 - ~/.nvm/versions/node/v22.16.0/bin/pnpm
Watchman: 2025.05.26.00 - /opt/homebrew/bin/watchman
Browsers:
Chrome: 138.0.7204.101
Safari: 18.5
npmPackages:
@turbo/gen: ^2.5.0 => 2.5.0
husky: ^9.1.7 => 9.1.7
syncpack: ^13.0.3 => 13.0.3
turbo: ^2.5.0 => 2.5.0
typescript: ^5.8.3 => 5.8.3
npmGlobalPackages:
@anthropic-ai/claude-code: 1.0.3
corepack: 0.32.0
npm: 10.9.2
pnpm: 10.11.0
Describe the bug
AWS Amplify's JWT token validation in the Next.js adapter fails when using LocalStack for local development due to hardcoded AWS URL construction in the JWT verification process. The CognitoJwtVerifier.parseUserPoolId()
method in cognito-verifier.js
(lines 67-80) hardcodes the issuer URL as https://cognito-idp.${region}.amazonaws.com/${userPoolId}
, but LocalStack JWTs contain issuer claims pointing to local endpoints (e.g., http://localhost:4567/us-east-1_localuserpool
).
Expected behavior
The JWT validator should respect custom endpoints specified in the Amplify configuration. When userPoolEndpoint is configured to point to LocalStack (http://localhost:4567), the validator should construct issuer URLs using this endpoint instead of hardcoding amazonaws.com domains.
Reproduction steps
- Set up Next.js application with AWS Amplify adapter
- Configure LocalStack with Cognito IDP service
- Set environment variables:
NEXT_PUBLIC_COGNITO_POOL_ENDPOINT=http://localhost:4567
NEXT_PUBLIC_COGNITO_USER_POOL_ID=us-east-1_localuserpool
- Configure Amplify with custom endpoint:
export const amplifyConfig: ResourcesConfig = {
Auth: {
Cognito: {
userPoolId: 'us-east-1_localuserpool',
userPoolEndpoint: 'http://localhost:4567',
userPoolClientId: 'localclientid',
identityPoolId: 'us-east-1:local-identity-pool',
identityPoolEndpoint: 'http://localhost:4567',
},
},
};
- Generate JWT token from LocalStack (issuer: http://localhost:4567/us-east-1_localuserpool)
- Attempt validation in Next.js middleware/server components
- Observe validation failure due to issuer mismatch
Code Snippet
// Put your code below this line.
Log output
// Put your logs below this line
aws-exports.js
No response
Manual configuration
{
Auth: {
Cognito: {
userPoolId: appConfig.NEXT_PUBLIC_COGNITO_USER_POOL_ID, // us-east-1_localuserpool
userPoolEndpoint: appConfig.NEXT_PUBLIC_COGNITO_POOL_ENDPOINT, // http://localhost:4567
identityPoolId: appConfig.NEXT_PUBLIC_COGNITO_IDENTITY_POOL_ID, // us-east-1:localidentitypool
userPoolClientId: appConfig.NEXT_PUBLIC_COGNITO_CLIENT_ID, // localuserpoolclient
identityPoolEndpoint: appConfig.NEXT_PUBLIC_COGNITO_POOL_ENDPOINT, // http://localhost:4567
},
}
}
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
- Affected files:
- @aws-amplify/adapter-nextjs/dist/esm/utils/createTokenValidator.mjs
- @aws-amplify/adapter-nextjs/dist/esm/utils/isValidCognitoToken.mjs
- aws-jwt-verify/dist/esm/cognito-verifier.js (lines 67-80)
- aws-jwt-verify/dist/esm/jwt-rsa.js (line 281)
- Framework: Next.js with AWS Amplify adapter
- Environment: LocalStack for local development
- Works in: Pure React client-side applications (doesn't use server-side JWT validation)