Session lost when refresh the page (Next, react, isomorphism)

5.5k views Asked by At

I am using zeit next for make a isomorphic app with react and an express with express-session (in other server) for make an API.

This component should request private data from the API (request.get('http://0.0.0.0:3100/private')) and show a private page if the user is logged in or redirect to login if not.

In client side this works but when I refresh the private page the I am redirected to login, because the session cookie of client and server side are different. ¿How can I solve this problem?

const Private = (props) => {
    return (
        <main>
            <h1>Private </h1>
            <Link href="/">
                <a>Home</a>
            </Link>
        </main>
    );
}

Private.getInitialProps = async ({ res }) => {
    // getInitialProps is ejecuted in server side when you refresh the page (first time) 
    // but if you navigate in client side it is ejecuted in client. Server side and client
    // have a different session for API calls. Is posible to share the session by client
    // and server side? 
    const response = await request.get('http://someDomain/private');

    let body;
    if (response.status !== 401) {
        body = await response.json();
    } else {
        if (res) {
            res.writeHead(302, { Location: '/login' })
            res.end()
        } else {
            Router.push('/login')
        }
    }

    return {}
}

export default Private;
2

There are 2 answers

1
Bijay Rai On BEST ANSWER

@PacoRampus as @neerajdngl said While refreshing the page , your cookie is passed to the express server not in browser. so, you are redirected to login page.

You can do something like this:

    Private.getInitialProps = async ({ req, res }) => {
        let Cookie;
        if (req) {
            Cookie = encodeURIComponent(req.cookies.your_token_name);
        } else {
            Cookie = '';
        }

        let yourCookie= 'token=' + Cookie;

       const response = await fetch('http://someDomain/private', {
            credentials: 'include',
            headers: {Cookie: yourCookie}
        }));

        let body;
        if (response.status !== 401) {
            body = await response.json();
        } else {
            if (res) {
                res.writeHead(302, { Location: '/login' })
                res.end()
            } else {
                Router.push('/login')
            }
        }

        return {}
    }

and your server.js file should ve code like this:

server.get('/yourPrivatePage', (req, res) => {
            return app.render(req, res, '/yourPrivatePage', req.query)
        });

Hope this works for you.

0
neerajdngl On

When you refresh the page, the cookie will be passed to the express server, not to the api. You will need to fetch the cookie in the express and then pass the cookie along with the api request.

When you make the api request from the client, the cookie will be automatically passed along with the request, which will authenticate your api call.

You need to do something like in the code snippet below. I am using fetch instead of request

getCookies = encodeURIComponent(req.cookies.token);
const sendCookie = 'token=' + getCookies;
const response = await fetch(YOUR_API_ENDPOINT, {
            credentials: 'include',
            headers: {Cookie: sendCookie}
        })