title: Scope claim is null when requesting web api from Angular 4 SPA
body: <p>I am trying to protect my web api using Azure B2C AD and consume the web api using an Angular 4 SPA. However, for some reason the scope claim is always null even though other claims are working just fine.</p>
  
  <p>I am using the MSAL library version 0.1.6 in the Angular app and have been following this guide: <a href="https://github.com/Azure-Samples/active-directory-b2c-javascript-angular2.4-spa" rel="nofollow noreferrer">https://github.com/Azure-Samples/active-directory-b2c-javascript-angular2.4-spa</a></p>
  
  <p>This is my web api startup.auth:</p>
  
  <pre><code>public partial class Startup
  {
      // These values are pulled from web.config
      public static string AadInstance = ConfigurationManager.AppSettings["ida:AadInstance"];
      public static string Tenant = ConfigurationManager.AppSettings["ida:Tenant"];
      public static string ClientId = ConfigurationManager.AppSettings["ida:ClientId"];
      public static string SignUpSignInPolicy = ConfigurationManager.AppSettings["ida:SignUpSignInPolicyId"];
      public static string DefaultPolicy = SignUpSignInPolicy;
  
      /*
       * Configure the authorization OWIN middleware.
       */
      public void ConfigureAuth(IAppBuilder app)
      {
          TokenValidationParameters tvps = new TokenValidationParameters
          {
              // Accept only those tokens where the audience of the token is equal to the client ID of this app
              ValidAudience = ClientId,
              AuthenticationType = Startup.DefaultPolicy
          };
  
          app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
          {
              // This SecurityTokenProvider fetches the Azure AD B2C metadata &amp; signing keys from the OpenIDConnect metadata endpoint
              AccessTokenFormat = new JwtFormat(tvps, new OpenIdConnectCachingSecurityTokenProvider(String.Format(AadInstance, Tenant, DefaultPolicy))),
  
          });
      }
  }
  </code></pre>
  
  <p>This is my controller:</p>
  
  <pre><code>[Authorize]
  [EnableCors(origins: "*", headers: "*", methods: "*")] // tune to your needs
  public class ValuesController : ApiController
  {
      // GET api/values
      public IEnumerable&lt;string&gt; Get()
      {
          string owner = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
          var scopes = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/scope");
          return new string[] {"value1", "value2"};
      }
  }
  </code></pre>
  
  <p>The owner variable contains a GUID as expected, however the scopes variable is always NULL.</p>
  
  <p>This is my auth.service.ts:</p>
  
  <pre><code>import { Injectable } from '@angular/core';
  import environment from '../../../environments/environment';
  import * as Msal from 'msal'
  
  declare var bootbox: any;
  // declare var Msal:any;
  
  const B2CTodoAccessTokenKey = "b2c.api.access.token";
  
  const tenantConfig = {
          tenant: environment.b2cTenant,
          clientID: environment.b2cClientID,
          signUpSignInPolicy: environment.b2cSignUpSignInPolicy,
          b2cScopes: environment.b2cScopes
      };
  
  @Injectable()
  export class AuthService {
  
      // Configure the authority for Azure AD B2C
      private authority = "https://login.microsoftonline.com/tfp/" + tenantConfig.tenant + "/" + tenantConfig.signUpSignInPolicy;
  
      private loggerCallback(logLevel, message, piiLoggingEnabled) {
          console.log(message);
      }    
  
      private logger = new Msal.Logger(this.loggerCallback, { level: Msal.LogLevel.Verbose }); 
  
      clientApplication = new Msal.UserAgentApplication(
          tenantConfig.clientID, 
          this.authority, 
          function(errorDesc: any, token: any, error: any, tokenType: any) {
              console.log('calling acquireTokenSilent with scopes: ' + tenantConfig.b2cScopes);
              console.log('idtoken: ' + token)
              if (token) {
                  this.acquireTokenSilent(tenantConfig.b2cScopes).then(function (accessToken) {
                      // Change button to Sign Out
                      console.log('acquireTokenSilent');
                      sessionStorage.setItem("b2c.api.access.token", accessToken);
                  }, function (error) {
                      console.log(error);
                      this.acquireTokenPopup(tenantConfig.b2cScopes).then(function (accessToken) {
                          console.log('acquireTokenPopup');
                          sessionStorage.setItem("b2c.api.access.token", accessToken);
                      }, function (error) {
                          console.log(error);
                      });
                  });
              }
              else if (errorDesc || error) {
                  console.log(error + ':' + errorDesc);
              }
          },
          { 
              logger: this.logger,
          });
  
      loginRedirect(): void {
          console.log('scopes: ' + tenantConfig.b2cScopes);
          this.clientApplication.loginRedirect(tenantConfig.b2cScopes);
      }
  
      login() : void {
          var _this = this;
          this.clientApplication.loginPopup(tenantConfig.b2cScopes).then(function (idToken: any) {
              _this.clientApplication.acquireTokenSilent(tenantConfig.b2cScopes).then(
                  function (accessToken: any) {
                      _this.saveAccessTokenToCache(accessToken);
                  }, function (error: any) {
                      _this.clientApplication.acquireTokenPopup(tenantConfig.b2cScopes).then(
                          function (accessToken: any) {
                              _this.saveAccessTokenToCache(accessToken);
                          }, function (error: any) {
                              //bootbox.alert("Error acquiring the popup:\n" + error);
                              console.log("Error acquiring the popup:\n" + error)
                          });
                  })
          }, function (error: any) {
              //bootbox.alert("Error during login:\n" + error);
              console.log("Error during login:\n" + error);
          });
      }
  
      getTokenFromCache() : string {
          return sessionStorage.getItem(B2CTodoAccessTokenKey);
      }
  
      saveAccessTokenToCache(accessToken: string): void {
          sessionStorage.setItem(B2CTodoAccessTokenKey, accessToken);
      }
  
      logout(): void{
          this.clientApplication.logout();
      }
  
      isLoggedIn(): boolean {        
          var user = this.clientApplication.getUser();
  
          console.log('isLogged In: ' + (user != null));        
          console.log('token in cache ' + (this.getTokenFromCache() != null))
          //console.log('token: ' + this.getTokenFromCache());
          return this.clientApplication.getUser() != null &amp;&amp; this.getTokenFromCache() != null; 
  
      }
  }
  </code></pre>
  
  <p>Finally, this is my environment values:</p>
  
  <pre><code>export default {
      b2cTenant: "[tenant].onmicrosoft.com",
      b2cClientID: '[app-id]',
      b2cSignUpSignInPolicy: "[policy]",
      b2cScopes: ["https://[tenant].onmicrosoft.com/apidemo/read", "https://[tenant].onmicrosoft.com/apidemo/user_impersonation"]
  };
  </code></pre>
  
  <p>Here is pictures of the Azure setup:</p>
  
  <p>API properties:
  <a href="https://i.stack.imgur.com/23fr5.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/23fr5.png" alt="API properties"></a></p>
  
  <p>API published scopes:
  <a href="https://i.stack.imgur.com/mHMjT.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/mHMjT.png" alt="API published scopes"></a></p>
  
  <p>Client API access:
  <a href="https://i.stack.imgur.com/xPOAF.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/xPOAF.png" alt="Client API access"></a></p>
  
  <p>Why is the value of the scopes variable NULL? What did I miss?
  The owner variable contains a value!</p>
  
  <p>Best regards</p>