I have not been able to link the Azure Active Directory access control in our ReactJS application to our API, and reading through the documentation on this matter has left me with more questions than answers.
I first began by following the instructions in the AAD Single-page app scenario, which was straightforward and allowed me to log in to my AAD account on the web, which I mentioned previously. That worked well.
However, when it came to configuring our NodeJS API, I was presented with two options: A Web app that calls web APIs, and Protected web API.
In A Web app that calls web APIs, the registration was straightforward and led me to believe that this was the way to go, however the Code Configuration page states that only ASP, Java, and Python are supported. I was unable to find any JavaScript examples for this scenario, so I moved on to Protected Web API.
Similarly, while I found the registration portion to be easy to follow, the Code Configuration page only listed examples in .NET, NodeJS (but only for App Functions, rather than a standalone API), and Python. Given that the NodeJS example was close enough to a standalone API, I followed along with that code, substituting our configuration options where appropriate, seeing as it used the passport-azure-ad package that I saw elsewhere and previously had tried to implement. However, in both cases, every attempt to make an API call against the protected endpoint resulted in the API logging the following:
“authentication failed due to: In Strategy.prototype.jwtVerify: cannot verify token”
Additionally, and I’m not sure how related this could be, but I noticed that when I decoded the ID Token and Access Token on the ReactJS application, the ID Token version was 2.0, but the Access Token was 1.0. Searching through Github Issues and StackOverflow showed that others had observed this behavior as well, although I was unable to replicate their processes in order to get a v2.0 Access Token, which I suspect but am not sure is the reason for the inability for the NodeJS API to verify the token.
Oh, and I have observed the same behavior when using MSAL.js 1.3 as well as the 2.0 beta in the client, in case that helps.
The comments discussion helped me discover a solution that was otherwise not made obviously clear in the MSAL examples and documentation, which was that any MS Graph scopes in the Login Request (ex: "User.Read") would downgrade Access Tokens from v2.0 to v1.0, which is why I was receiving v2.0 ID Tokens with v1.0 Access Tokens.
I removed all Graph scopes from the Login Request, with the API scope being the only one remaining, and as a result the following login returned a v2.0 Access Token, which was subsequently validated by the API and enabled authenticated access.