Reputation: 116
I'm working on a NextJS project where I'm using AWS Amplify for authentication with Amazon Cognito. However, I'm encountering an issue where I receive an error message stating "Auth UserPool not configured" when I try to log in/sign up. I've checked my configurations and they seem correct, I am also able to manually create users from the AWS GUI. Below is the relevant code and configuration details.
Index.js
import React, { useState, useEffect } from 'react'
import { Amplify } from 'aws-amplify'
import { Authenticator } from '@aws-amplify/ui-react'
import '@aws-amplify/ui-react/styles.css'
import { Auth } from 'aws-amplify'
Amplify.configure({
Auth: {
region: process.env.REGION,
userPoolId: process.env.USER_POOL_ID,
userPoolWebClientId: process.env.USER_POOL_APP_CLIENT_ID,
},
})
function Home() {
const [jwtToken, setJwtToken] = useState('')
useEffect(() => {
fetchJwtToken()
}, [])
const fetchJwtToken = async () => {
try {
const session = await Auth.currentSession()
const token = session.getIdToken().getJwtToken()
setJwtToken(token)
} catch (error) {
console.log('Error fetching JWT token:', error)
}
}
return (
<Authenticator
initialState='signIn'
components={{
SignUp: {
FormFields() {
return (
<>
<Authenticator.SignUp.FormFields />
{/* Custom fields for given_name and family_name */}
<div>
<label>First name</label>
</div>
<input
type='text'
name='given_name'
placeholder='Please enter your first name'
/>
<div>
<label>Last name</label>
</div>
<input
type='text'
name='family_name'
placeholder='Please enter your last name'
/>
<div>
<label>Email</label>
</div>
<input
type='text'
name='email'
placeholder='Please enter a valid email'
/>
</>
)
},
},
}}
services={{
async validateCustomSignUp(formData) {
if (!formData.given_name) {
return {
given_name: 'First Name is required',
}
}
if (!formData.family_name) {
return {
family_name: 'Last Name is required',
}
}
if (!formData.email) {
return {
email: 'Email is required',
}
}
},
}}
>
{({ signOut, user }) => (
<div>
Welcome {user.username}
<button onClick={signOut}>Sign out</button>
<h4>Your JWT token:</h4>
{jwtToken}
</div>
)}
</Authenticator>
)
}
export default Home
This is the template.yaml file I ran using sam deploy --guided
to create the infrastructure
AWSTemplateFormatVersion: 2010-09-09
Description: >-
template for creating the Cognito User Pool
Transform:
- AWS::Serverless-2016-10-31
Parameters:
Env:
Type: String
Default: dev
S3BucketName:
Type: String
Default: pibot-nextjs-website
CognitoUserPoolName:
Type: String
Default: pibot-users-v2
CognitoWebClientName:
Type: String
Default: cognito-webclient
Resources:
CloudFrontOriginAccessIdentity:
Type: 'AWS::CloudFront::CloudFrontOriginAccessIdentity'
Properties:
CloudFrontOriginAccessIdentityConfig:
Comment: 'Origin Access Identity'
CloudfrontDistribution:
Type: 'AWS::CloudFront::Distribution'
Properties:
DistributionConfig:
Comment: 'Cloudfront distribution for the static website'
DefaultRootObject: 'index.html'
Enabled: true
HttpVersion: http2
Origins:
- Id: s3-website
DomainName: !GetAtt S3Bucket.DomainName
S3OriginConfig:
OriginAccessIdentity:
Fn::Sub: 'origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}'
DefaultCacheBehavior:
Compress: 'true'
AllowedMethods:
- GET
- HEAD
- OPTIONS
ForwardedValues:
QueryString: false
TargetOriginId: s3-website
ViewerProtocolPolicy: redirect-to-https
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub '${Env}-${S3BucketName}'
S3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref S3Bucket
PolicyDocument:
Statement:
- Effect: Allow
Action: 's3:GetObject'
Resource:
- !Sub 'arn:aws:s3:::${S3Bucket}/*'
Principal:
AWS: !Sub 'arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${CloudFrontOriginAccessIdentity}'
CognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: !Sub '${Env}-${CognitoUserPoolName}'
AliasAttributes:
- email
UsernameConfiguration:
CaseSensitive: false
AutoVerifiedAttributes:
- email
Policies:
PasswordPolicy:
MinimumLength: 8
RequireLowercase: true
RequireNumbers: true
RequireUppercase: true
RequireSymbols: true
Schema:
- AttributeDataType: String
Mutable: true
Name: given_name
Required: true
StringAttributeConstraints:
MinLength: '1'
- AttributeDataType: String
Mutable: true
Name: family_name
Required: true
StringAttributeConstraints:
MinLength: '1'
- AttributeDataType: String
Mutable: true
Name: email
Required: true
StringAttributeConstraints:
MinLength: '1'
WebCognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: !Sub '${Env}-${CognitoWebClientName}'
UserPoolId: !Ref CognitoUserPool
ExplicitAuthFlows:
- ALLOW_USER_SRP_AUTH
- ALLOW_REFRESH_TOKEN_AUTH
PreventUserExistenceErrors: ENABLED
Upvotes: 8
Views: 20186
Reputation: 163
For me the adding 'use client' at the top of this component (taken from the docs) did the trick:
'use client'; // before adding this line I had the error that the user pool was not configured!
import { Amplify } from 'aws-amplify';
import config from '../../amplify_outputs.json';
Amplify.configure(config, { ssr: true });
export const ConfigureAmplifyClientSide = () => {
return null;
};
Upvotes: 0
Reputation: 1
Steps for improvement:
Separate Config Files: Create two separate config files for Auth and API (or any other configurations).
Single Configuration File: Create a single configuration file where you import both the Auth and API configs and combine them.
Initialize Amplify: Finally, initialize Amplify with the merged config.
config file:
App.js/Layout.js or any main file:
Upvotes: 0
Reputation: 642
The core of the problem is that
Amplify.configure(amplifyConfig)
is not async - so we can await it somewhere early in <App />
When you call the configure in the entry of your react code the react router could be already trying to use something from amplify.
i have to find a pattern so that Amplify is configured before any loading happens. For example this AuthGuard fails everytime:
const AuthGuard = () => {
const user = await getCurrentUser();
useEffect(() => {
if (!user) {
window.location.href = "/auth/login";
}
}, [user]);
return <Outlet/>;
};
because the routes get loaded before Amplify.configure(amplifyConfig)
chunk-GSLA2FH7.js?v=bb46ed7c:45 Uncaught (in promise) AuthUserPoolException: Auth UserPool not configured.
at http://localhost:5173/node_modules/.vite/deps/chunk-GSLA2FH7.js?v=bb46ed7c:45:11
at assertTokenProviderConfig (http://localhost:5173/node_modules/.vite/deps/chunk-GSLA2FH7.js?v=bb46ed7c:153:3)
at getCurrentUser (http://localhost:5173/node_modules/.vite/deps/chunk-GSLA2FH7.js?v=bb46ed7c:6153:3)
at getCurrentUser2 (http://localhost:5173/node_modules/.vite/deps/chunk-GSLA2FH7.js?v=bb46ed7c:6173:10)
at AuthGuard (http://localhost:5173/src/app/components/auth/guards/AuthGuard.tsx?t=1724479425050:23:16)
at getProfileRoutes (http://localhost:5173/src/app/routes/profileRoutes.ts?t=1724479425050:27:16)
at http://localhost:5173/src/app/routes/appRoutes.ts?t=1724479425050:72:6
Upvotes: 1
Reputation: 420
Arriving here searching for the error in the title, the issue and its resolution for me wound up being very different from the ones so far described. Rather than Next.js I was using react-native with Expo and the metro bundler. That's a very different setup, but because I found this stackoverflow question for my identical error, this might be relevant to other searchers.
I had totally messed up my configuration for typescript and for the metro bundler.
Do NOT do this. I had no idea what I was doing; this was wrong and bad:
// metro.config.js:
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("expo/metro-config");
const defaultSourceExts =
require("metro-config/src/defaults/defaults").sourceExts;
const sourceExts = [
"jsx",
"js",
"cjs",
"ts",
"tsx",
"json",
"svg",
"d.ts",
"mjs",
].concat(defaultSourceExts);
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);
module.exports = { ...config, resolver: { sourceExts } };
// tsconfig.json:
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"module": "NodeNext",
"moduleResolution": "NodeNext",
"resolveJsonModule": true,
"esModuleInterop": true
},
"include": [
...
],
"exclude": ["node_modules/**/*", "babel.config.js", "metro.config.js"]
}
After reviewing the expo docs for typescript and metro, and educating myself somewhat better about TypeScript compilation, cjs, and esm, I changed those to this much more default-like config:
// metro.config.js:
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("expo/metro-config");
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);
module.exports = config;
// tsconfig.json:
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true
},
"include": [
...
]
}
I determined I needed to look at this configuration by adding console.log
statements to various amplify source code beneath node_modules/@aws-amplify
. By doing so I determined that some amplify code from beneath dist/cjs
was calling other code beneath dist/esm
and vice-versa, which was causing the Amplify config to appear falsy in the module system by which it hadn't been loaded, and that system was the one throwing the error.
That was my clue that my typescript and javascript-module systems were horribly misconfigured. Returning to the defaults from expo did indeed resolve this specific error for my setup.
Upvotes: 2
Reputation: 31
For me, I had to import the following:
import { Amplify } from 'aws-amplify';
import amplifyconfig from '../src/amplifyconfiguration.json';
then call:
Amplify.configure(amplifyconfig);
I'm running react-native on expo.
Reference:
https://docs.amplify.aws/gen1/react-native/build-a-backend/auth/set-up-auth/
Upvotes: 0
Reputation: 3857
In my case, the config object was correct.
My issue was ultimately a "single character" error of importing from the old lib.
The fix was to modify...
import { Amplify } from '@aws-amplify';
// Amplify.configure( ... );
... to instead be...
import { Amplify } from 'aws-amplify';
// Amplify.configure( ... );
☝️ notice the removed @
Upvotes: 6
Reputation: 81
I had the same error until this afternoon. I figured out what the error is (or was is my case). I think I can see why you'd get the same error.
Like you, I was able to create new users and see them in Amplify console. However I wasn't able to log in due to that error.
You've chosen to configure amplify with the lines that you've shown. You may want to comment out that block until after you try what I suggest.
Amplify will have configured a default configuration as you've set up your authentication and answered the questions to amplify add auth
or amplify update auth
. This config is output to ./aws-export.js
and ./amplifyconfiguration.json
. They both have the same info, only the first is only the json without export and the second file exports the data.
The problem is that you're not using all the settings from this in your current project. To do this you need to call Amplify.configure()
with the json like shown here: https://docs.amplify.aws/javascript/build-a-backend/auth/set-up-auth/
import { Amplify } from 'aws-amplify';
import config from './amplifyconfiguration.json';
Amplify.configure(config);
The best way to figure to actually do this is to create a separate file: ConfigureAmplify.tsx
with the following contents:
import { Amplify } from "aws-amplify";
import config from "../amplifyconfiguration.json";
Amplify.configure(config, { ssr: true });
export default function ConfigureAmplifyClientSide() {
return null;
}
This essentially wraps the include into a do-nothing component and allows you to use the configuration anywhere in your project. Add it to your ./src/app/page.tsx
:
'use client';
import type { WithAuthenticatorProps } from '@aws-amplify/ui-react';
import { withAuthenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import ConfigureAmplifyClientSide from '../../components/ConfigureAmplify';
export function App({ signOut, user } : WithAuthenticatorProps) {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<ConfigureAmplifyClientSide />
<h1>Hello {user?.username}</h1>
<button onClick={signOut}>Sign out</button>
</main>
);
}
export default withAuthenticator(App);
I found this somewhere in the documentation. When in the right place that error should disappear. You should be able to add your current Amplify.configure
back where you have it. You may even find it beneficial to add it to the bottom of the ConfigureAmplify.tsx
file.
You're able to call Amplify.configure() many times to override/add/update functionality as you wish.
In my case I was calling Amplify.configure()
in the wrong file. I moved it and got it working "inline" however I prefer it in a separate file.
Good luck!
Upvotes: 1
Reputation: 101
I had the same problem and was related to the configuration on "aws-exports", the Documentation is a little confusing, but I made it work with this config:
export const amplifyConfig = {
Auth: {
Cognito: {
userPoolId: your_userPoolId,
userPoolClientId: your_userPoolClientId,
region: your_region,
loginWith: {
oauth: {
domain: your_domain,
scopes: [
'phone',
'email',
'profile',
'openid',
'aws.cognito.signin.user.admin'
],
redirectSignIn: [window.location.origin],
redirectSignOut: [window.location.origin],
responseType: "code",
},
},
},
},
};
And also you should have something like this in you index
import { Amplify, ResourcesConfig } from "aws-amplify";
import { amplifyConfig } from './aws-exports';
Amplify.configure(amplifyConfig as ResourcesConfig );
I hope it works for you.
refs: https://github.com/aws-amplify/amplify-js/issues/12627#issuecomment-1848214340
Upvotes: 0
Reputation: 117
It appears that the issue stems from the configuration setup. In AWS Amplify version 6, user pool configuration has been updated. Please adjust your configuration as follows:
Amplify.configure({
Auth: {
Cognito: {
userPoolClientId: 'abcdefghij1234567890',
userPoolId: 'us-east-1_abcd1234',
loginWith: { // Optional
oauth: {
domain: 'abcdefghij1234567890-29051e27.auth.us-east-1.amazoncognito.com',
scopes: ['openid email phone profile aws.cognito.signin.user.admin '],
redirectSignIn: ['http://localhost:3000/','https://example.com/'],
redirectSignOut: ['http://localhost:3000/','https://example.com/'],
responseType: 'code',
}
username: 'true',
email: 'false', // Optional
phone: 'false', // Optional
}
}
}
});
For additional details, you can refer to the official documentation at: AWS Amplify Documentation
I hope this helps resolve your issue. If you have further questions, feel free to ask.
Upvotes: 9
Reputation: 300
I think You need to use NEXT_PUBLIC_
for your environmental vars to make them accessible to your browser environment? https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables#bundling-environment-variables-for-the-browser
so your vars should be:
Amplify.configure({
Auth: {
Cognito: {
region: process.env.NEXT_PUBLIC_REGION,
userPoolId: process.env.NEXT_PUBLIC_USER_POOL_ID,
userPoolWebClientId: process.env.NEXT_PUBLIC_USER_POOL_APP_CLIENT_ID,
}
}
});
don't forget to change the var names in your .env file too :)
Also in amplify docs userpool is configured inside Cognito
property of Auth
object
Upvotes: 0