Login successful with wrong credentials swagger, nodeJS, JWT - javascript

Created a login method but it spits out the token regardless of what is entered in the Userfields
This uses swagger API and I'm trying to develop the frontend and backend
I'm relatively new to nodejs/javascript
Any Help would be appreciated!
login.js
var form = document.getElementById('login')
form.addEventListener('submit', login)
async function login(event) {
event.preventDefault()
const username = document.getElementById('username').value
const password = document.getElementById('password').value
const result = await fetch('/v1/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username,
password
})
}).then((res) => res.json())
if (result.status === 'ok') {
// everythign went fine
console.log('Got the token: ', result.data)
localStorage.setItem('token', result.data)
alert('Login Successful')
return false;
} else {
alert(result.error)
}
}
userController.JS
login: async (req,res)=> {
const { userName, password } = req.body
const existUsername = await userModel.findOne({ userName: req.body.userName, password: req.body.password}).then((existUsername) =>{
if (existUsername){
res.status(400).json({status: 'Failed', message: `User was Not found`, data: null})
return;
}
try{
async() => {
await bcrypt.compare(password, req.body.password) }
// the username, password combination is successful
const token = jwt.sign(
{
id: userModel._id,
userName: userModel.userName
},
JWT_SECRET
)
res.json({ status: 'ok', data: token })
}
catch (e) {
res.status(400).json({status: 'Failed', message: `${e.message}`, data: null})
}
});
},

Related

Why am I getting different response from my data when local and when on heroku?

I am working on an Application which i have also deployed in heroku. The issue is that when I login in using heroku, user is nested inside a data object. but when I work locally or use postman, user isnt nested.
Help Please.
I get this response on the deployed version.
data: {
user: {
email: "my_email"
name: "my_name"
role: "user"
_id: "6205807deeadcfa734f954f3".
}
status: "success"
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYyMDU4MDdkZWVhZGNmYTczNGY5NTRmMyIsImlhdCI6MTY0NDg0NTYyMCwiZXhwIjoxNjQ1NDUwNDIwfQ.YeWFNrN8rsLPJvvU8JQDwBVG4aBqqEuo7ssgLrR3O8M"
But when I log in locally, I get the response as
user: {
email: "my_email"
name: "my_name"
role: "user"
_id: "6205807deeadcfa734f954f3".
}
status: "success"
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYyMDU4MDdkZWVhZGNmYTczNGY5NTRmMyIsImlhdCI
For Heroku, the USER is nested inside data but for local host and postman, the user isnt nested.
My codes are:
exports.login = catchAsync(async (req, res, next) => {
const { email, password } = req.body
if (!email || !password) {
return next(new AppError('Please provide email and password!', 400))
}
const user = await User.findOne({ email }).select('+password')
if (!user || !(await user.comparePassword(password, user.password))) {
return next(new AppError('Incorrect email or password', 401))
}
createSendToken(user, 200, req, res)
})
These are my api codes
const createSendToken = (user, statusCode, req, res) => {
const token = signToken(user._id)
res.cookie('jwt', token, {
expires: new Date(
Date.now() + process.env.JWT_COOKIE_EXPIRES_IN * 24 * 60 * 60 * 1000
),
httpOnly: true,
})
user.password = undefined
res.status(statusCode).json({
status: 'success',
token,
user,
})
}
For my react, The function code is:
function request(path, { data = null, token = null, method = 'GET' }) {
return (
fetch(`${process.env.REACT_APP_API}${path}`, {
method,
headers: {
Authorization: token ? `Bearer ${token}` : '',
'Content-Type': 'application/json',
},
body:
method !== 'GET' && method !== 'DELETE' ? JSON.stringify(data) : null,
})
.then((response) => {
// If Successful
if (response.ok) {
if (method === 'DELETE') {
// If delete, nothing returned
return true
}
return response.json()
}
// If errors
return response
.json()
.then((json) => {
// Handle Json Error response from server
if (response.status === 400) {
const errors = Object.keys(json).map(
(k) => `${json[k].join(' ')}`
)
throw new Error(errors.join(' '))
}
throw new Error(JSON.stringify(json))
})
.catch((e) => {
if (e.name === 'SyntaxError') {
throw new Error(response.statusText)
}
throw new Error(e)
})
})
.catch((e) => {
// Handle all errors
toast(e.message, { type: 'error' })
})
)
}
The main sign in function
export function signIn(email, password) {
return request('/api/v1/auth/login', {
data: { email, password },
method: 'POST',
})
}
Then I import this into my auth context and execute it there
import {signIn as signInApi} from '../apis'
const AuthContext = createContext()
export const AuthProvider = ({ children }) => {
const [token, setToken] = useState(localStorage.getItem('token'))
const [user, setUser] = useState(
JSON.parse(localStorage.getItem('user'))
)
const [loading, setLoading] = useState(false)
const signIn = async (email, password, callback) => {
setLoading(true)
const res = await signInApi(email, password)
if (res.token) {
localStorage.setItem('token', res.token)
localStorage.setItem('user', JSON.stringify(res.user)) // This stores the user in localhost but returns undefined for user in the one deployed to heroku. I have to use
localStorage.setItem('user', JSON.stringify(res.data.user)) which now works on the deployed one but not on the local one
setToken(res.token)
setUser(res.user)
callback()
}
setLoading(false)
}
}
it seems the deployed version is using built in implementaion of createSendToken and not the one you provided. need to check your project structure.
in order to validate this change the function name and the call createSendToken to something else and you will find the issue

Getting Request json data in C# in an HttpPost method

Im in the process of converting my nodejs implementation of my backend to c#. I want to get the request body from my client. How do i access the request body in c#. I then want to use the user input from the client to make another api call using the users parameters.
Here is the front end code
class User {
constructor(userData) {
this.user = userData.id;
this.login = userData.login;
this.password = userData.password;
this.email = userData.email;
this.external_user_id = userData.external_user_id;
this.facebook_id = userData.facebook_id;
this.twitter_id = userData.twitter_id;
this.full_name = userData.full_name;
this.phone = userData.phone;
this.website = userData.website;
this.custom_data = userData.custom_data;
this.user_tags = userData.user_tags;
this.avatar = userData.avatar;
this.created_at = userData.created_at;
this.updated_at = userData.updated_at;
this.last_request_at = userData.last_request_at;
//encrypt the password
}
}
export default User;
async signUp(userCredentials) {
let userForm = new User(userCredentials);
fetch("http://localhost:8080/auth/signup", {
method: 'POST',
body: JSON.stringify(userForm),
headers: {
'Content-Type': 'application/json',
}
})
.then(response => {
if (!response.ok) {
throw Error(`Error message: ${response.statusText}`)
}
console.log(response)
return response.json()
})
.then(json => {
console.log(json);
sessionStorage.setItem('session_token', json.session_token)
this.signIn({ login: userForm.login, password: userForm.password });
})
.catch(error => console.log(error))
}
Here is the nodejs implementation
router.post("/signup", async (req, res) => {
let reqBody = req.body;
console.log(reqBody.password);
console.log(req.headers["cb-token"]);
let cbToken = req.headers["cb-token"];
const userObj = {
user: {
login: req.body.login,
password: req.body.password,
email: req.body.email,
full_name: req.body.full_name,
phone: req.body.phone,
website: req.body.website
}
}
console.log(`token in auth route ${res.locals.session_token}`)
fetch("https://api.connectycube.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
"CB-Token": res.locals.session_token
},
body: JSON.stringify(userObj)
})
.then(response => {
if (!response.ok) {
throw Error(`Error message: ${response.statusText}`)
}
return response.json()
})
.then(data => {
console.log(data)
const resObj = Object.assign(data, { session_token: res.locals.session_token });
res.status(200).json(resObj);
})
.catch(error => {
console.log(error)
res.status(400).json(error)
})
})

MissingPasswordError: No password given

I can signup users just fine on my website, but when I test it with Postman I get this error:
MissingPasswordError: No password given
I also cannot login because the password/username combination is incorrect, so there's definitely something wrong but I can't for the life of me figure out what.
This is my html input field for the password:
<input type="password" class="input--text" name="password" id="password">
signup.js with my fetch function:
const btnSignup = document.querySelector('.btn').addEventListener('click', function () {
let username = document.querySelector('#username').value;
let password = document.querySelector('#password').value;
let bday = document.querySelector('#bday').value;
fetch('http://localhost:3000/users/signup', {
method: "post",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'username': username,
'password': password,
'bday': bday
})
}).then(response => {
return response.json();
}).then(json => {
if (json.status === 'success') {
let feedback = document.querySelector('.alert');
feedback.textContent = "Sign up successful!";
feedback.classList.remove('hidden');
}
})
})
And this is my signup function in my auth.js controller:
const signup = async (req, res, next) => {
const username = req.body.username;
const password = req.body.password;
const bday = req.body.bday;
const user = new Users({
username: username
});
/*user.bday = bday;*/
await user.setPassword(password);
await user.save()
.then(result => {
console.log(result.id);
let token = jwt.sign({
id: result._id
}, "{this is a secret}");
res.json({
'status': 'success',
'data': {
'token': token
}
})
}).catch(error => {
res.json({
'status': 'error'
})
});
}
I've added bodyParser, made sure the name for my input fields are correct, ...
Solved! Turns out my code was correct, but I forgot to set the raw body in Postman to JSON (default was text).

Sequelize update information

I've been struggling with this issue for a day now and can't seem to figure out a way to resolve it. This is the code I'm running
Client side:
const nameInput = document.querySelector("#nameInput");
const urlInput = document.querySelector("#urlInput");
const rowAlert = document.querySelector(".alertAppend");
const divAlert = document.createElement("div");
const nameUpdate = async (e) => {
e.preventDefault();
fetch("/auth/updateName", {
method: 'POST',
headers: {
'Content-Type' : 'application/json'
},
body: JSON.stringify({
name: nameInput,
url: urlInput,
})
})
.then(function (data) {
console.log('Request success: ', data);
})
.catch(function (error) {
console.log('Request failure: ', error);
});
};
submitName.addEventListener("click", nameUpdate);
API:
router.get("/updateName", auth, async (req, res) =>{
try {
const { name, url } = req.body;
const ime = name;
const uid = req.session.passport.user;
db.User.find({ where: { id: uid } })
.on('success', function (user) {
if (user) {
user.update({
name: ime,
webhook: url
})
.success(function () {})
}
})
res.json({ message: url});
} catch (err) {
if (err) res.status(500).json({ message: "Internal Error"})
}
});
For some reason it just runs the select query and never proceeds to update the user.
Chrome console output
Debug console output
Sequelize model in case it helps:
module.exports = function (sequelize, DataTypes) {
var User = sequelize.define("User", {
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true
}
},
password: {
type: DataTypes.STRING,
allowNull: false
},
name: {
type: DataTypes.STRING
}
})
return User;
}
The issue was in the API, it's supposed to be router.post
router.post("/updateName", auth, async (req, res) =>{
const { ime, url } = req.body;
const uid = req.session.passport.user;
console.log(ime);
db.User.findOne({where: {id: uid}})
.then(record => {
let values = {
name: ime,
webhook: url
}
record.update(values).then( updatedRecord => {
console.log(`updated record ${JSON.stringify(updatedRecord,null,2)}`)
res.status(200).json({ message: "success"});
})
}
})
.catch((error) => {
// do seomthing with the error
throw new Error(error)
})
});
You can try the following code
await db.User.update({
name: ime,
webhook: url
}, { where: { id: uid } });
When defining your model I don't see the webhook field

Fetch API response with react and Express.js won't show any result with console.log

I have a login form that sends data to an Express.js backend using fetch. On the client side, when I want to display the results of the fetch call when it completes nothing is displayed (and it never reaches the data callback). I don't seem to be getting any errors, but I know that the data is successfully being sent to the backend.
Here's the Express.js server code:
const express = require('express');
const User = express.Router();
const bcrypt = require('bcrypt');
const user = require('../Models/user');
this is edited
function loginRouteHandler(req, res) {
user.findOne(
{
where: {
userName: req.body.userName,
},
},
)
.then((data) => {
if (bcrypt.compareSync(req.body.password, data.password)) {
req.session.userName = req.body.userName;
req.session.password = req.body.password;
console.log(req.session);
res.status(200).send('Success!');
} else {
res.status(400).send('some text');
}
});
}
User.route('/').get(getRouteHandler);
User.route('/register').post(postRouteHandler);
User.route('/login').post(loginRouteHandler);
module.exports = User;
And here's the fetch call:
fetch('http://localhost:4000/login',{
method: 'POST',
headers: {
'Accept': 'application/json,text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({
userName: this.state.userName,
password: this.state.password,
}),
}).then((response)=>{
if(response.ok){
console.log(response)
}
else {
console.log("a problem")
}
}).then((data)=>{
console.log(data)
});
In your loginRouteHandler, if the bcrypt compare succeeds nothing is returned in the response. So in the first branch of the if statement, put res.send('Success!') or something similar.
Here's an example:
function loginRouteHandler(req, res) {
user.findOne(
{
where: {
userName: req.body.userName,
},
},
)
.then((data) => {
if (bcrypt.compareSync(req.body.password, data.password)) {
req.session.userName = req.body.userName;
req.session.password = req.body.password;
console.log(req.session);
res.status(200).send('Success!');
} else {
res.status(400).send('some text');
}
});
}
UPDATE: you're also not getting the output of the fetch response with .text() or .json(). You have to update the fetch call to the following:
fetch(/* stuff */).then((response)=>{
if(response.ok){
console.log(response)
}
else {
console.log("a problem")
}
return response.text()
}).then((data)=>{
console.log(data)
});
Remove ok from response.ok
Remove .then((data)=>{ console.log(data) });
And check console log.
}).then((response)=>{
if(response){
console.log(response)
}
else {
console.log("a problem")
}
}).then((data)=>{
console.log(data)
});

Categories

Resources