0

I am attempting to set up SAML Single Sign On with my React application. The backend is an express / passport setup. Front end is Reactjs.

I load the initial Reactjs SPA and it notices I don't have a username set. ... so then it redirects to the SSO page. I enter my information (as needed) and then after success I am to point where the identity provider forwards my client back to the /login/callback route. This route, in turn, is supposed to forward the user back to their original URL (as defined by req.body.RelayState).

The callback route looks like this:

samlRouter.use(session(config.session));
samlRouter.use(passport.initialize());
samlRouter.use(passport.session());

samlRouter.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', req.header('origin'));
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-Width, Content-Type, Accept, Authorization');
    res.header('Access-Control-Allow-Credentials', 'true'); //SAML

    if (req.method == 'OPTIONS') {
        res.header('Access-Control-Allow-Methods', 'PUT, POST, GET');
        return res.status(200).json({})
    }
    next();
})

samlRouter.post('/login/callback',
    (req, res, next) => {
        passport.authenticate('saml', config.saml.options)(req, res, next)
    },
    (req, res, next) => {
        console.log('req.user.nameID :>> ', req.user?.nameID);   // ***THIS IS CORRECT**
        req.session.user = req.user;

        return res.redirect(`${req.body.RelayState}`);
    });

The problem is - I need to tell the front-end reactjs application who the req.user.nameID is. I can't just put it in a query string on the redirect because it's the login (and thus anyone that wanted to just type in xxxx.com/privatePage?myusername could pretend to be me).

How can I securely pass data to my front end after authentication?

lowcrawler
  • 6,777
  • 9
  • 37
  • 79

2 Answers2

1

There are a number of ways to pass data with a redirect.

  1. Put data in a query string that is part of the redirect URL so that data will be available in the URL when the redirect URL is rendered.
  2. Put data into a cookie that will be present when the redirected URL is rendered.
  3. Put data into a server-side user session that will be present when the redirected URL is rendered.

Both options 2 and 3 have potential concurrency issues or race conditions if the same user is very involved in multiple redirects at the same time. These options 2 and 3 also need to clean up the data after it is used so it isn't left hanging around.

Options 2 and 3 are more private than option 1 if that is desired. If this data is involved in authentication (e.g. who the user is and needs to be secure), then it really ought to be in the server-side session (which is indexed by the session cookie). This would typically be saved in the session so it's available as req.session.user to future requests.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • As stated, #1 isn't viable. I'm looking into JWT for #2 right now. For #3, how does the front end reactjs app pick up the req.session.user? – lowcrawler May 12 '21 at 22:51
  • @lowcrawler - The front-end does not pick up `req.session.user` - that's for back-end use. But, it could be used by the back-end to render something into the web page that the front-end could use (such as a Javascript variable). – jfriend00 May 12 '21 at 23:06
  • ... So, back to the original question, then: How do I get this 'javascript variable' sent from the backend to the front end while also doing the redirect? – lowcrawler May 12 '21 at 23:09
  • @lowcrawler - Options 2 or 3 - Put it in a cookie that the front-end can read directly or put it in the session and then use the session data to render a javascript variable into the redirected page that the front-end can then read. – jfriend00 May 12 '21 at 23:11
  • I guess technically you answered the question. I should have been more clear with the HOW - technically - can I do those things. See new question: https://stackoverflow.com/questions/67512088/how-to-pass-data-with-a-session-or-cookie-while-redirecting-with-express-nodej – lowcrawler May 12 '21 at 23:16
0

One possible solution depending on the type and quantity of data you want to pass:

Make another get route e.g.

router.get('samepage/:some param',
(req,res)=>{
///get data with param or use param as the data !
res.render('samepage',{data})

})

////redirect to that route with param you need