2

This question is based on the example code provided by Microsoft:
https://learn.microsoft.com/en-us/samples/azure-samples/active-directory-javascript-singlepageapp-angular/active-directory-javascript-singlepageapp-angular/

app.module.ts has been configured and the application can successfully login through the Azure B2C sign in screen.

There is also an Azure function that simply returns a JSON object with one string property "text" through an HTTP GET request. The function has been configured to authenticate using Azure B2C. This has been confirmed by visiting the function URL in the browser, logging in through the B2C login screen, and being returned the JSON object from the function.

The component that is calling the protected api looks like this:

import { Component, OnInit } from '@angular/core';
import { MsalService } from '@azure/msal-angular';
import { HttpClient } from '@angular/common/http';

const FUNCTION_ENDPOINT = 'function-url-here';

export interface MyInterface {
  text: string;
}

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  value: MyInterface;

  constructor(private authService: MsalService, private http: HttpClient) { }

  ngOnInit() {
    this.getValue();
  }

  getValue() {
    this.http.get<MyInterface>(FUNCTION_ENDPOINT).toPromise()
      .then(value => {
          this.value = value;
      });
  }

}

When the function authentication is turned off, the JSON from the function is returned to the Angular app. When the function authentication is turned on, following error is printed to the browser console:

Access to XMLHttpRequest at 'https://mytenant.b2clogin.com/mytenant.onmicrosoft.com/oauth2/v2.0/authorize?response_type=id_token&redirect_uri=https%3A%2F%functionname.azurewebsites.net%2F.auth%2Flogin%2Faad%2Fcallback&client_id=SAMPLE-STRING&scope=openid+profile+email&response_mode=form_post&p=b2c_1_signupsignin1&nonce=SAMPLE-STRING&state=redir%3D%252Fapi%252FHttpTrigger2%253Fcode%SAMPLE-STRING' (redirected from 'https://functionname.azurewebsites.net/api/HttpTrigger2?code=SAMPLE-STRING') from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

The second error:

core.js:4002 ERROR Error: Uncaught (in promise): HttpErrorResponse: {"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status":0,"statusText":"Unknown Error","url":"https://functionname.azurewebsites.net/api/HttpTrigger2?code=SAMPLE-STRING","ok":false,"name":"HttpErrorResponse","message":"Http failure response for https://functionname.azurewebsites.net/api/HttpTrigger2?code=SAMPLE-STRING: 0 Unknown Error","error":{"isTrusted":true}}

There is also a warning in the console:

Cross-Origin Read Blocking (CORB) blocked cross-origin response https://mytenant.b2clogin.com/mytenant.onmicrosoft.com/oauth2/v2.0/authorize?response_type=id_token&redirect_uri=https%3A%2F%2Ffunctionname.azurewebsites.net%2F.auth%2Flogin%2Faad%2Fcallback&client_id=SAMPLE-STRING&scope=openid+profile+email&response_mode=form_post&p=b2c_1_signupsignin1&nonce=SAMPLE-STRING&state=redir%3D%252Fapi%252FHttpTrigger2%253Fcode%SAMPLE-STRING with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.

The URL for the Angular application is http://localhost:4200/. Here is the CORS configuration for the Azure Function:

enter image description here

enter image description here

What can be done to allow the Angular application to make authenticated requests for the Azure Function?

4
  • Hi @craydon. You might have to check Enable Access-Control-Allow-Credentials for this. Commented Mar 2, 2020 at 2:47
  • What is the difference? Is that secure? If that doesn't work, any other suggestions? Commented Mar 2, 2020 at 2:49
  • To access the authentication enabled app service, you need to pass the access token in the header. codemilltech.com/… Commented Mar 2, 2020 at 2:52
  • Was able to add B2C to the function app, but it is not simple to call from Angular using MSAL. Commented Mar 2, 2020 at 2:55

2 Answers 2

2

AAD and AAD B2C do not support CORS as stated in the MSDN documentation. That means when your Angular app calls the Function API without a token and thus gets redirected to the AAD B2C endpoint for authentication you have an unresolvable problem. The trick with the so-called "implicit flow" is to prevent that by assuring you first have a token issued in a direct call from the Angular app to the B2C endpoint. And because the app registration where this token is assigned for has the permission to access the Function API, the token can be implicitly generated and forwarded to the Function API which then accepts it. And then no redirect occurs and thus no CORS issues as well.

Often - at least from my experience - the CORS problem you encounter is a bit misleading as it shadows the real problem which may be 1) user is not authenticated at all (token is completely missing) or 2) the token for the API call is not implicitly generated and injected to the HTTP call. I propose the following checks:

  1. MsalModule correctly configured (note: the MsalModule.forRoot(<config>) does not support dynamic configurations)
  2. User token is available in SessionStorage or LocalStorage without errors
  3. Implicit flow is configured correctly with:
    • MsalInterceptor registered as provider
    • protectedResourceMap is configured for the Function's URL

I recently created and documented a reference solution with Angular & Azure Function connected to AAD B2C. Source and readme you find here: https://github.com/garaio/DevCamp-AzureServerless/tree/master/Solutions/D04-AAD-B2C-multi-tenancy#client-app-deployment.

Sign up to request clarification or add additional context in comments.

Comments

0

You can get the access token by referring to this document. Remember to update the protectedResourceMap to your value. For B2C, it should be something like

protectedResourceMap: {"https://tonyb2ctest.onmicrosoft.com/test", ["user_impersonation"]}

Then you can call the function api with the access token.

enter image description here

4 Comments

Thanks for the response. I tried this, but still getting CORS errors mentioned above. Tried both localhost, and serving from an Azure blob storage container. Both have CORS issues. Even checked off Enable Access-Control-Allow-Credentials in the function CORS configuration.
Added a screen grab at the bottom of the question that displays the AD Authentication configuration for the Azure function. Could this be the issue?
@crayden This issue occurs when using msal? Acquire a token with a pop-up window should be fine.
Tried a simpler example, still not working. stackoverflow.com/questions/60682584/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.