How can I store my JWT Token in localstorage? - javascript

userAction.js -> Frontend, Action
export const login = (userID, password) => async (dispatch) => {
try {
dispatch({ type: USER_LOGIN_REQUEST });
const url = "http://localhost:8080/authenticate/";
const config = {
auth: {
username: userID,
password,
},
};
const data = {};
const response = await axios.post(
url,
data,
config,
)
dispatch({ type: USER_LOGIN_SUCCESS, payload: config});
if (response.status === 200) {
// Login succeeded
const token = response.data.token;
console.log("TOKEN\n" + token);
config.token = response.data.token;
console.log(response.data.token);
}
localStorage.setItem("userInfo", JSON.stringify(config) );
}
My login function in REST Server :
exports.login = async (req,res) =>{
const b64auth = (req.headers.authorization || '').split(' ')[1] || '';
const [userID, password] = Buffer.from(b64auth, 'base64').toString().split(':');
const user = await User.findOne({ userID: userID });
if(!user) return res.status(400).send('User not found');
const validPass = await bcrypt.compare(password, user.password);
if(!validPass) return res.status(400).send('Incorrect Password');
//const token = generateToken(user.userID);
let payload = {
userID: user.userID
}
const token = generateToken(userID);
res.header('Authorization', 'Bearer ' + token).json(user);
return token;
}
I generate my token this way :
const generateToken = (_id) => {
console.log('Signing token for ID ', _id);
console.log('Secret key is ', process.env.JWT_KEY);
const token = jwt.sign({ _id}, process.env.JWT_KEY, {
expiresIn: "30d",
});
console.log('Signed token: ', token);
return token;
};
I try to store my token in my "userInfo" State .. but only username and password is displayed not token ..It works before .. but I don´t know why it´s not working anymore ^^ I´m completely at a loss
I hope someone sees the error
my Console gives me the detail:
TOKEN
undefined

You are expecting response.data to be an object. In that case update your API handler to return property token in an object:
exports.login = async (req,res) =>{
const b64auth = (req.headers.authorization || '').split(' ')[1] || '';
const [userID, password] = Buffer.from(b64auth, 'base64').toString().split(':');
const user = await User.findOne({ userID: userID });
if(!user) return res.status(400).send('User not found');
const validPass = await bcrypt.compare(password, user.password);
if(!validPass) return res.status(400).send('Incorrect Password');
//const token = generateToken(user.userID);
let payload = {
userID: user.userID
}
const token = generateToken(userID);
return res.header('Authorization', 'Bearer ' + token).json({ user, token });
}
Hopefully that helps!

Related

compare json result from API response

I'm trying to send API with axios to check if login creds are correct, and I can't retrieve the result from the API.
the mongodb .find finds the correct row but then i want to compare the result from mongo to the api parameters.
for example:
I send to the API {email:somthing#sms.com, password: somthing} and compare with the row {id..,email:somthing, pass: somthing}
code:
API
export default async function handler(request, response){
try{
const { mongoClient } = await connectedToDatabase();
const db = mongoClient.db("db");
const table = db.collection("users");
const {email,password} = request.body
const result = await table
.find({email})
.limit(1)
.toArray();
if (result[0].password == password){
console.log('pass correct')
}
else{
console.log('false');
}
response.status(200).json(result);
}
catch(e){
console.error(e);
}
}
Request:
const clickLogin = async (e) => {
const registerDetails = {
'email': email,
'password': password
};
e.preventDefault();
const res = await axios ({
method: 'POST',
headers:{ 'Content-Type': 'application/json'},
url: 'api/list',
data: JSON.stringify(registerDetails),
});
if (res.status == 200){
console.log(res);
console.log(res.data[0].NickName);
}
setNickName('');
setEmail('');
setPassword('');
};
I managed to find the value of object by ['key'] and then compared it.
code:
export default async function handler(request, response){
try{
const { mongoClient } = await connectedToDatabase();
const db = mongoClient.db("db");
const table = db.collection("users");
const {Email,password} = request.body
const result = await table
.find({Email})
.limit(1)
.toArray();
console.log(result[0]);
if (result[0] !== undefined){
if(result[0]['password'] === password){
console.log('True welcome!');
response.status(200).json(result);
}
else{
console.log('User/Pass not exist!.');
response.status(400).json({ msg: "Email or Password are not exist!" });
}
}
else{
console.log('User/Pass not exist!.');
response.status(400).json({ msg: "Email or Password are not exist!" });
}
}
catch(e){
console.error(e);
}
}

Invalid signature error when trying to refresh a token

I have this weird error every time I try to refresh a token after the session token expired
{ success: false, message: 'invalid signature' }
This is the function where I try to refresh my token:
async function updateToken(currentToken, refreshToken) {
const response = await fetch(`${basePath}/auth/token`, {
method: 'GET',
headers: getTokenAndRefreshAuthHeaders(currentToken, refreshToken)
});
const token = await response.json();
await saveTokenInLocalStorage(token);
return token;
}
This is the /token endpoint:
router.get('/token', async (req, res) => {
try {
const token = await TokenController.getTokenFromRequest(req);
const refreshToken = await TokenController.getRefreshTokenFromRequest(req);
await TokenController.verifyRefreshToken(refreshToken);
const decoded = jwt.decode(token);
res.json({
token: TokenController.generateToken(decoded.email, decoded.type, decoded.id)
});
} catch (error) {
ErrorController.errorCallback(error, res);
}
});
and this is my getTokenFromRequest function:
static getTokenFromRequest(req) {
let token = req.body.token || req.headers['x-access-token'] || req.headers['authorization'] || req.params.token;
return TokenController.getNormalizedToken(token);
}
I'm not sure what I'm doing wrong, some console.log() that I placed in those 3 places suggest that the culprit is the getTokenFromRequest but I'm not quite sure

JWT Authentication error on Updating an item in MERN stack

Can't update/edit. It's a basic MERN CRUD app with JWT, RTK, and MUI. When I try, I get
PUT http://localhost:3000/api/purchases/[object%20Object] 401 (Unauthorized) xhr.js:210
in Chrome Dev Tools. Also I'm getting 2 error messages saying Not Authorized tableForm.jsx:29 and Not Authorized Table.jsx:17
Those messages are originating from a console.log in my auth middleware, but only happen when updating. Get, Create, and Delete all work fine.
const protect = asyncHandler(async (req, res, next) => {
let token
if(req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
try{
//Get token from header
token = req.headers.authorization.split(' ')[1]
//Verify token
const decoded = jwt.verify(token, process.env.JWT_SECRET)
//Get user from the token
req.user = await User.findById(decoded.id).select('-password')
next()
} catch (error) {
console.log(error)
res.status(401)
throw new Error('Not authorizecd')
}
}
if (!token) {
res.status(401)
throw new Error('Not authorized, no token')
}
} )
In Table and tableForm, I also have
useEffect(() => {
if (isError) {
console.log(message)
}
Maybe my Slice or Controller is wrong, but I've checked similar questions and projects on here and GitHub, so idk. Here, they are:
//Update Purchase
export const updatePurchase = createAsyncThunk(
'purchases/update',
async (purchaseData, thunkAPI) => {
try {
const token = thunkAPI.getState().auth.user.token
return await purchaseService.updatePurchase(purchaseData, token)
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString()
return thunkAPI.rejectWithValue(message)
}
})
//extra reducers part
.addCase(updatePurchase.pending, (state) => {
state.isLoading = true
})
.addCase(updatePurchase.fulfilled, (state, action) => {
state.isLoading = false
state.isSuccess = true
state.purchases = state.purchases.map((purchase) => purchase._id === action.payload._id ? action.payload : purchase)
})
.addCase(updatePurchase.rejected, (state, action) => {
state.isLoading = false
state.isError = true
state.message = action.payload
})
//"Service" part
const updatePurchase = async (purchaseId, purchaseData, token) => {
const config = {
headers: {
Authorization: `Bearer ${token}`
}
}
const response = await axios.put(API_URL + purchaseId, purchaseData, config)
return response.data
}
//and the Controller
const updatePurchase = asyncHandler(async (req, res) => {
const purchase = await Purchase.findById(req.params.id)
if (!purchase){
res.status(400)
throw new Error('Purchase not found')
}
//const user = await User.findById(req.user.id)
//Check for user
if(!req.user) {
res.status(401)
throw new Error('User not found')
}
//Make sure the user matches the purchases
if (purchase.user.toString() !==req.user.id) {
res.status(401)
throw new Error('User not authorized')
}
const updatedPurchase = await Purchase.findByIdAndUpdate(req.params.id, req.body, {
new: true,
})
res.status(200).json(updatedPurchase)
})
Any and all help would be appreciated. I've tried everything and have been working on this for days, but I'm kind of new so I'm sure I'm missing something obvious.
Here is the git repo if needed.
https://github.com/LazAustin/final_license_manager.git
Here is the front end where updatePurchase is used. I'm not sure what to pass anymore. The ID and/or the whole Purchase? Either way I've tried everything.
function EditForm({purchase}) {
const [title, setTitle] = useState(purchase.title);
const [producer, setProducer] = useState(purchase.producer);
... //shortened for reading purposes
const [notes, setNotes] = useState(purchase.notes);
const dispatch = useDispatch()
const onSubmit = (e) => {
e.preventDefault()
const purchaseData = {
title,
producer
... //just shortening for reading purposes
notes,
id: purchase._id
}
dispatch(updatePurchase(purchaseData)) // <-tried different combinations of id and purchase on front and back end.
//I think its supposed to be updatePurchase(purchase._id, purchaseData) and same on the slice but that didnt work either
}
Nvm! Figured it out, just in case anyone else rolls on this question. Forgot my id was set to "purchaseId" in the Service. Changed my service back to what I originally had it as (below). Then below that is my new front end with purchaseId: purchase._id
const updatePurchase = async (purchaseData, token) => {
const { purchaseId, ...body } = purchaseData;
const config = {
headers: {
Authorization: `Bearer ${token}`
}
}
const response = await axios.put(API_URL + purchaseId, body, config)
return response.data
}
const onSubmit = (e) => {
e.preventDefault();
const purchaseData = ({
title,
...,
notes,
purchaseId: purchase._id
})
dispatch(updatePurchase(purchaseData))
}

How can I find a Post of a User?

Hello I want to find posts which user has made ..
I do my request with JWT Token:
###
http://localhost:8080/forum/getByOwnerID
Authorization: Bearer {{token}}
This is my create function :
exports.create = async (req, res) => {
const { forumName, forumDescription } = req.body;
const token = req.token;
const forumExist = await Forum.findOne({ forumName: req.body.forumName });
if(forumExist){
res.status(400).send("Forum Exists already.");
}
try{
const owner = await User.findOne({userID:token._id});
if (!forumName || !forumDescription) {
res.status(400);
throw new Error("Please Fill all the feilds");
return;
}
else {
const newForum = new Forum({ forumName, forumDescription,user: owner.userID });
newForum.user = owner;
const createdNote = await newForum.save();
res.status(201).json(createdNote);
}
}catch(err){
res.status(400).send(err);
}
};
This is my function where I want to get the Posts which the user has made :
exports.getByToken = async (req, res, next) => {
const forum = await Forum.findById( {user: req.token._id} );
if (forum) {
res.json(forum);
} else {
res.status(404).json({ message: "Forum not found" });
}
res.json(forum);
}
And this is model which I have for Post:
const forumSchema = ({
forumName: {
type: String,
required: true,
},
forumDescription: {
type: String,
required: true,
},
user: {
type: Schema.Types.ObjectId,
ref: 'user'
},
published_on: {
type: String,
default: moment().format("LLL")
},
});
Everytime I do a request it has this error :
UnhandledPromiseRejectionWarning: CastError: Cast to ObjectId failed for value "{ user: 'admin' }" (type Object) at path "_id" for model "Forum"
my generate Token :
const generateToken = (_id, userID) => {
console.log('Signing token for ID ', _id,userID);
console.log('Secret key is ', process.env.JWT_KEY);
const token = jwt.sign({ _id,userID}, process.env.JWT_KEY, {
expiresIn: "30d",
});
console.log('Signed token: ', token);
return token;
};
As you are using findById, you should only send the id as argument function.
If you want to search with filter query, use find method

TypeError: verifyJsonWebToken is not a function

I created two model (I use MongoDB):
User: name, email, password, isBanned, blogPosts[].
BlogPost: title, content, date, author.
with author: {type:ObjectId, ref: 'User'}
I want insert a new blog post with Json Web Token. But I received error: : TypeError: verifyJWT is not a function
Here is my code:
const { verifyJWT } = require('./User')
const insertBlogPost = async (title, content, tokenKey) => {
try {
//Check Login with tokenKey
let signedInUser = await verifyJWT(tokenKey) //<-Code not run here
let newBlogPost = await BlogPost.create({
title, content,
date: Date.now(),
author: signedInUser
})
await newBlogPost.save()
await signedInUser.blogPosts.push(newBlogPost._id)
await signedInUser.save()
return newBlogPost
} catch(error) {
throw error
}}
module.exports = {
BlogPost,
insertBlogPost,
}
Here's verifyJWT from User
const jwt = require('jsonwebtoken')
const verifyJWT = async (tokenKey) => {
try {
let decodedJson = await jwt.verify(tokenKey, secretString)
if(Date.now() / 1000 > decodedJson.exp) {
throw "Token timeout, please Login again"
}
let foundUser = await User.findById(decodedJson.id)
if (!foundUser) {
throw "Can not find user with this token"
}
if(foundUser.isBanned === 1) {
throw "User looked"
}
return foundUser
} catch(error) {
throw error
}}
module.exports = { User, verifyJWT }
And here's my router:
router.post('/insertBlogPost', async (req, res) =>{
let {title, content} = req.body
//Client must send tokenKey
let tokenKey = req.headers['x-access-token']
try {
let newBlogPost = await insertBlogPost(title, content, tokenKey)
res.json({
result: 'ok',
message: 'Create BlogPost successfully!',
data: newBlogPost
})
} catch(error) {
res.json({
result: 'failed',
message: `${error}`
})
}})
Github: https://github.com/vantuan1303/authentication

Categories

Resources