Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protect Page Route in NextJS #148

Closed
ImranAhmed opened this issue Jul 31, 2020 · 8 comments
Closed

Protect Page Route in NextJS #148

ImranAhmed opened this issue Jul 31, 2020 · 8 comments

Comments

@ImranAhmed
Copy link

Using instructons in readme there is an example at bottom of page on a HOC that can be used to protect API routes requireAuthentication . Is there anything similar for pages? If not how would one best protect access to a page?

@the25x8
Copy link

the25x8 commented Aug 1, 2020

As I understood you should check the session in serverless methods in getInitialProps or in getServerSideProps (or in your routes of the custom server). And when the session doesn't exist you will redirect the user to the login route (before page will be rendered).

For example:

const YourPage = () => { ... }

export getServerSideProps = async (context) => {
   const session = await auth0.getSession(context.req);
      if (!session || !session.user) {
         res.writeHead(302, {
           Location: '/api/login'
      });
      res.end();
      return {
         props: {}
      };
   }

   return {
      props: {}
   }
}

@rogelio-meza-t
Copy link

Hey @ImranAhmed
Did you check the api-call-example inside examples directory? There is a protected-page.tsx page working as you want.

@ImranAhmed
Copy link
Author

@rogelio-meza-t That looks perfect. Will give that a try. Thanks.

@ImranAhmed
Copy link
Author

@rogelio-meza-t I managed to get that working however as soon as I added a getStaticProps to my page I got the following error.

Error: You can not use getInitialProps with getStaticProps. To use SSG, please remove your getInitialProps /home

I think this refers back to the HOC with-auth.jsx which uses getInitialProps. Any ideas how to move past this?

@ImranAhmed ImranAhmed reopened this Aug 5, 2020
@ImranAhmed
Copy link
Author

so I finally got this working.

With HOC

import { NextPage } from 'next';
import withAuth from '../components/with-auth/with-auth';
import HomeContainer from '../containers/home/home-container';

interface Props {
    user: any;
}

const Home: NextPage<Props> = ({ user }) => <HomeContainer user={user} />;

export default withAuth(Home);

With getInitialProps


import { NextApiRequest, NextPage } from 'next';
import HomeContainer from '../containers/home/home-container';
import auth0 from '../utils/auth0';

interface Props {
    user: any;
}

const Home: NextPage<Props> = ({ user }) => <HomeContainer user={user} />;

Home.getInitialProps = async ({ req, res }) => {
    const { user } = (await auth0.getSession(req as NextApiRequest)) || {};

    if (!user) {
        res.writeHead(302, {
            Location: '/api/login',
        });
        res.end();
        return;
    }

    return { user };
};

export default Home;

With getServerSideProps

import { NextPage } from 'next';
import HomeContainer from '../containers/home/home-container';
import auth0 from '../utils/auth0';

interface Props {
    user: any;
}

const Home: NextPage<Props> = ({ user }) => <HomeContainer user={user} />;

export const getServerSideProps = async (context) => {
    const { user } = (await auth0.getSession(context.req)) || {};

    if (!user) {
        context.res.writeHead(302, {
            Location: '/api/login',
        });
        context.res.end();
        return;
    }

    // eslint-disable-next-line consistent-return
    return {
        props: {
            user,
        },
    };
};

export default Home;

@danthareja
Copy link

For those who come across this issue in a search, I shared my solution to this problem in another comment: #132 (comment)

The comment explains the implementation of a withSession HOC to protect pages and provide session info to make authenticated requests.

Example Usage

import React from 'react'

import { withSession, useSession } from '../utils/session-provider'

function DashboardPage(props) {
  const session = useSession()

  console.log(props.hello) // 'hello from getInitialProps'
  
  // You can use `session.accessToken` to make an authenticated request on the client
  // Could be with useEffect, or your own useApi, useQuery, or whatever
  const data = useApi('/dashboard', session.accessToken)

  return (
    <Dashboard data={data} />
  )
}

DashboardPage.getInitialProps = async function (context) {
  const { session } = context;
  
  // You can use `session.accessToken` to make an authenticated request on first page load
  // This works for both server and client requests
  // Here, you'd have to use `fetch` or `axios`, or whatever else directly.
  const data = await fetch('/api/dashboard', session.accessToken)

  return {
    message: 'hello from getInitialProps',
  }
}

export default withSession(DashboardPage)

@gmwill934
Copy link

What about using CSR? I do not saw any examples when using client side rendering.

@NikolozR
Copy link

what about middlewares?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants