AWS Cognito 'Index.handler' Error in React-Redux app - reactjs

I am trying to learn how to integrate AWS Cognito Auth into a custom React-Redux app. I am running into an issue during the sign-up event with the following error message from cognito:
"message: "CustomMessage failed with error index.handler is undefined or not exported."}"
This error is being generated from my 'signup' action. So I know that react is passing off the form data to redux accurately. The Cognito console also successfully shows a registered user, however the email confirmation the user is supposed to get after the signup process is not sent (I am using real email's to test).
Below are my action and reducers for the signup process. Any suggestions would be helpful.
--FYI I made sure that my Amplify configuration is in the root and that my src directory has an index.js file. I am also using email as the username.
ACTION
// SIGN UP USER
export const signup = ({
firstname,
lastname,
username,
password,
phonenumber,
}) => async (dispatch) => {
try {
const res = await Auth.signUp({
username,
password,
attributes: {
given_name: firstname,
family_name: lastname,
phone_number: phonenumber,
},
});
console.log(res);
dispatch({
type: SIGNUP_SUCCESS,
payload: res,
});
// get if user is signed in
dispatch(loadUser());
} catch (error) {
console.log(error);
dispatch({
type: SIGNUP_FAIL,
});
}
};
REDUCER
case SIGNUP_SUCCESS:
return {
...state,
...payload,
isAuthenticate: true,
};
case AUTH_ERROR:
case LOGOUT:
return {
...state,
isAuthenticated: false,
user: null,
};
REACT FORM
const SignUp = ({ signup, isAuthenticated }) => {
// collect data from form
const [formData, setFormData] = useState({
firstname: '',
lastname: '',
username: '',
password: '',
phonenumber: '',
});
//extract data into formData object
const { firstname, lastname, username, password, phonenumber } = formData;
// collect input data on click
const onChange = (event) =>
setFormData({ ...formData, [event.target.name]: event.target.value });
// call action on submit of form
const onSubmit = async (event) => {
event.preventDefault();
try {
// call signup action
signup({ firstname, lastname, username, password, phonenumber });
//this.props.history.push('/welcome');
return <Redirect to='/welcome' />;
} catch (error) {
console.log(error.message);
}
};
// if user is already signed up/in then return to dashboard
if (isAuthenticated) {
return <Redirect to='/dashboard' />;
}
return (
<Fragment>
<div className='row signin'>
<div className='col-md-3 col-sm-auto col-lg-3'></div>
<div className='col-md-6 col-sm-auto col-lg-6 text-center '>
{/* onSubmit={this.handleSubmit} */}
<form className='form-signin' onSubmit={onSubmit}>
<h1 className='h3 font-weight-normal'>Please sign in</h1>
<label for='inputFirstName' className='sr-only'>
First Name
</label>
<input
type='text'
id='inputFirstName'
name='firstName'
className='form-control'
placeholder='First Name'
required
onChange={onChange}
></input>
<label for='inputLastName' className='sr-only'>
Last Name
</label>
<input
type='text'
id='inputLastName'
name='lastname'
className='form-control'
placeholder='Last Name'
required
onChange={onChange}
></input>
<label for='inputEmail' className='sr-only'>
E-mail
</label>
<input
type='text'
name='username'
id='inputemail'
className='form-control'
placeholder='Email address'
required
autofocus
onChange={onChange}
></input>
<label for='inputPassword' className='sr-only'>
Password
</label>
<input
type='password'
id='inputPassword'
name='password'
className='form-control'
placeholder='Password'
required
onChange={onChange}
></input>
<label for='inputPhoneNumber' className='sr-only'>
Phone Number
</label>
<input
type='text'
id='inputPhoneNumber'
name='phonenumber'
className='form-control'
placeholder='Phone Number'
required
onChange={onChange}
></input>
<button className='btn btn-lg btn-primary btn-block' type='submit'>
Sign up
</button>
</form>
</div>
<div className='col-md-3 col-sm-auto col-lg-3'></div>
</div>
</Fragment>
);
};
SignUp.propTypes = {
signup: propTypes.func.isRequired,
isAuthenticated: propTypes.bool,
};
const mapStateToProps = (state) => ({
isAuthenticated: state.auth.isAuthenticated,
});
export default connect(mapStateToProps, { signup })(SignUp);

That error message sounds like a Lambda function is failing. Do you by chance have Cognito set to trigger a Lambda function with a custom signup message?
It sounds like you have customized the 'send email confirmation' behavior with your own Lambda function, and that function is not written/packaged/deployed correctly.

Related

React how to pass onSubmit handler through props to the components

I have developed a simple login component for my project. In this I am having two fields (UserName and Password) along with onSubmit handler. I need to pass the onSubmit handler through the props to the components which accepts two params(Username and Password). When I am calling the onsubmit handler I need to call handler with password and username password as params. I have wrote the logic for the same but when I am rendering I am not getting the textbox to fill (userName and Password). Any one can help me to sort out this issue? Thanks in advance. I have wrote down the code below.
function FormDetails(props) {
return (
<div>
<form onSubmitHandler={props.onSubmitHandler}>
<input type="text" id="user-input" name="userName" />
<input type="password" id="password-input" name="password" />
<button type="submit">Submit</button>
</form>
</div>
);
}
function LoginForm() {
const [form, setForm] = useState({
userName: "",
password: "",
});
const onSubmitHandler = (e) => {
e.preventDefault();
console.log("form.userName", form.userName);
setForm({ [e.target.name]: e.target.value });
};
if (form.userName && form.password == null) {
return <FormDetails onSubmitHandler={onSubmitHandler} />;
}
return (
<div>
UserName:{form.userName}
Password:{form.password}
</div>
);
}
export default LoginForm;
update your if condtion and form element to this
<form onSubmit={props.onSubmitHandler}>
if (!form.userName && !form.password) {
// other code
}
the if condition
the if condition should be revesed because you want to show the form if the values are falsy("" empty string, undefined, null ...)
if (!form.userName || !form.password) {
// ^-- ^--
return <FormDetails onSubmitHandler={onSubmitHandler} />;
}
moving values from child to parent
use a ref for the username & password fields
const userName = useRef(null);
const password = useRef(null);
pass the values up with the handleSubmit callback
<div>
<form
onSubmit={(e) => {
e.preventDefault();
console.log({
userName: userName.current.value,
password: password.current.value
});
props.onSubmitHandler({
userName: userName.current.value,
password: password.current.value
});
}}
>
<input ref={userName} type="text" id="user-input" name="userName" />
<input
ref={password}
type="password"
id="password-input"
name="password"
/>
<button type="submit">Submit</button>
</form>
</div>
Final result
import { useState, useRef } from "react";
function FormDetails(props) {
const userName = useRef(null);
const password = useRef(null);
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
console.log({
userName: userName.current.value,
password: password.current.value
});
props.onSubmitHandler({
userName: userName.current.value,
password: password.current.value
});
}}
>
<input ref={userName} type="text" id="user-input" name="userName" />
<input
ref={password}
type="password"
id="password-input"
name="password"
/>
<button type="submit">Submit</button>
</form>
</div>
);
}
function LoginForm() {
const [form, setForm] = useState({
userName: "",
password: ""
});
const onSubmitHandler = (val) => {
setForm(val);
};
if (!form.userName || !form.password) {
return <FormDetails onSubmitHandler={onSubmitHandler} />;
}
return (
<div>
UserName:{form.userName}
Password:{form.password}
</div>
);
}
export default LoginForm;

I can't find an example of how to make an HTTP POST request using useEffect hook along with axios

Lately, I've been trying to make an HTTP POST request using the useEFfect hook along with axios, but the code returns this error in the console: Error: Request failed with status code 422. The POST request is always successfully made when I make it from the form onSubmit handler. However, when I try to make it from the useEffect hook, it gives that error. Can anybody help me with what I'm doing wrong? Here's the code:
import React, { useState, useEffect } from "react";
import axios from "axios";
function RandomPost() {
const [input, setInput] = useState({
name: "",
email: "",
companyName: "",
password: "",
});
const handleChange = (event) => {
setInput({ ...input, [event.target.id]: event.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
};
useEffect(() => {
const { name, email, companyName, password } = input;
axios
.post(`https://01hire.collaq.com/user/createCompany`, input)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
}, [input]);
const { name, email, companyName, password } = input;
return (
<div>
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" id="name" value={name} onChange={handleChange} />
</label>
<label>
Email:
<input type="text" id="email" value={email} onChange={handleChange} />
</label>
<label>
Company Name:
<input
type="text"
id="companyName"
value={companyName}
onChange={handleChange}
/>
</label>
<label>
Password:
<input
type="password"
id="password"
value={password}
onChange={handleChange}
/>
</label>
<button type="submit">Submit</button>
</form>
</div>
);
}
export default RandomPost;

how to fix (CSRF token missing or incorrect ) react/redux + django

i'm developing authentication
[login_page localhost:8000/login/][1]
i tried to login but my state is LOGIN_FAIL
[LOGIN_FAIL][2]
I've checked it's working on postman and I know my template should have this code.
<form method="post">{% csrf_token %}
But, If I paste this code into Login.js, it makes an error. Like this
Login.js:
const Login = ({ login }) => {
const [formData, setFormData] = useState({
email: '',
password: ''
});
const { email , password } = formData;
const onChange = e => setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = e => {
e.preventDefault();
login(email, password);
};
// Is the user authenticated
// Redirect them to the home page
return (
<form method="post">{% csrf_token %}
<div className="container mt-5">
{/* <h1>회원가입</h1>
<p>이메일로 회원가입</p> */}
<form onSubmit={e => onSubmit(e)}>
<div className="form-group">
<input
className="form-control"
type="email"
placeholder="이메일"
name="email"
value={email}
onChange={e => onChange(e)}
required
/>
</div>
<div className="form-group">
<input
className="form-control"
type="password"
placeholder="비밀번호"
name="password"
value={password}
onChange={e => onChange(e)}
minLength='6'
required
/>
</div>
<button className='btn btn-primary' type='submit'>login</button>
</form>
<p className='mt-3'>
<Link to='/signup'>signin</Link>
</p>
<p className='mt-3'>
<Link to='/reset_password'>find password</Link>
</p>
</div>
</form>
);
};
error code:
Forbidden (CSRF token missing or incorrect.): /http//localhost:8000/auth/jwt/create/
[04/Feb/2021 01:33:26] "POST /http//localhost:8000/auth/jwt/create/ HTTP/1.1" 403 2513
authentication trigger code:
export const login = (email, password) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ email, password });
try {
const res = await axios.post(`${process.env.REACT_APP_API_URL}/auth/jwt/create/`, body, config);
dispatch ({
type: LOGIN_SUCCESS,
payload: res.data
});
dispatch (load_user());
} catch (err) {
dispatch ({
type: LOGIN_FAIL,
});
}
};
MIDDLEWARE code :
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Any hint would be appreciated.
[1]: https://i.stack.imgur.com/QVXfX.jpg
[2]: https://i.stack.imgur.com/9mWSA.jpg
If you use redux, you can use redux-csrf package.
npm install redux-csrf --save
Then you can use the setCsrfToken(token) API that set the CSRF token in the Redux store.
Please refer here. enter link description here

ReactJS - how can I handle notifications to user based on server response?

so I've been trying to figure out
how to handle some notifications/alerts to show users some information based on what they typed in for example login form.
const DoLogin = async (email, password) => {
const loginTeacher = await axios.post(
"http://localhost:3000/teachers/login",
{
email,
password
}
);
return loginTeacher;
};
class Login extends React.Component {
state = {
email: "",
password: "",
logged: false,
status: "",
errorMessage: ""
};
onEmailChange = e => {
this.setState({
email: e.target.value
});
};
onPassChange = e => {
this.setState({
password: e.target.value
});
};
onSubmit = e => {
e.preventDefault();
DoLogin(this.state.email, this.state.password)
.then(res => {
localStorage.setItem("mysecrettoken", res.data.token);
this.setState({ teacher: res.data, logged: true, status: res.status });
alert("Successfully logged in");
})
.catch(err => {
alert("Unable to login in, user not found");
});
};
loginForm() {
return (
<div className="Login form">
<form onSubmit={this.onSubmit}>
<label htmlFor="email">
Email:
<input
type="text"
name="email"
value={this.state.email}
onChange={this.onEmailChange}
/>
</label>
<br />
<label htmlFor="password">
Hasło:
<input
type="password"
name="password"
value={this.state.password}
onChange={this.onPassChange}
/>
</label>
<br />
<input type="submit" value="Zaloguj" />
<input type="button" value="Dodaj nauczyciela" />
</form>
</div>
);
}
}
Now, whenever a user is able to login it shows alert with the message, but I don't think that's a good way to show user information.
Could you please help me with that? Some articles/libraries would be great. I've tried to implement react toast but I failed to do that.
You can store the details in the state (like you already do) and then access in the render method for conditional rendering if the user has logged in.
const DoLogin = async (email, password) => {
const loginTeacher = await axios.post(
"http://localhost:3000/teachers/login",
{
email,
password
}
);
return loginTeacher;
};
class Login extends React.Component {
state = {
email: "",
password: "",
logged: false,
status: "",
errorMessage: ""
};
onEmailChange = e => {
this.setState({
email: e.target.value
});
};
onPassChange = e => {
this.setState({
password: e.target.value
});
};
onSubmit = e => {
e.preventDefault();
DoLogin(this.state.email, this.state.password)
.then(res => {
localStorage.setItem("mysecrettoken", res.data.token);
this.setState({ teacher: res.data, logged: true, status: res.status, showingMessage: true });
setTimeout(() => {
this.setState({ showingMessage: false })
}, 2000)
alert("Successfully logged in");
})
.catch(err => {
// update state with ERROR
this.setState({ error: err.message })
alert("Unable to login in, user not found");
});
};
loginForm() {
if (this.state.logged && this.state.showingMessage) {
return (<div>You've logged in as {this.state.teacher.name}</div>)
}
return (
<div className="Login form">
{/* display ERROR */}
{this.state.error && <span style="color:red">
There was an error during registration: {this.state.error}.
</span>}
<form onSubmit={this.onSubmit}>
<label htmlFor="email">
Email:
<input
type="text"
name="email"
value={this.state.email}
onChange={this.onEmailChange}
/>
</label>
<br />
<label htmlFor="password">
Hasło:
<input
type="password"
name="password"
value={this.state.password}
onChange={this.onPassChange}
/>
</label>
<br />
<input type="submit" value="Zaloguj" />
<input type="button" value="Dodaj nauczyciela" />
</form>
</div>
);
}
}
I don't know where your render method is, but basically just access the state. You can also set a timeout after you received the data, and add another property on the state, like showingMessage which will be true at first, and then in say 2s will be false, then your condition would be if (this.state.logged & this.state.showingMessage).

How to fix "XML Parsing Error: syntax error" in React JS?

I am trying to setup user login/auth in MERN stack. When I fill the register form and submit I get the following message on console.
XML Parsing Error: syntax error
Location: http://localhost:3000/api/users/register
Line Number 1, Column 1:
I have tested my api using Postman and everything seems to be working fine.
Below is my api for register requuest:
// API routes
// #routes POST api/users/register
// #access Public
// #route POST api/users/register
// #desc Register user
// #access Public
router.post("/register", (req, res) => {
// Form validation
const { errors, isValid } = validateRegisterInput(req.body);
// Check validation
if (!isValid) {
return res.status(400).json(errors);
}
User.findOne({ email: req.body.email }).then(user => {
if (user) {
return res.status(400).json({ email: "Email already exists" });
} else {
const newUser = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password
});
// Hash password before saving in database
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => res.json(user))
.catch(err => console.log(err));
});
});
}
});
});
On the client side:
Register.jsx
import ...
class Register extends Component {
constructor() {
super();
this.state = {
name: "",
email: "",
password: "",
password2: "",
errors: {}
};
}
componentDidMount() {
// If logged in and user navigates to Register page, should redirect them to dashboard
if (this.props.auth.isAuthenticated) {
this.props.history.push("/dashboard");
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.errors) {
this.setState({
errors: nextProps.errors
});
}
}
onChange = e => {
this.setState({ [e.target.id]: e.target.value });
};
onSubmit = e => {
e.preventDefault();
const newUser = {
name: this.state.name,
email: this.state.email,
password: this.state.password,
password2: this.state.password2
};
this.props.registerUser(newUser, this.props.history);
};
render() {
const { errors } = this.state;
return (
<div className="container">
<div className="row">
<div className="col s8 offset-s2">
<Link to="/" className="btn-flat waves-effect">
<i className="material-icons left">keyboard_backspace</i> Back to
home
</Link>
<div className="col s12" style={{ paddingLeft: "11.250px" }}>
<h4>
<b>Register</b> below
</h4>
<p className="grey-text text-darken-1">
Already have an account? <Link to="/login">Log in</Link>
</p>
</div>
<form noValidate onSubmit={this.onSubmit}>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.name}
error={errors.name}
id="name"
type="text"
className={classnames("", {
invalid: errors.name
})}
/>
<label htmlFor="name">Name</label>
<span className="red-text">{errors.name}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.email}
error={errors.email}
id="email"
type="email"
className={classnames("", {
invalid: errors.email
})}
/>
<label htmlFor="email">Email</label>
<span className="red-text">{errors.email}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.password}
error={errors.password}
id="password"
type="password"
className={classnames("", {
invalid: errors.password
})}
/>
<label htmlFor="password">Password</label>
<span className="red-text">{errors.password}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.password2}
error={errors.password2}
id="password2"
type="password"
className={classnames("", {
invalid: errors.password2
})}
/>
<label htmlFor="password2">Confirm Password</label>
<span className="red-text">{errors.password2}</span>
</div>
<div className="col s12" style={{ paddingLeft: "11.250px" }}>
<button
style={{
width: "150px",
borderRadius: "3px",
letterSpacing: "1.5px",
marginTop: "1rem"
}}
type="submit"
className="btn btn-large waves-effect waves-light hoverable blue accent-3"
>
Sign up
</button>
</div>
</form>
</div>
</div>
</div>
);
}
}
Register.propTypes = {
registerUser: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth,
errors: state.errors
});
export default connect(
mapStateToProps,
{ registerUser }
)(withRouter(Register));
I cannot see what is wrong in the code. I have followed a tutorial and done the exact same thing.
My registerUser method is in the following file.
authActions.js
// Register User
export const registerUser = (userData, history) => dispatch => {
axios
.post("/api/users/register", userData)
.then(res => history.push("/login")) // re-direct to login on successful register
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
// Login - get user token
export const loginUser = userData => dispatch => {
axios
.post("/api/users/login", userData)
.then(res => {
// Save to localStorage
// Set token to localStorage
const { token } = res.data;
localStorage.setItem("jwtToken", token);
// Set token to Auth header
setAuthToken(token);
// Decode token to get user data
const decoded = jwt_decode(token);
// Set current user
dispatch(setCurrentUser(decoded));
})
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
// Set logged in user
export const setCurrentUser = decoded => {
return {
type: SET_CURRENT_USER,
payload: decoded
};
};
// User loading
export const setUserLoading = () => {
return {
type: USER_LOADING
};
};
// Log user out
export const logoutUser = () => dispatch => {
// Remove token from local storage
localStorage.removeItem("jwtToken");
// Remove auth header for future requests
setAuthToken(false);
// Set current user to empty object {} which will set isAuthenticated to false
dispatch(setCurrentUser({}));
};

Resources