I have been stuck on this problem for a few days now. I have a NestJs backend that runs on localhost:8080 with user authentication. When I use postman to login or register a user, it works perfectly fine. But when I try to do so from my React frontend, I get the following: ERROR [ExceptionsHandler] data and salt arguments required.
Here is the code for my auth controller:
@ApiTags('auth')
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Post('register')
async register(@Body() registrationData: RegisterDto) {
return this.authService.register(registrationData);
}
@HttpCode(200)
@UseGuards(LocalAuthenticationGuard)
@Post('log-in')
async logIn(@Req() request: RequestWithUser, @Res() response: Response) {
const { user } = request;
const cookie = this.authService.getCookieWithJwtToken(user.id);
response.setHeader('Set-Cookie', cookie);
user.password = undefined;
return response.send(user);
}
@UseGuards(JwtAuthenticationGuard)
@Post('log-out')
async logOut(@Res() response: Response) {
response.setHeader(
'Set-Cookie',
this.authService.getCookieForLogOut(),
);
return response.sendStatus(200);
}
@UseGuards(JwtAuthenticationGuard)
@Get()
authenticate(@Req() request: RequestWithUser) {
const user = request.user;
user.password = undefined;
return user;
}
}
On the frontend, I have a simple login component:
import { useRef, useState, useEffect, useContext } from 'react';
import AuthContext from '../../context/AuthProvider';
import axios from '../../api/axios';
const LOGIN_URL = '/auth/register';
const Login = () => {
const { setAuth } = useContext(AuthContext);
const userRef = useRef();
const errRef = useRef();
const [user, setUser] = useState('');
const [pwd, setPwd] = useState('');
const [errMsg, setErrMsg] = useState('');
const [success, setSuccess] = useState(false);
useEffect(() => {
userRef.current.focus();
}, []);
useEffect(() => {
setErrMsg('');
}, [user, pwd]);
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await axios.post(
LOGIN_URL,
JSON.stringify({ user, pwd }),
{
headers: { 'Content-Type': 'application/json' },
withCredentials: true,
}
);
console.log(JSON.stringify(response?.data));
//console.log(JSON.stringify(response));
const accessToken = response?.data?.accessToken;
const roles = response?.data?.roles;
setAuth({ user, pwd, roles, accessToken });
setUser('');
setPwd('');
setSuccess(true);
} catch (err) {
if (!err?.response) {
setErrMsg('No Server Response');
} else if (err.response?.status === 400) {
setErrMsg('Missing Username or Password');
} else if (err.response?.status === 401) {
setErrMsg('Unauthorized');
} else {
setErrMsg('Login Failed');
}
errRef.current.focus();
}
};
return (
<>
{success ? (
<section>
<h1>You are logged in!</h1>
<br />
<p>
<a href="#">Go to Home</a>
</p>
</section>
) : (
<section>
<p
ref={errRef}
className={errMsg ? 'errmsg' : 'offscreen'}
aria-live="assertive"
>
{errMsg}
</p>
<h1>Sign In</h1>
<form onSubmit={handleSubmit}>
<label htmlFor="username">Username:</label>
<input
type="text"
id="username"
ref={userRef}
autoComplete="off"
onChange={(e) => setUser(e.target.value)}
value={user}
required
/>
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
onChange={(e) => setPwd(e.target.value)}
value={pwd}
required
/>
<button>Sign In</button>
</form>
<p>
Need an Account?
<br />
<span className="line">
{/*put router link here*/}
<a href="#">Sign Up</a>
</span>
</p>
</section>
)}
</>
);
};
export default Login;
I'm completely stumped as to how to fix this error. I'm not sure why bcrypt is saying the password is undefined/it can't hash it.