Why is couchdb login good but couchdb session empty, using vuejs and pouchdb - vue.js

Using Vusjs, pouchdb-browser, CouchDB, pouchdb-authentication
I want to check if a session is open to use for offline stay logged in.
When I login with db.logIn from pouchdb-authentication:
response: {ok: true, name: "01HAYJ", roles: Array(1)}
When I run "getSession" i get userCtx.name as null
session response:
info:
authentication_handlers: Array(2)
0: "cookie"
1: "default"
length: 2
__proto__: Array(0)
__proto__: Object
ok: true
userCtx:
name: null
roles: Array(0)
Here is a snippet of my action:
setUser({commit, dispatch},payload){
console.log('store action payload: ', payload);
var user = payload.user;
var pass = payload.pass
db.logIn(user, pass , function (err, response) {
if (err) {
if (err.name === 'unauthorized' || err.name === 'forbidden') {
alert("Login failed, check user or password!")
} else {
}
}
}).then(function (response) {
// handle response
console.log('response: ', response);
db.getSession(function (err, response) {
if (err) {
// network error
console.log('session error: ', error);
} else if (!response.userCtx.name) {
// nobody's logged in
console.log('nobody is logged in' );
} else {
// response.userCtx.name is the current user
console.log('response.userCtx.name: ', response.userCtx.name );
commit('setUser', response.userCtx.name)
router.push({ name: 'dashboard'})
}
});
commit('setUser', payload.user)
}).catch(function (error) {
// handle error
console.log('error: ', error);
dispatch('logOut');
});
}

There is a mix of callbacks and promises in your code. It is possible that db.login is not completing before the db.session call. I am not sure from the snippet if the "then" is part of another Promise, but here is how I would structure the call:
setUser({commit, dispatch},payload){
console.log('store action payload: ', payload);
var user = payload.user;
var pass = payload.pass
db.logIn(user, pass).then(function (response) {
// handle response
console.log('response: ', response);
return db.getSession();
}).then(response) {
//check user details from the session response here
commit('setUser', payload.user)
}).catch(function (error) {
// handle error
console.log('error: ', error);
dispatch('logOut');
});
}
(this is an example - there may be typos!)

Related

Aws amplify google SSO, sign in is not persisted in local storage

The app is built with react.
I am having some trouble making sure the user stays loggedIn after signing in via Google SSO. Following are my relevant imports
import { Amplify, Auth, Hub, Cache } from "aws-amplify";
import awsExports from "./aws-exports";
Hi, I am using the following code. To listen to sign in events. The Sign in is successful, and stores all the relevant info in the local Storage for the tab that was used to log in. However, if I open another tab the information is not there, and therefore the currentAuthenticatedUser returns unauthenticated.
If I use a username, password log in, the data persists across tabs.
I am using ImplicitGrant, with Google.
useEffect(() => {
// Side Effect
console.log("not app use effect");
// fetchDevices();
if (!authenticated) {
console.log("fetching session", Cache.getItem("userSession"));
console.log("getting my item", localStorage.getItem("myItem"));
Auth.currentAuthenticatedUser({
bypassCache: false, // Optional, By default is false. If set to true, this call will send a request to Cognito to get the latest user data
})
.then((user) => {
console.log("got suer datal", user);
if (user?.username) {
console.log("usernname exists", user.username.startsWith("google"));
if (user.username.startsWith("google")) {
console.log("modifying the username");
user.username = user?.attributes.email.split("#")[0];
}
console.log("user autheticatd", user);
setAuthenticated(true);
// rememberDevice();
setCurrentActiveUser(user);
store.dispatch(
getUserExistingAPIKey(user?.signInUserSession?.idToken?.jwtToken)
);
store.dispatch({
type: SET_ID_TOKEN,
payload: user?.signInUserSession?.idToken?.jwtToken,
});
// getExistingUserAPIKey(user?.signInUserSession?.idToken?.jwtToken);
}
})
.catch((e) => {
console.log("the first login failed");
console.log(e);
});
}
const unsubscribe = Hub.listen("auth", ({ payload: { event, data } }) => {
switch (event) {
case "signIn":
console.log("sign in event", data);
setAuthenticated(true);
setCurrentActiveUser(data);
store.dispatch(
getUserExistingAPIKey(data?.signInUserSession?.idToken?.jwtToken)
);
store.dispatch({
type: SET_ID_TOKEN,
payload: data?.signInUserSession?.idToken?.jwtToken,
});
rememberDevice();
Auth.currentAuthenticatedUser({
bypassCache: true, // Optional, By default is false. If set to true, this call will send a request to Cognito to get the latest user data
})
.then((user) => {
console.log("got suer datal", user);
if (user?.username) {
console.log(
"usernname exists",
user.username.startsWith("google")
);
if (user.username.startsWith("google")) {
console.log("modifying the username");
user.username = user?.attributes.email.split("#")[0];
}
console.log("user autheticatd", user);
setAuthenticated(true);
rememberDevice();
setCurrentActiveUser(user);
store.dispatch(
getUserExistingAPIKey(
user?.signInUserSession?.idToken?.jwtToken
)
);
store.dispatch({
type: SET_ID_TOKEN,
payload: user?.signInUserSession?.idToken?.jwtToken,
});
// getExistingUserAPIKey(user?.signInUserSession?.idToken?.jwtToken);
}
})
.catch((e) => {
console.log("the first login failed");
console.log(e);
});
break;
case "signUp":
console.log("sign up event");
setAuthenticated(true);
setCurrentActiveUser(data);
break;
case "signOut":
console.log("sign out event");
// setUser(data);
setAuthenticated(false);
setCurrentActiveUser(null);
break;
case "cognitoHostedUI":
console.log("cognito hosted ui event", data);
Auth.currentSession()
.then((session) => {
// Save the session info to the cache
console.log("session", session);
Cache.setItem("userSession", session);
localStorage.setItem("myItem", session);
})
.catch((err) => {
console.log("err", err);
});
Auth.currentAuthenticatedUser({
bypassCache: true, // Optional, By default is false. If set to true, this call will send a request to Cognito to get the latest user data
})
.then((user) => {
console.log("updated user", user);
let token = data?.signInUserSession?.idToken?.jwtToken;
Auth.federatedSignIn(
"google",
{
token,
expires_at: 1000 + new Date().getTime(), // the expiration timestamp
},
user
)
.then((cred) => {
// If success, you will get the AWS credentials
console.log("cred", cred);
return Auth.currentAuthenticatedUser();
})
.then((user) => {
// If success, the user object you passed in Auth.federatedSignIn
console.log("fetched user", user);
setAuthenticated(true);
// rememberDevice();
setCurrentActiveUser(user);
store.dispatch(
getUserExistingAPIKey(
user?.signInUserSession?.idToken?.jwtToken
)
);
store.dispatch({
type: SET_ID_TOKEN,
payload: user?.signInUserSession?.idToken?.jwtToken,
});
})
.catch((e) => {
console.log(e);
});
})
.catch((e) => {
console.log("error", e);
});
break;
case "customOAuthState":
console.log("custom oauth event", data);
setAuthenticated(true);
setCurrentActiveUser(data);
break;
case "signIn_failure":
console.log("user sign in failed", data);
break;
case "tokenRefresh":
console.log("token refresh succeeded");
break;
case "tokenRefresh_failure":
console.log("token refresh failed");
break;
case "autoSignIn":
console.log("auto sign in");
break;
case "autoSignIn_failure":
console.log("auto sign in failed");
break;
case "cognitoHostedUI_failure":
console.log("cognito hosted ui failed");
Auth.federatedSignIn({ provider: "Google" })
.then(async (cred) => {
// If success, you will get the AWS credentials
console.log(cred);
Auth.currentAuthenticatedUser({
bypassCache: false, // Optional, By default is false. If set to true, this call will send a request to Cognito to get the latest user data
})
.then((user) => {
console.log("got suer datal", user);
if (user?.username) {
console.log(
"usernname exists",
user.username.startsWith("google")
);
if (user.username.startsWith("google")) {
console.log("modifying the username");
user.username = user?.attributes.email.split("#")[0];
}
console.log("user autheticatd", user);
setAuthenticated(true);
rememberDevice();
setCurrentActiveUser(user);
store.dispatch(
getUserExistingAPIKey(
user?.signInUserSession?.idToken?.jwtToken
)
);
store.dispatch({
type: SET_ID_TOKEN,
payload: user?.signInUserSession?.idToken?.jwtToken,
});
// getExistingUserAPIKey(user?.signInUserSession?.idToken?.jwtToken);
}
})
.catch((e) => {
console.log("the first login failed");
console.log(e);
});
})
.catch((e) => {
console.log("the second login failed");
console.log(e);
});
break;
case "customState_failure":
console.log("custom state failure", event, data);
break;
default:
console.log("DEFAUL CASE", event, data);
break;
}
});
return unsubscribe;
});
I receive a cognitoHostedUI event after signingIn. I tried to store data manually but it never persists when I open a new tab.
any help would be appreciated, seriously considering, getting off of cognito/amplify.

Using asynchronous methods but Express still returning 503 (NodeJS)

I'm developing a web application in NodeJS with an Express back-end. The application is running smoothly except that when a user signs up, a somewhat long operation is called on the back end that involves saving to a database, resizing an image, etc. It takes a few seconds for this process to complete, and during this time anyone else who makes a request to the server will receive a 503 error and will be unable to do anything, whether that's sending or receiving data. I am using asynchronous functions in order to do this whole process. I am using multer to read the file, fs to read and write the file, and Jimp to resize the image. The code is as shown below.
module.exports = function(router) {
router.route('/')
.post(function(req, res, next) {
upload(req, res, function(err) {
var salt = bcrypt.genSaltSync(saltRounds);
var identifier = makeIdentifier(req.body.first_name.trim())
let emailNotifications = 0;
if (req.body.email_notifications === 'true') {
emailNotifications = 1;
}
var signup = {
identifier: identifier,
first_name: toTitleCase(req.body.first_name.trim()),
last_name: req.body.last_name.trim(),
hobby: req.body.hobby,
type: 'user',
email: req.body.email.trim(),
email_notifications: emailNotifications,
password: bcrypt.hashSync(req.body.password, salt)
};
let ascii = /^[ -~]+$/;
for (var propertyName in signup) {
if (!ascii.test(signup[propertyName])) {
res.json({
reason: "invalid-characters"
});
return;
}
}
if (req.file.size > 5000000) {
res.json({
reason: "file-size"
});
return;
}
let emailExists = false;
db.doesEmailExist(req.body.email, function(err, results) {
if (err) {
res.status(500).send("Server error");
return;
} else {
if (results.length > 0) {
res.json({
reason: "email-exists"
});
return;
} else {
fs.readFile(req.file.path, function(err, data) {
let newPath = __dirname + "/profile-pictures/" + identifier + ".png";
fs.writeFile(newPath, data, function(err) {
if (err) {
console.log(err);
} else {
try {
Jimp.read(newPath, (err, file) => {
if (err) throw err;
file
.resize(300, 300) // resize
.quality(60) // set JPEG quality
.write(newPath); // save
});
} catch (error) {
res.json({
reason: "image-properties"
});
return
}
}
});
});
db.signup(signup, function(err, results) {
if (err) {
res.status(500).send("Server error");
return;
} else {
res.json({
success: true
});
return;
}
})
}
}
})
})
});
}
What is causing the server to respond with a 503 error? Any help would be appreciated, thanks!

undefined jwt token react/express

I am implementing a JWT authentication on a login/registration system. When there is a successful login/registration I am setting a user token in localStorage.
Problem is when I check my localStorage the user key is present but the value is undefined. I think the issue might be in my axios post or in my express file but I can't quite figure it out.
// my action creator
export function login(user, history) {
return async (dispatch) => {
axios.post('/api/login', { user })
.then(res => {
dispatch({ type: AUTHENTICATED });
localStorage.setItem('user', res.data.token);
history.push('/');
})
.catch((error) => {
dispatch({
type: AUTHENTICATION_ERROR,
payload: 'Invalid email or password'
});
});
};
}
The data is reaching my api correctly. The item is being set but the value res.data.token is undefined.. Below is my express file
// login.js (/api/login)
router.post('/', function(req, res) {
var email = req.body.user.email;
var password = req.body.user.password;
// TODO: create db file and import connection
var connection = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "dbname",
port: 3307
});
connection.connect(function(err) {
if(err) {
console.log(err);
} else {
connection.query("SELECT ID, Password FROM Users WHERE Email = ?", [email], function(err, result) {
if(err) {
console.log('Could not find account');
res.send(err);
} else {
var id = result[0].ID;
bcrypt.compare(password, result[0].Password, function(err, result) {
if(result) {
console.log(id);
res.json({ id });
} else {
console.log('Incorrect password');
}
});
}
});
}
});
});
Since the res.data.token in my action creator is returning undefined does that mean the response in my express file ( res.json([id]) ) is just returning defined?
You are not sending the response properly.
res.json([id]); Its just sending the array of id. That's why res.data.token is undefined. as data does not contain an object.
Send proper object like:
res.json({id});

Resetting password using express and JWT token

I am trying to reset the user password using the following code and Postman.
But what I realised is that there is no user after I generate the token. the console is saying null;
// Reset User Password
exports.resetPassword = function (req, res) {
User.findOne({
reset_password_token: req.body.token,
reset_password_expires: {
$gt: Date.now()
}
}).exec(function (err, user) {
console.log('this user: ' + user)
if (!err && user) {
if (req.body.newPassword === req.body.verifyPassword) {
user.hash_password = bcrypt.hashSync(req.body.newPassword, 10);
user.reset_password_token = undefined;
user.reset_password_expires = undefined;
user.save(function (err) {
if (err) {
return res.status(422).send({
message: err
});
} else {
console.log(user.hash_password)
}
});
} else {
return res.status(422).send({
message: 'Passwords do not match'
});
}
} else {
return res.status(400).send({
message: 'Password reset token is invalid or has expired.'
});
}
});
};
This is how I use it in Postman
{
"newPassword": "cocacola",
"verifyPassword": "cocacola",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1YjI3NjAyNDAwOWI1NDA5ZjMwNzAzZWYiLCJpYXQiOjE1MzA5NjA2NDEwOTN9.1LjroayiTWDNevShnH30n3LxUGCrazmTaJlHgOUNvJ0"
}
and the response in Postman is message from status 400

socket.io callback is not recevied in vue.js method?

Using this vue.js method to login users:
loginUser: function () {
socket.emit('loginUser', {
email: this.email ,
password: this.password
}, function() {
console.log('rooms in callback are:', rooms);
});
}
On the server the loginUser event is handled by:
socket.on('loginUser', (newuser,callback)=> {
var body = _.pick(newuser, ['email', 'password']);
console.log('body is:', body);
User.findByCredentials(body.email, body.password).then((user) => {
return user.generateAuthToken().then((token) => {
if (token) {
console.log('token was found');
let rooms = ['Cats', 'Dogs', 'Birds'];
callback(rooms);
} else {
socket.emit('loginFailure', {'msg' : 'Login failure'});
}
}).catch((e) => {
throw e;
});
}).catch((e) => {
socket.emit('loginFailure', {'msg' : 'Login failure'});
throw e;
});
});
I can see 'token was found' printed out in the console but does not recieve the rooms being printed in the browser console. I receive no errors either.
I'm wondering whetehr it is due to how vue.js methods work? And if so, if there is a way around it?
You forgot to specify rooms as argument in the callback
loginUser: function () {
socket.emit('loginUser', {
email: this.email ,
password: this.password
}, function(rooms) { // need to have rooms argument
console.log('rooms in callback are:', rooms);
});
}