Getting a 401 (Unauthorized) on Heroku, No error on local host Mern stack being used - cookies

I have been having trouble with a MERN stack deployment, I get a 401 error on heroku, wheni try to login or use any APi call.
I am using express-sessions andi have noticed using console.log that the session on login page shows that the user have logged in but as soon as i am redirected to Dashboard, the session changes
NOte: Using AXios
Note: everything is working perfectly fine on Localhost, only facing this issue on developemnt.. and on Heroku (free v)
Code on Server.js
var express = require('express');
var session = require('express-session');
var MongoDBStore = require('connect-mongodb-session')(session);
const bodyParser = require('body-parser');
var mongoUtil = require( './utils/mongoUtil' );
const cors = require('cors');
app.use(cors({credentials: true, origin: 'https://teamdashboard0.herokuapp.com'}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var store = new MongoDBStore(
{
uri: "mongodb+srv://teamdashboard:ONgnWv4aqRwBKo8g#teamdashboard.3ivb8.mongodb.net/TeamDashboard",
databaseName: 'TeamDashboard',
collection: 'sessions'
});
store.on('error', function(error) {
console.log(error);
});
app.use(session({
secret: 'bakdhgsjcdbcbsdm',
resave: false,
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 7, // 1 week
secure: true
},
store: store,
unset: 'destroy',
saveUninitialized: false
}));
mongoUtil.connectToServer( function( err, client ) {
var user = require( './controllers/user.js' );
var colleague = require( './controllers/colleague.js' );
var team = require( './controllers/team.js' );
var news = require( './controllers/news.js' );
app.post('/register', (req, res)=>{user.register(req,res)});
app.get('/verify',(req,res)=>{user.verify(req,res)});
app.get('/login',(req,res)=>{user.login(req,res)});
app.post('/changePasswordEmail',(req,res)=>{user.sendChangePassword(req,res)});
app.put('/changePassword',(req,res)=>{user.changePassword(req,res)});
app.post('/logout', (req,res)=>{user.logout(req,res)});
app.get('/colleague/checkLimit', (req,res)=>{colleague.checkLimit(req,res)});
app.post('/colleague/add', (req,res)=>{colleague.add(req,res)});
app.delete('/colleague/delete', (req,res)=>{colleague.delete(req,res)});
app.put('/colleague/update', (req,res)=>{colleague.update(req,res)});
app.get('/colleague/all', (req,res)=>{colleague.getAll(req,res)});
app.get('/colleague/one', (req,res)=>{colleague.getOne(req,res)});
app.get('/team/all', (req,res)=>{team.allTeams(req,res)});
app.post('/team/add', (req,res)=>{team.newTeam(req,res)});
app.delete('/team/delete', (req,res)=>{team.deleteTeam(req,res)});
app.put('/team/update', (req,res)=>{team.updateTeam(req,res)});
app.get('/team/colleague/all', (req,res)=>{team.getColleagues(req,res)});
app.post('/team/colleague/add', (req,res)=>{team.addColleague(req,res)});
app.delete('/team/colleague/delete', (req,res)=>{team.deleteColleague(req,res)});
app.get('/news',(req,res)=>{news.getNews(req,res)});
app.get('/', function(req, res) {
var msg = `
Welcome to the Team Dashboard\n
Visit:
https://app.swaggerhub.com/apis-docs/Hira172/TeamDashboard/1.0.0
to view all the api and details about the backend
`
res.send(msg)
});
if (err) console.log(err);
port = process.env.PORT || 8080;
app.listen(port, () => console.log(`Server Running at port ${port}`));
} );```

Related

SvelteKit unable to set cookie

Using SvelteKit 1.0.0-next.571
My application has a login route with:
+page.server.ts => redirects to / if locals.user is set
+page.svelte => show login page
signin/+server.ts => Login and get a jwt from graphql app running on the same machine.
+server.ts:
[..]
let gqlResponse = await response.json();
if ( gqlResponse.errors ) {
console.log("ERRORS FROM GRAPHQL MIDDLEWARE:", gqlResponse.errors);
return json( { error: gqlResponse.errors, isException: true } );
}
if (gqlResponse.data.login.user && !gqlResponse.data.login.error) {
opts.cookies.set('jwt', gqlResponse.data.login.token, {
path: '/',
maxAge: SESSION_MAX_AGE
});
opts.setHeaders( { 'Access-Control-Allow-Credentials': 'true' } )
opts.setHeaders({ 'Content-Type': 'application/json' })
}
return json( gqlResponse.data.login );
and the login handler in +page.svelte :
[..]
const fetchOptions = {
method: 'POST',
//mode: 'no-cors',
//redirect: 'follow' as RequestRedirect,
body: JSON.stringify(credentials),
credentials: 'include' as RequestCredentials
}
try {
const response = await fetch('/login/signin', fetchOptions);
const login = await response.json();
if (login.error) {
handleError(login);
return false;
}
} catch (e) {
return handleException(e);
}
goto('/', { replaceState: true, invalidateAll: true} );
This works fine in localhost, but connecting another device to the local network does not set any cookies making impossible to login:
Local: http://localhost:5173/
➜ Network: http://192.168.x.x:5173/
I also tried with different fetch options and cookie settings like:
opts.cookies.set('jwt', gqlResponse.data.login.token, {
path: '/',
httpOnly: true,
sameSite: 'strict',
// secure: true
maxAge: SESSION_MAX_AGE
});
but no luck, and now 'm stuck.

ERR_CONNECTION_REFUSED when sending requests to server from NGINX app

For my production app, I'm running Unbuntu on an EC2 instance. I've cloned my repo into an /apps folder under /home.
My back end is running with PM2, and is (seemingly) working.
This is the code it's running.
// ************************
// DEPENDENCIES
// ************************
const express = require("express");
const cors = require("cors");
const bcrypt = require("bcrypt");
const passport = require("passport");
const cookieParser = require("cookie-parser");
const session = require("express-session");
const bodyParser = require("body-parser");
const Redis = require("ioredis");
const RedisStore = require("connect-redis")(session);
const app = express();
const pool = require("./db");
const path = require("path");
const authRouter = require("./routers/authRouter");
const testRouter = require("./routers/testRouter");
const modRouter = require("./routers/modRouter");
const dbRouter = require("./routers/dbRouter");
// ************************
// ENV
// ************************
const PORT = process.env.PORT || 3001;
// ************************
// MIDDLEWARE
// ************************
const redisClient = new Redis();
app.use(
cors({
credentials: true,
origin: "http://localhost:3000",
})
);
app.use(express.json());
app.use(
session({
secret: process.env.SECRET,
resave: true,
saveUninitialized: true,
store: new RedisStore({ client: redisClient }),
})
);
app.use(cookieParser("secretcode"));
app.use(passport.initialize());
app.use(passport.session());
require("./passportConfig")(passport);
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "client/build")));
}
// ************************
// ROUTES
// ************************
// **** AUTHENTICATION ****
app.use("/api/auth", authRouter);
// **** DB ****
app.use("/api/db", dbRouter);
// **** MODERATION ****
app.use("/api/mod", modRouter);
// **** TEST ****
app.use("/api/test", testRouter);
// **** CATCH ALL ****
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "client/build/index.html"));
});
// ************************
// SERVER
// ************************
app.listen(PORT, () => {
console.log(`Server started on ${PORT}`);
});
My front end is being served by NGINX. I ran npm build on the client and moved the files to /var/www/html.
In the configuration file inside the sites-available folder, I (believe) have set it up to proxy Port 3001 when a call is made to the /api url.
I don't have a URL at the moment, so i'm just using my EC2 instance's IP for the server_name.
Now in my client code, I've set the baseURL request in Axios in my api.js file
import axios from "axios";
const baseURL =
process.env.NODE_ENV === "produciton" ? "api" : "http://localhost:3001/api";
export default axios.create({
baseURL,
});
In the instance of my Login component, it sends a POST request to the server to '/auth/login'
import axios from "./api";
const postLogin = (username, password) => {
return axios
.post(
`/auth/login`,
{
username,
password,
},
{
withCredentials: true,
}
)
.catch((err) => {
console.log(err);
})
.then((response) => response);
};
export default postLogin;
However, when I attempt to do just that in my deployed app I get ERR_CONNECTION_REFUSED.
Console Output
So I know the client is sending a request to the correct location, but for some reason it's being refused.

AWS cognito not storing cookies in prod

Context:
I am using the amazon-cognito-identity-js SDK for authentication, as I am not using amplify for this project, only need to use cognito services. So far locally, I can do pretty much every fine, tokens come back and using the new AmazonCognitoIdentity.CookieStorage() it seems to be to store cookies locally using ({ domain: 'localhost', secure: 'false' }).
Also using nextjs v10.0.6
Problem
I tried to deploy the app to netlify and after installing it gives me back the tokens but does not store them in cookies on my browser.
Here is the snippet of code that I am using to sign in a user, there is a use case where the user was created by the admin, and will be forced to change password, thus the redirect to /changePassword
Any guidance would be amazing! My suspicion is that I am not configuring the domain right... but have tried every combination such as, removing the https, only including the autoGenerated subdomain part, etc
export const userPoolData = (): ICognitoUserPoolData => ({
UserPoolId: process.env.USER_POOL_ID || '',
ClientId: process.env.CLIENT_ID || '',
Storage: new CookieStorage({
domain: 'https://<autoGeneratedURL>.netlify.app',
secure: true,
expires: 10,
path: '/',
}),
});
const authenticationData = {
Username: username,
Password: password,
};
const authenticationDetails = new AuthenticationDetails(authenticationData);
const poolData = userPoolData();
const userPool = new CognitoUserPool(poolData);
console.log({ poolData });
const userData = {
Username: username,
Pool: userPool,
Storage: new CookieStorage({
domain: 'https://<autoGeneratedURL>.netlify.app',
secure: true,
expires: 10,
path: '/',
}),
};
const cognitoUser: CognitoUser = new CognitoUser(userData);
const userTokens: Pick<ResponseMessage, 'tokens'> = {};
console.log(authenticationData);
const authResponse = new Promise(() => {
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: (result) => {
console.log(result);
router.push({ pathname: '/' });
},
onFailure: (error) => {
console.log(error);
if (error.code !== 'InvalidParameterException' && error.code !== 'NotAuthorizedException') {
router.push({ pathname: '/changePassword', query: { username, password } });
}
},
});
});
try {
await authResponse;
} catch (error) {
return {
success: false,
code: 500,
error,
};
}
In case anyone runs into this, it turned out my suspicion was right and the fault was in the domain pattern, for a netlify app it should be configured as domain: <autoGeneratedURL>.netlify.app

Graphql Apollo setting cookies is dont working

I'm trying to set cookies in apollo client.
I'm setting the response cookie which works fine, also working on graphql playground with setting "request.credentials": "same-origin", or "include" and it stores cookies successfully.
My problem starts when I'm trying to store cookies from FE app (React, Apollo client). When i put the credentials: "same-origin" the app is working but the cookies are not saved. And when i use "include" the queries are cors blocked.
FRONTEND
const RouterComponent: FC = () => {
const cache = useMemo(() => {
return new InMemoryCache();
}, []);
const client = useMemo(() => {
const token = localStorage.getItem('token') || 'token';
const httpLink = createHttpLink({
uri: 'http://localhost:4000/graphql',
credentials: 'include',
headers: {
authorization: token ? `Bearer ${token}` : '',
},
});
const link = from([
httpLink,
createUploadLink({
uri: 'http://localhost:4000/graphql',
}),
]);
return new ApolloClient({
link,
cache,
typeDefs,
});
}, [cache]);
return (
<ApolloProvider client={client}>
<Switch>
<Route exact path="/" component={MainPage} />;
<Route exact path="/:category" component={Category} />;
</Switch>
</ApolloProvider>
);
};
QUERY
games: (_: any, args: any, {req, res}: any) => {
const refresh_token = sign({userId: "123"}, "secret", {expiresIn: "7d"})
const access_token = sign({userId: "123"}, "secret", {expiresIn: "15min"})
res.cookie('refresh-token', refresh_token, {expire: 60 * 60 * 24 * 7}) // 7 days
res.cookie('access-token', access_token, {expire: 60 * 15}) // 15 mins
return Game.find()
}
SERVER.TS
const { ApolloServer } = require( 'apollo-server-express');
const {typeDefs} = require( './typeDefs');
const {resolvers} = require( './resolvers');
const express = require( 'express');
const cors = require( 'cors');
const path = require( 'path');
const bodyParser = require( 'body-parser');
const mongoose = require("mongoose");
const dotenv = require('dotenv');
const MONGO_CONNECTION = ""
const app = express();
export default (async function () {
try {
await mongoose.connect(MONGO_CONNECTION, {
useNewUrlParser: true,
useUnifiedTopology: true})
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req, res }: any) => {
return {
req,
res
};
},
});
const corsConfig = {
origin: '*',
credentials: true,
allowedHeaders: ['Content-Type', 'Authorization'],
};
dotenv.config();
app.use(function (req: any, res: any, next: any) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/images', express.static(path.join(__dirname, 'images')));
const dir = path.join(process.cwd(), 'images');
app.use(express.static(dir));
app.use(express.static('public'))
app.use(express.static('files'))
server.applyMiddleware({ app, cors: corsConfig });
app.listen({ port: 4000 }, () =>
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
)
} catch (err) {
console.error(err);
}
})();
thank you for any help

Parse LiveQuery not receiving events AWS EB + Redis

I am trying to set up parse LiveQuery but am getting stuck. On the client I am able to open the connection, but the LiveQuery won't update the client when I make a change on the server. What am I doing wrong? Is there a better way to set up?
Here is what I have going on in the client:
Parse.liveQueryServerURL = 'ws://myawsEB-LiveQuery.com'
var Message = Parse.Object.extend('Room');
var query = new Parse.Query(Message);
query.include("messages");
// Subscribes to incoming messages
query.subscribe().then(subscription =>{
subscription.on('open', () => {
console.log('subscription opened'); // THIS WORKS!
});
subscription.on('create', function (message) {
console.log("create: ", message); //THIS DOES NOT WORK
});
subscription.on('update', function (message) {
console.log("update: ", message); //THIS DOES NOT WORK
});
})
.catch(error => {
console.log(error)
});
My AWS Setup:
AWS EB - Main App
AWS EB - Parse LiveQuery
AWS ElastiCache - Redis
Here is my server config:
//Main APP
var api = new ParseServer({
appName: "app-name",
databaseURI: databaseUri,
cloud: process.env.CLOUD_CODE_MAIN,
appId: process.env.APP_ID,
masterKey: process.env.MASTER_KEY
fileKey: process.env.FILE_KEY,
serverURL: process.env.SERVER_URL,
publicServerURL: process.env.SERVER_URL,
clientKey: process.env.CLIENT_KEY,
javascriptKey: process.env.JAVASCRIPT_KEY,
liveQuery: {
classNames: ["Room", "Messages"], // List of classes to support for query subscriptions
redisURL: process.env.redisURL
},
databaseOptions: { poolSize: 500 },
maxUploadSize: "5mb",
verbose: true
});
var port = process.env.PORT || 1337;
var httpServer = require('http').createServer(app);
httpServer.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
Here is my LiveQuery Server Settings:
//Live Query Server
var express = require('express');
var cors = require('cors')
var ParseServer = require('parse-server').ParseServer;
var app = express();
app.use(cors());
// We include the lines below so that we can hit `/` and it passes the Elastic Beanstalk Health Check
app.get('/', function(req, res) {
res.status(200).send('Make sure to star the parse-server repo on GitHub!');
});
var port = process.env.PORT || 1338;
var httpServer = require('http').createServer(app);
httpServer.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
ParseServer.createLiveQueryServer(httpServer, {
appId: process.env.APP_ID, // same as main-index.js file below
masterKey: process.env.MASTER_KEY, // same as main-index.js
serverURL: process.env.SERVER_URL, // socket.myApp.com
javascriptKey: process.env.JAVASCRIPT_KEY,
redisURL: process.env.redisURL,
websocketTimeout: 10 * 1000,
cacheTimeout: 60 * 600 * 1000,
verbose: true
});
Check your Nginx Configuration.
Here is a great guide https://github.com/SoBump/ParseLiveQueryHelp/blob/master/guide.md
that was made specifically for AWS.
Hope this helps