B2C: Can I call Downstream Service from SPA and ASP? Error=405 Method Not Allowed

Siegfried Heintze 1,861 Reputation points
2021-03-26T15:36:58.71+00:00

Since my prospective investors now tell me I need to demonstrate a SPA approach to my B2C Web App (based on 4-2-B2C), here is one approach I'm considering: add a B2C SPA to my existing Web App that calls a downstream service and having the SPA also call the downstream service directly.

(1) Is it possible for an Angular SPA to call the downstream REST service implemented at TodoListController.cs so it would work double duty as a service for Angular/AJAX and the ASP.NET client at TodoListController.cs simultaneously? If so, what MSAL.js function would it call to get a token?

(2) I see that TodoListService.cs (line 120) is calling this special function microsoft.identity.web.itokenacquisition.getaccesstokenforuserasync to get a token for the downstream service... Is it only the way it is called that makes it a downstream service (with this special token) or is the implementation of the downstream service special?

(3) What would I have to change in TodoListService.cs to accommodate SPA/AJAX/Angular too? For example, I see the B2B sample Startup.cs (line 41-43) allows CORS so I guess I would add that to Startup.cs. What else would I add (assuming it is possible to make it do double duty)?

Tue Mar 30 2021 Afternoon Update

JP Dandison on Reactor 425 Show answered some (not all) of my above questions and explained (I'm paraphrasing) that there should be no problem having an existing sample SPA call a new B2C downstream API and the only changes necessary would be in the configuration of an existing sample SPA client to call a new & different API.

So I have been watching angular11-b2c-sample successfully call this nodejs REST server via fiddler and when I click the "Web API" button I see the bearer token in the HTTP header of the fiddler display. It works!

83021-image.png

It is kinda curious because fiddler shows two consecutive rows (or entires) of "localhost.:5000/hello" and the second one contains the bearer token in the header... But it works and the node/express server extracts the claim with my name in it and passes it back as JSON and the angular client correctly displays my name.

I have also been watching this B2C ToDo ASP.NET Client (the same sample my web app is based on) call this downstream ASP.NET REST service (the same service my web app is based on) successfully (see last screen shot below).

However, when I reconfigure angular11-b2c-sample (by adjusting the port and the scopes and API permissions) to call ASP.NET REST service it does not work and then it says (in the fiddler display) "Method not allowed". However, this is the same path that works nicely with the ASP.NET client (see below). The Angular client never gets the XMLHttp callback and never displays any data in my javascript alert statement (that uses JSON.stringify to display the data). Fiddler only shows localhost.:44332 once and there is no bearer token in the header. Why am I getting "method not allowed"? I'm specifying the same scope with both the angular and ASP.NET client.

82942-image.png

Maybe that is the problem is with fiddler and the period after the "localhost"... Let me try that again with a base address using https (as before) and localhost without the trailing period:
https://localhost:44332/api/todolist
:

83055-image.png

No, that did not help.

Strange... The MSAL Angular/AJAX call looks a lot different (more verbose) than the REST call generated by ASP.NET (see below). Why is that? And why does not the MSAL Angular/AJAX have a bearer token?

Here is the screen shot of fiddler with a successful REST call from the ASP.NET client with a bearer token. Note the JSON in the response... Note the REST path is identical.

82978-image.png

Both the Angular and the ASP.NET are using identical scopes.

Sat Apr 03 2021 Update:

Problem solved: I need to call both services.AddCors AND app.UseCors (services.AddCors is not sufficient) and now I can call the downstream REST service using the modified code from angular11-b2c-sample.

Now back to my original question I posted at the top:

I see that TodoListService.cs (line 120) is calling this special function microsoft.identity.web.itokenacquisition.getaccesstokenforuserasync to get a token for the downstream REST service... Why is it doing this? Apparently it is not necessary because I can call this same REST service with javascript/angular/AJAX just using the access token I get from AADB2C authentication... JP Dandison did not answer this question on the REACTOR show.

Thanks

Siegfried

Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
19,559 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. AmanpreetSingh-MSFT 56,311 Reputation points
    2021-04-08T05:29:27.97+00:00

    Hi @Siegfried Heintze · Thank you for reaching out.

    This sample is a web app calling a web API, you could also use MSAL JS: Azure-Samples/ms-identity-javascript-v2: VanillaJS sample using MSAL.js v2.x and OAuth 2.0 Authorization Code Flow with PKCE on Microsoft identity platform (github.com)

    This is a .NET library, so we use this helper method. Of course, if you have the right access token you can use it on the web API, we are just trying to simplify things for a .NET developer and show correct security practices, e.g., the web app shouldn't open the access token.

    -----------------------------------------------------------------------------------------------------------

    Please "Accept the answer" if the information helped you. This will help us and others in the community as well.