I wanted to write this to help others who might be stuck in the same rut I was in trying to find a basic direction / understanding. I essentially went with the workflow that @Chris Pradget described. My initial perception of the problem was wrong though and I’ll clarify where my error was and give a little context.
My initial goal was to bring a user’s roles and / or groups claims when a user logs in to my Azure / Angular App. Azure doesn’t have an easy way to do this when you are logging in with Azure B2C for policies. (In some regards it seems that Firebase makes this easy).
After a bunch of research and not really comprehending the big picture I saw what seemed to be conflicting information which took some time to sort through. Eventually I found the information I was looking for which was that I couldn’t have only one login.
(Just a heads up, I refer to my classic Azure AD registered app as an 'app registration' just to draw a distinction from the code implementation and the configuration set in Azure's Portal)
It took alot of experimentation, but i came up with something that seems to work. I essentially retrieve 3 tokens, 2 in Angular using MSAL.js and one in .NET using ADAL for Microsoft Graph. One in Angular is for the initial login (MSAL Client's loginRedirect call) to retrieve the id_token and the other I retrieved using that token along with the aquireTokenSlient function to retrieve the access_token. I sent that to my .NET Core backend where I used the users id from the incoming token as resource id in a request to Microsoft Graph to get my groups claim and then I crafted my own JWT token with the claims to send back to Angular for my route guards.
Things of note in my research:
Azure AD Graph vs Microsoft Graph to pull user groups: There’s conflicting information about which to use, some say Microsoft Graph because Azure Graph is being deprecated, but others say Azure Graph because MS Graph doesn’t cover all of the bases yet. After experimenting, I found that I was able to pull a user’s groups out of MS Graph. Given that and the fact that MS Graph is newer, I went with MS Graph. For experimentation with the graphs I used both Azure Graph explorer and MS Graph Explorer.
It took me awhile to successfully query the Microsoft Graph, but when I did was through MS Graph Explorer as stated above. The main problem I first encountered was when I queried my app with my own account. Only some queries worked and even those brought back very limited info. It wasn’t until I re-read this article about the Azure AD Graph API did I notice that in order to query the Graphs, you need to use a user id that is local to your tenant’s domain and is an admin. When I created and used my tenant’s admin (from that domain), all of the queries worked. So as far as my questions above are concerned:
1) How do I fix this ["code": "Authentication_MissingOrMalformed"] error?
Use a local admin account
2) Is it necessary to have a local admin account?
Yes
3) Are there any special Scopes I need to set on my B2C app to grant authorization for my queries? If there are, what specifically are they?
To query the MS Graph in the ways you want with ADAL use Directory.Read Access
4) Does this app need to be multi tenant?
No
Additionally In my research I found that instead of using B2C Groups, you can use Azure AD Roles. Specifically, Application Roles can be added to a Classic Azure AD app manifest in the Azure Portal. It was a different route that looked promising for me. I found this article describing how to edit the manifest to add the Application Roles. First you add roles to the manifest, next you assign users to roles in the Azure Portal, then you query the user information (from Angular) using the ADAL.js library. When you login using the library, the Application Roles are brought down on the token acquired. This of course doesn't use the B2C policies. Also this might go without saying, but when you login, neither the B2C id_token or access_token can be used to acquire the Classic Azure AD credentials/token. I tried to think of other ways to accomplish what I wanted. Given that the 2 registrations are in the same tenant I thought I could use single sign on to log into one and remain logged in for the other. I didn’t get very far. Another method that I considered was using custom policies to retrieve the data from my Azure AD classic app but didn’t get far with that either.
Also when @Chris Padgett mentioned creating a "user api", I misinterpreted it. By "user api" I thought he meant my classic Azure Ad app registration, which was set up in Azure Portal, houses my user info, and acts as an api to retrieve my token. I thought I first needed to obtain an access token from B2C in Angular and then use that token (still in Angular) to access my Azure AD classic registration. From there I would be able to pull down my users' information including the Application Roles (made accessible from editing the manifest). This wouldn't have worked because as I've stated above I wanted to do this with one login and you can't use a B2C token in a Classic Azure AD app. Even if it did work, it would have required setting roles for users in my classic Azure AD app registration outside of my B2C app which I didn't want to do. Having one app registration for the policies and another to manage users' roles isn't very elegant. Also getting it to work would require 2 logins one for B2C and one for Classic Azure AD. In this approach, it feels like these 2 apps are separate and I don't want to divvy up concerns across 2 platforms. So, in the end, the scenario of logging in with B2C in Angular and then hitting the server to pull the user groups with MS Graph is a better one. The backend app only needs to log in once independent of users accessing it, which means users don't need to log in twice. Also it consolidates my information to my B2C app registration.
I'm think Azure might eventually provide the groups and / or roles on their id_tokens in the future, but I thought this info might be helpful to people in the meantime. In addition here are links to other related questions I asked that helped guide me my research:
Learning that I needed to use MSAL.js over ADAL.js in order to use B2C Policies.
A similar question I asked about querying MS Graph and getting a limited response