1

I am trying to protect my form route on the react page. I register and login on the server side. A little confused about how to use authentication for that route.

This is my app.js, my client side routes.

const App = () => {

 
return (
  <Container maxwidh='lg'>
    <BrowserRouter>
      <Navbar />
        <Grow in>
          <Container>
            <div className="content">
              <Switch> 
                <Route path="/" exact component={Home} />
                <Route path="/form" exact component={Form} />
                <Route path="/auth" exact component={Auth} />
                <Route path="/login" exact component={SignIn} />
              </Switch>
            </div>
          </Container>
        </Grow>
      </BrowserRouter>
    </Container>
   );
}
 
export default App;

These are my server side routes.

import express from 'express';

import { getPosts } from '../controllers/posts.js'
import { createPost, updatePost, deletePost, registerPost } from '../controllers/posts.js'

const router = express.Router();

router.get('/', getPosts);
router.post('/', createPost);
router.patch('/:id', updatePost);
router.delete('/:id', deletePost);

export default router;



export const createPost = async (req, res) => {
    const { title, message, selectedFile, creator, tags } = req.body;

    const newPostMessage = new PostMessage({ title, message, selectedFile, creator, tags })

    try {
        await newPostMessage.save();

        res.status(201).json(newPostMessage );
    } catch (error) {
        res.status(409).json({ message: error.message });
    }
}

This is from my index.js page server side.

import postRoutes from './routes/posts.js'
import userRoutes from './routes/user.js'
import loginRoutes from './routes/login.js'

const app = express();
dotenv.config();


passportConfig(passport);

app.use(passport.initialize());
app.use(passport.session());

app.use(bodyParser.json({limit: "30mb", extended: true}));
app.use(bodyParser.urlencoded({limit: "30mb", extended: true}));
app.use(cors());

app.use('/posts', postRoutes);
app.use('/auth', userRoutes);
app.use('/login', loginRoutes);

This is my authentication page.

import jwt from 'jsonwebtoken';
import User from '../models/user.js';

const auth = {
    ensureAuthenticated: function(req, res, next) {
        if (req.isAuthenticated()) {
          return next();
        }
        res.redirect('/');
      },
      forwardAuthenticated: function(req, res, next) {
        if (!req.isAuthenticated()) {
          return next();
        }
        res.redirect('/auth');      
      }
}

module.exports = auth
Sean Burnett
  • 89
  • 2
  • 9
  • Yes it helps. I'm still confused how to check authentication status. Like from useAthentication() in the example below – Sean Burnett Mar 25 '21 at 20:50
  • Ignore the [custom](https://reactjs.org/docs/hooks-custom.html) react-hook I mentioned i.e. `useAthentication` for a moment, try to do it first in a raw way, later if you think creating a hook helps, you can create such a hook. So, let's figure out the raw way to authenticate. How are you authenticating? Using [stateless, JWT](https://stackoverflow.com/a/55887742/2873538)? – Ajeet Shah Mar 25 '21 at 20:59
  • If yes, is that working (let's say is it working with [postman](https://www.postman.com/product/rest-client/))? If yes, Where are you [storing](https://stackoverflow.com/q/44133536/2873538) your JWT? – Ajeet Shah Mar 25 '21 at 21:04
  • I was going to use the ensureAuthenticated method from the above code. – Sean Burnett Mar 25 '21 at 21:04
  • My authentication method is being stored server side. Would I need to access that from my client side? – Sean Burnett Mar 25 '21 at 21:06

1 Answers1

1

You are trying to protect frontend routes based on authentication status. So, you can create a PrivateRoute component which will check if the user is authenticated or not and when the user is not authenticated it will redirect to /login route:

import { Route, Redirect } from 'react-router-dom'

export default function PrivateRoute({ component: Component, ...rest }) {
  const { isAuthenticated } = useAuthentication() 
  // An example: you can create a react-hook which will provide you 
  // authentication details based on your implementation.

  return (
    <Route
      {...rest}
      render={props =>
        isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: "/login",
              state: { from: props.location } 
              // (optional) You can use this location state "from" value to redirect 
              // back the user from /login to the location they were trying
              // to visit before authentication
            }}
          />
        )
      }
    />
  );
}

And use above component to setup routes:

...
<Switch> 
  <Route path="/" exact component={Home} />
  <PrivateRoute path="/form" exact component={Form} /> // This is now protected
  <Route path="/auth" exact component={Auth} />
  <Route path="/login" exact component={SignIn} />
</Switch>
...
Ajeet Shah
  • 18,551
  • 8
  • 57
  • 87