Scope claim is null when requesting web api from Angular 4 SPA


Scope claim is null when requesting web api from Angular 4 SPA



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.



I am using the MSAL library version 0.1.6 in the Angular app and have been following this guide: https://github.com/Azure-Samples/active-directory-b2c-javascript-angular2.4-spa



This is my web api startup.auth:


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 & signing keys from the OpenIDConnect metadata endpoint
AccessTokenFormat = new JwtFormat(tvps, new OpenIdConnectCachingSecurityTokenProvider(String.Format(AadInstance, Tenant, DefaultPolicy))),

});
}
}



This is my controller:


[Authorize]
[EnableCors(origins: "*", headers: "*", methods: "*")] // tune to your needs
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> 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"};
}
}



The owner variable contains a GUID as expected, however the scopes variable is always NULL.



This is my auth.service.ts:


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 && this.getTokenFromCache() != null;

}
}



Finally, this is my environment values:


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"]
};



Here is pictures of the Azure setup:



API properties:
API properties



API published scopes:
API published scopes



Client API access:
Client API access



Why is the value of the scopes variable NULL? What did I miss?
The owner variable contains a value!



Best regards





In the Azure AD B2C portal, did you grant access by your web app to your web API, using the API Access blade (see docs.microsoft.com/en-us/azure/active-directory-b2c/…)?
– Chris Padgett
Jul 3 at 11:19





I am not sure I did it correctly - I will update the psot with screenshots of the current setup
– Hos
Jul 3 at 11:55









By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

api-platform.com Unable to generate an IRI for the item of type

How to set up datasource with Spring for HikariCP?

Display dokan vendor name on Woocommerce single product pages