RuntimeError
RuntimeError

Reputation: 1390

MSAL with Express and React: Authentication for root URL

I have a React frontend together with an express backend.

The goal is to only allow access to the frontend when the user was successfully authenticated by the express backend which uses MSAL (Microsoft Authentication Library).

Originally, I implemented the authentication flow by follwing this official Microsoft guide. However, this guide is only about using pure express without a real frontend. So I had to combine the information of this guide with my React frontend.

Step 1 was to run them both at the same port (localhost:3000) by building the frontend into a "build" folder and telling express to use the static files in this folder. This worked fine.

But now I am stuck with following problem: I want the authentication to be done when visiting localhost:3000. But currently, this URL is accessed without authentication. After the app.use(), app.get() is not called. It works only when app.get() is called with a somehow extended URL such as /login. Then the user will be authenticated and then redirected to localhost:3000.

Please see the express code:

//server.js
const path = require('path');

const express = require("express");
const msal = require('@azure/msal-node');

const SERVER_PORT = process.env.PORT || 3000; // use static build
const REDIRECT_URI = "http://localhost:3000"; 

// msal config
const config = {
    auth: {
        clientId: "xyz",
        authority: xyz",
        clientSecret: "xyz"
    },
    system: {
        loggerOptions: {
            loggerCallback(loglevel, message, containsPii) {
                console.log(message);
            },
            piiLoggingEnabled: false,
            logLevel: msal.LogLevel.Verbose,
        }
    }
};

// Create msal application object
const pca = new msal.ConfidentialClientApplication(config);

// Create Express App and Routes
const app = express();

// production mode: Build frontend using npm run build --> creates build folder. Use "build"-folder to serve static files with express

// use build folder
app.use(express.static(path.join(__dirname, './build')));

app.get('/', (req, res) => { // "/": app.get() is not invoked. "/login": works fine
    const authCodeUrlParameters = {
        scopes: ["user.read"],
        redirectUri: REDIRECT_URI,
    };

    // get url to sign user in and consent to scopes needed for application
    pca.getAuthCodeUrl(authCodeUrlParameters).then((response) => {
        res.redirect(response);
    }).catch((error) => console.log(JSON.stringify(error)));
});

// currently not being invoked
app.get('/redirect', (req, res) => {
    const tokenRequest = {
        code: req.query.code,
        scopes: ["user.read"],
        redirectUri: REDIRECT_URI,
    };

    pca.acquireTokenByCode(tokenRequest).then((response) => {
        console.log("\nResponse: \n:", response);
        res.sendStatus(200);
    }).catch((error) => {
        console.log(error);
        res.status(500).send(error);
    });
});


app.listen(SERVER_PORT, () => console.log(`Msal Node Auth Code Sample app listening on port ${SERVER_PORT}!`))

Why is app.get() (= the authentication flow) not invoked when using "/"? "*" does not work, too. Is it even possible to achieve the goal to do the authentication on localhost:3000 instead of localhost:3000/login?

If it is not possible, how can I prevent the user from accessing the frontend by just typing localhost:3000?

I also searched StackOverflow for this, but with no success.This question for example does not really work out for me, since it uses extra private routes. But I would like to avoid extra routes. Because I find so many examples that do exactly this, I start wondering if it's the only possible way.

Help will be appreciated.

Upvotes: 0

Views: 1290

Answers (1)

Rutha
Rutha

Reputation: 805

To allow access to the frontend when the user was successfully authenticated by the express backend you can use react-router-guards.

Learn more here: https://www.npmjs.com/package/react-router-guards

Upvotes: 1

Related Questions