modimo
August 13, 2022, 6:41am
1
When I sign up or sign in on my nodejs application, I generate a jwt token but what happens after is I have an api that verifies that token but that api only works on postman and not heroku. I am unsure of why that is. It just gives me a 401 error.
auth.js
//check if user is authenticated
exports.isAuthenticated = async (req,res,next) => {
const {token} = req.cookies;
//make sure token exists
if (!token) {
return next (new ErrorResponse('You must log in to access this resource okay yeah', 401));
}
try {
//verify token
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = await User.findById(decoded.id);
next();
} catch (error) {
return next (new ErrorResponse('You must log in to access this resource okay dude', 401));
}
}
Did you add the JWT_SECRET
variable to the Heroku config vars?
modimo
August 13, 2022, 4:33pm
3
Yes I did add that variable to the config variables. I seem to get a cors error that prevents it
** No ‘Access-Control-Allow-Origin’ header is present on the requested resource.**
but I thought I had code to deal with it.
index.js
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
next();
});
Try using the cors package and see if that works. I assume your middleware is running before all the routes?
modimo
August 14, 2022, 10:08pm
5
I have the middleware before my routes.
index.js
const express = require("express");
const app = express();
const PORT = process.env.PORT || 8500
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const helmet = require("helmet");
const morgan = require("morgan");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const errorHandler = require("./middleware/error");
const cors = require('cors');
//setting cors
const corsOptions = {
//my origin
origin: '*'
}
//Import Routes
const Routes = require('./routes/routes');
dotenv.config();
//middleware
app.use(cors(corsOptions));
app.use(express.json());
app.use(helmet());
app.use(bodyParser.json());
app.use(morgan("dev"));
app.use(cookieParser());
app.use("/api", Routes);
//welcome message
app.get('/', (req,res) => {
console.log("Welcome to the API.")
});
app.get('/greeting', (req,res) => {
res.json({greeting: 'Hello there'})
});
mongoose.connect(process.env.MONGO_URL, {useNewUrlParser: true, useUnifiedTopology: true}).then(() => {
console.log("MongoDB Connected")
})
.catch((err) => console.log(err));
app.listen(PORT, ()=> {
console.log("Backend server is running!")
})
Okay so it says I need to add a “no-cors” method to the fetch method I have which is in my frontend but I am not sure how to do it and get it working.
Original
useEffect(()=>{
fetch(process.env.REACT_APP_USER)
.then(res => {
return res.json()
})
.then(result=>{
console.log(result);
setProfile(result.user);
})
.catch(error => {
console.log(error);
})
},[]);
My attempt
useEffect(()=>{
const data = fetch(process.env.REACT_APP_USER, {
mode: 'no-cors'
})
.then(res => {
return res.json()
})
.then(result=>{
console.log(result);
setProfile(result.user);
})
.catch(error => {
console.log("this is the error for getme" ,error);
})
return data.json()
},[]);
You shouldn’t use the no-cors mode, it returns an opaque response.
Fetch Standard
“no-cors
”: Restricts requests to using CORS-safelisted methods and CORS-safelisted request-headers . Upon success, fetch will return an opaque filtered response .
Fetch Standard
An opaque filtered response is a filtered response whose type is "opaque
", URL list is the empty list, status is 0, status message is the empty byte sequence, header list is empty, and body is null.
Not sure why you can’t fetch from your own API. Does commenting out the helmet middleware do anything?
Is the URL you are fetching against an HTTPS URL?
Is your frontend on Netlify? (I seem to remember you moving it to that).
You might try using
But I really do not think that should be needed if the backend is set up correctly and you are not fetching from HTTPS to an HTTP endpoint
modimo
August 15, 2022, 3:40am
7
I commented out the helmet and that did not work. I also tried a _redirect file which is basically like the netlify.toml file and that did not succeed.
(still get the same cors error : No ‘Access-Control-Allow-Origin’ header is present on the requested resource.).
All the urls I am doing a request to on heroku are https. My frontend is on netlify, and I am fetching from an https to an https endpoint.
modimo
August 15, 2022, 10:55pm
8
Any other suggestion would be greatly appreciated.
Do you have a repo for this so we can see all the code?
I assume this has to do with using a cookie for JWT.
Add the sameSite
option to the cookie res.
res
.cookie('token', token, {
httpOnly: true,
secure: true,
sameSite: 'none',
})
.send();
Add the origins to cors (not *
) and set credentials: true
(the URL should not have a trailing slash)
app.use(
cors({
origin: [
"http://localhost:3000",
"https://yourfontend.netlify.app",
],
credentials: true,
})
);
Set credentials: 'include'
in the fetch options (or use Axios with defaults axios.defaults.withCredentials = true
)
Article
When using Fetch, cookies are not shared between sites with different origins, including domains, subdomains, and even ports. Here's why, and the solution.
Here is an example repo I found you can look at. I tested it with Heroku and Netlify and it works for me.
https://github.com/jgbijlsma/mern-auth-template-tutorial
modimo
August 16, 2022, 10:55pm
10
I am still getting the same cors error. I will provide my github repo though.