admin管理员组

文章数量:1332345

I've created API in node express and I'm running it on port :8000, I am consuming APIs through simple CRA on port :3000. I've created registration and login with setting httpOnly cookie. Furthermore, I've put middleware to check each endpoint in order to verify if it has that token. When I test through Thunder/Postman everything works, after logging in I get the cookie in response, I set that cookie as auth token and make request to get data and I get the data.

When I log in through the React Frontend it succeeds and I can see in network tab that I have received the cookie in response. But when I make a request to protected endpoint, the request does not have a cookie in it (I log ining requests on server and pare ones made with Thunder/Postman client and via app in Browser).

I use axios, and I've put {withCredentials: true} it doesn't work. I've used withAxios hook and it doesn't work either.

SERVER

index.js

...
const app = express()
app.use(cors({
    credentials: true,
    origin: 'http://localhost:3000',
}));
...

controllers/User.js

...
const loginUser = async(req, res) => {
    const body = req.body
    const user = await User.findOne({ email: body.email })
        if(user) {
        const token = generateToken(user)
        const userObject = {
            userId: user._id,
            userEmail: user.email,
            userRole: user.role
        }
        const validPassword = await bcryptpare(body.password, user.password)
        if(validPassword) {
            res.set('Access-Control-Allow-Origin', req.headers.origin);
            res.set('Access-Control-Allow-Credentials', 'true');
            res.set(
                'Access-Control-Expose-Headers',
                'date, etag, access-control-allow-origin, access-control-allow-credentials'
            )
            res.cookie('auth-token', token, {
            httpOnly: true,
            sameSite: 'strict'
            })
            res.status(200).json(userObject)
        } else {
            res.status(400).json({ error: "Invalid password" })
        }
    } else {
        res.status(401).json({ error: "User doesn't exist" })
    }
}
...

middleware.js

...
exports.verify = (req, res, next) => {
    const token = req.headers.authorization
    if(!token) res.status(403).json({ error: "please provide a token" })
    else {
        jwt.verify(token.split(" ")[1], tokenSecret, (err, value) => {
            if(err) res.status(500).json({error: "failed to authenticate token"})
            req.user = value.data
            next()
         })
    }
}
...

router.js

...
router.get('/bills', middleware.verify, getBills)

router.post('/login', loginUser)
...

CLIENT

src/ponents/LoginComponent.js

...
const loginUser = (e) => {
        setLoading(true)
        e.preventDefault()
        let payload = {email: email, password: password}
        axios.post('http://localhost:8000/login', payload).then(res => res.status === 200 
        ? (setLoading(false), navigate('/listbills')) : navigate('/register'))
    }
...

src/ponents/ListBills.js

...
useEffect(() => {
        fetch('http://localhost:8000/bills', {
            method: 'get',
            headers: {'Content-Type': 'application/json'}, 
            credentials: 'include',
        })
            .then(response => {console.log(response)}).catch(err => console.log(err));
    }, [])
...

I've also tried:

axios.get('http://localhost:8000/bills',{withCredentials: true})
  .then((data) => console.log(data))
  .then((result) => console.log(result))
  .catch((err) => console.log('[Control Error ] ', err))
    }

and

const [{ data, loading, error }, refetch] = useAxios(
  'http://localhost:8000/bills',{
  withCredentials: true,
  headers: {'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json'
}})

Console.log error:

After I login I get this in Network tab:

However when I want to access the list:

=== UPDATE ===

So the cause of the issue is not having the httpOnly cookie passed in the request header. This is the log of the middleware I am using:

token undefined
req headers auth undefined
req headers {
  host: 'localhost:8000',
  connection: 'keep-alive',
  'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"',
  'sec-ch-ua-mobile': '?0',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36',
  'sec-ch-ua-platform': '"macOS"',
  'content-type': 'application/json',
  accept: '*/*',
  origin: 'http://localhost:3000',
  'sec-fetch-site': 'same-site',
  'sec-fetch-mode': 'cors',
  'sec-fetch-dest': 'empty',
  referer: 'http://localhost:3000/',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'en-US,en;q=0.9,hr;q=0.8,sr;q=0.7,bs;q=0.6,de;q=0.5,fr;q=0.4,it;q=0.3'
}

token is read from headers.authorization but from the log of the headers it doesn't exist so my requests fail to be authorized.

Still not working.

I've created API in node express and I'm running it on port :8000, I am consuming APIs through simple CRA on port :3000. I've created registration and login with setting httpOnly cookie. Furthermore, I've put middleware to check each endpoint in order to verify if it has that token. When I test through Thunder/Postman everything works, after logging in I get the cookie in response, I set that cookie as auth token and make request to get data and I get the data.

When I log in through the React Frontend it succeeds and I can see in network tab that I have received the cookie in response. But when I make a request to protected endpoint, the request does not have a cookie in it (I log ining requests on server and pare ones made with Thunder/Postman client and via app in Browser).

I use axios, and I've put {withCredentials: true} it doesn't work. I've used withAxios hook and it doesn't work either.

SERVER

index.js

...
const app = express()
app.use(cors({
    credentials: true,
    origin: 'http://localhost:3000',
}));
...

controllers/User.js

...
const loginUser = async(req, res) => {
    const body = req.body
    const user = await User.findOne({ email: body.email })
        if(user) {
        const token = generateToken(user)
        const userObject = {
            userId: user._id,
            userEmail: user.email,
            userRole: user.role
        }
        const validPassword = await bcrypt.pare(body.password, user.password)
        if(validPassword) {
            res.set('Access-Control-Allow-Origin', req.headers.origin);
            res.set('Access-Control-Allow-Credentials', 'true');
            res.set(
                'Access-Control-Expose-Headers',
                'date, etag, access-control-allow-origin, access-control-allow-credentials'
            )
            res.cookie('auth-token', token, {
            httpOnly: true,
            sameSite: 'strict'
            })
            res.status(200).json(userObject)
        } else {
            res.status(400).json({ error: "Invalid password" })
        }
    } else {
        res.status(401).json({ error: "User doesn't exist" })
    }
}
...

middleware.js

...
exports.verify = (req, res, next) => {
    const token = req.headers.authorization
    if(!token) res.status(403).json({ error: "please provide a token" })
    else {
        jwt.verify(token.split(" ")[1], tokenSecret, (err, value) => {
            if(err) res.status(500).json({error: "failed to authenticate token"})
            req.user = value.data
            next()
         })
    }
}
...

router.js

...
router.get('/bills', middleware.verify, getBills)

router.post('/login', loginUser)
...

CLIENT

src/ponents/LoginComponent.js

...
const loginUser = (e) => {
        setLoading(true)
        e.preventDefault()
        let payload = {email: email, password: password}
        axios.post('http://localhost:8000/login', payload).then(res => res.status === 200 
        ? (setLoading(false), navigate('/listbills')) : navigate('/register'))
    }
...

src/ponents/ListBills.js

...
useEffect(() => {
        fetch('http://localhost:8000/bills', {
            method: 'get',
            headers: {'Content-Type': 'application/json'}, 
            credentials: 'include',
        })
            .then(response => {console.log(response)}).catch(err => console.log(err));
    }, [])
...

I've also tried:

axios.get('http://localhost:8000/bills',{withCredentials: true})
  .then((data) => console.log(data))
  .then((result) => console.log(result))
  .catch((err) => console.log('[Control Error ] ', err))
    }

and

const [{ data, loading, error }, refetch] = useAxios(
  'http://localhost:8000/bills',{
  withCredentials: true,
  headers: {'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json'
}})

Console.log error:

After I login I get this in Network tab:

However when I want to access the list:

=== UPDATE ===

So the cause of the issue is not having the httpOnly cookie passed in the request header. This is the log of the middleware I am using:

token undefined
req headers auth undefined
req headers {
  host: 'localhost:8000',
  connection: 'keep-alive',
  'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"',
  'sec-ch-ua-mobile': '?0',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36',
  'sec-ch-ua-platform': '"macOS"',
  'content-type': 'application/json',
  accept: '*/*',
  origin: 'http://localhost:3000',
  'sec-fetch-site': 'same-site',
  'sec-fetch-mode': 'cors',
  'sec-fetch-dest': 'empty',
  referer: 'http://localhost:3000/',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'en-US,en;q=0.9,hr;q=0.8,sr;q=0.7,bs;q=0.6,de;q=0.5,fr;q=0.4,it;q=0.3'
}

token is read from headers.authorization but from the log of the headers it doesn't exist so my requests fail to be authorized.

Still not working.

Share edited Feb 11, 2022 at 8:31 fedjedmedjed asked Feb 10, 2022 at 9:02 fedjedmedjedfedjedmedjed 5051 gold badge9 silver badges18 bronze badges 2
  • try to use cookie-parser middleware for express – wald3 Commented Feb 10, 2022 at 10:34
  • @wald3 yeah, I'm using that, calling right under const app = express() still not working, doesn't matter what I try, the Authorization cookie, bearer token whatever you call it doesn't get sent with the request to the server – fedjedmedjed Commented Feb 10, 2022 at 13:46
Add a ment  | 

1 Answer 1

Reset to default 6

After reading everything on CORS and httpOnly cookies I've managed to get it working. First I removed sameSite and added domain prop according to documentation in controllers/User.js on SERVER

res.cookie('auth-token', token, {
    httpOnly: true,
    domain: 'http://localhost:3000'
})

Then I got a little yellow triangle in the console request view, it said that domain was invalid. Then I just changed domain to origin and the cookie appeared in the request log of the headers

本文标签: javascriptHttpOnly cookies are not sent with request to serverStack Overflow