2

I am creating a SPA using React and Express. I am trying to include authentication using MSAL.js and have looked at Microsoft's tutorials for SPA. I've been able to implement this with React using @msal-react. While this does perform authentication, it does not protect the REST API from access by unauthenticated users.

I found the Active Directory Javascript Nodejs Web API that seems to provide a means for protecting the REST API using Passport and the Bearer strategy, but the links showing how to couple this with the client-side seem to be broken.

I'm not sure how to connect the authentication that is occurring on the client side with REST API. As I understand it, the authentication token has to be passed, but I am not sure how to pass that.

The server-side sample code has:

// API endpoint exposed
app.get("/api",
    passport.authenticate('oauth-bearer', {session: false}),
    (req, res) => {
        console.log('Validated claims: ', req.authInfo);

        // Service relies on the name claim.  
        res.status(200).json({
            'name': req.authInfo['name'],
            'issued-by': req.authInfo['iss'],
            'issued-for': req.authInfo['aud'],
            'scope': req.authInfo['scp']
        });
    }
);

What I tried to do on the client side was to get the account information:

import {
  useAccount,
  useMsal
} from "@azure/msal-react";

...

const { accounts } = useMsal();
const account = useAccount(accounts[0] || {});

From looking at account after authenticating, I thought account.idTokenClaims might have what is necessary, but have had no luck.

I am stuck because I am not sure if I have a fundamental misunderstanding of how the Bearer strategy works, if I am using MSAL or Passport (or both) incorrectly, or if this is a configuration issue. I appreciate the help!

oort
  • 1,840
  • 2
  • 20
  • 29

1 Answers1

5

When calling your protected REST API, you need to present an access token obtained by the client application (on behalf of the signed-in user). So the ID token won't do here -it's only meant for your client application as a proof of successful user authentication. (ideally, your client and service apps should be separate, each represented by an Azure AD app registration).

After authentication, you need to obtain an access token, by using one of the acquireToken* methods. You pass a token request object to that method. Here you need to specify what resources and permissions you are requesting an access token for. The access token that would work with calling your REST API shouldn't/won't work with other APIs.

The tutorial article you linked points to a sample using implicit flow. I would recommend using the more secure auth code flow.

This tutorial should cover your need. Check this section in particular.

p.s. for a React client app, see this.

derisen
  • 630
  • 3
  • 13
  • 1
    I actually have been able to run the React client app, however the problem I am running into is how to allow the client code access my own REST apis on the backend. My assumption has been that once logged in, I can obtain the authorization token using `acquireTokenSilent` and then call the local API similar to how the MS Graph API is called - but this has been met with constant 401 responses. I assumed that this would have been a simple thing to do, but I cannot find code examples or documentation of this! – oort Feb 02 '21 at 20:57
  • 1
    Your assumption is on the right track, but there might be configuration issues that would cause 401. Please go through [this sample](https://github.com/Azure-Samples/ms-identity-javascript-tutorial/tree/main/3-Authorization-II/1-call-api) once to get an idea of how to setup Azure AD app registration and call your web API. If that won't clarify, please open a new issue in [React client sample repository](https://github.com/Azure-Samples/ms-identity-javascript-react-spa). I can help you more over there. – derisen Feb 02 '21 at 23:10
  • @derisen There are very few examples which secure the back end, which makes your sample very helpful but passport-azure-ad has been moved to maintenance. Is it still current or what does one use to protect the back end API? The Problem I find with MSAL is the volume of documentation and finding the best code that's current. – strattonn Aug 23 '21 at 03:24
  • @derisen, I have a question at https://stackoverflow.com/questions/68872369/can-i-get-the-token-through-url-fragement-such-as-clientid-etc-in-azure-directl. Could you please help me out? – Bigeyes Aug 23 '21 at 18:11