Hello friends,
I’ve been away from coding for a little while and I was doing a youtube tutorial to jump start me back into back end development. The video was for setting up basic user authentication, and I am finding that while the fetch request to login works fine, I can’t store the JSON Web Token upon completion of the fetch request. The video was using local Storage to store the JWT (I understand this is a security risk) but overall I am just not understanding why the code for it is failing to execute. The fetch request is successful, but any code that it attached to the proceeding .then statement on the login page doesn’t run. Local storage is empty upon completion of the request. I would appreciate any help. Thank you :).
The code for my login page is
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'/>
<meta name="viewport" content="width=device-width, intitial-scale=1.0" />
<title>Login Page</title>
</head>
<body>
<h1>Login</h1>
<form id='login' method='post' action='/api/login' >
<input type='text' id='username' name='username' autocomplete='off' placeholder='Username'>
<input type='Password' id='password' name='password' autocomplete='off' placeholder='Password'>
<input type='submit' value='Submit Form' />
</form>
<script>
async function loginUser(event) {
event.preventDefault()
const username = document.getElementById('username').value
const password = document.getElementById('password').value
const result = await fetch('/api/login', {
method: 'POST',
credentials: 'include',
mode: 'cors',
headers: {
Accept: 'application/json',
Content-Type: 'application/json'
},
body: JSON.stringify({
username,
password
})
}).then((res) =>
localStorage.setItem('token', res.data))
}
const form = document.getElementById('login')
form.addEventListener('submit', loginUser)
</script>
</body>
</html>
The code for my server.js with all the routes is
const express = require('express')
const path = require('path')
const bodyParser = require('body-parser')
const mongoose = require('mongoose')
const User = require('./model/user')
const bcrypt = require('bcryptjs')
const mongodb = require('mongodb')
const jwt = require('jsonwebtoken')
const cors = require('cors')
mongoose.connect(process.env['URI'], { useNewUrlParser: true, useUnifiedTopology: true}).catch(error => console.log(error));
mongoose.connection.on('error', err => {
console.log(err);
})
const app = express()
app.use('/', express.static(path.join(__dirname, 'static')))
app.use(cors())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
app.post('/api/change-password', async (req, res) => {
const { token, newpassword } = req.body
console.log(token)
try {
const user = jwt.verify(token, process.env['JWT_SECRET'])
const _id = user.id
const hashedPassword = bcrypt.hash(newpassword, 10)
await User.updateOne({ _id }, { $set: { password: hashedPassword } } )
} catch (error) {
console.log(error.message)
return res.json({ status: 'error', error: 'write something'})
}
res.json({ status: 'ok' })
})
app.post('/api/login', async (req, res) => {
const { username, password } = req.body;
const user = await User.findOne({ username }).lean()
if (!user) {
return res.json({ status: 'error', error: 'Invalid username/password' })
}
if (await bcrypt.compare(password, user.password)) {
const token = jwt.sign({ id: user._id, username: user.username }, process.env['JWT_SECRET']
)
// console.log('login token ' + token)
return res.json({ status: 'ok', data: token })
}
res.json({ status: 'error', error: 'Invalid username/password' })
})
app.post('/api/register', async (req, res) => {
console.log(req.body)
const { username, password: plainTextPassword } = req.body
if (!username || typeof username !== 'string') { return res.json({ status: 'error', error: 'Invalid Username' })}
if (!plainTextPassword || typeof plainTextPassword !== 'string') { return res.json({ status: 'error', error: 'Invalid Password' })}
if (!plainTextPassword.length > 5) {
return res.json({ status: 'error', error: 'Password is too short. Please use 6 characters.' })
}
const password = await bcrypt.hash(plainTextPassword, 10)
try {
const response = await User.create({
username: username,
password: password
})
console.log('User created successfully ' + response)
} catch (error) {
if (error.code === 11000) {
//duplicate username
console.log(error)
res.json({ status: 'error', error: 'Username already in use' })
}
throw error
}
await res.json({status: 'ok'}) })
app.listen('9999', () => {
console.log('Server at 9999')
})