我正在尝试使用Azure B2C AD保护我的Web api,并使用Angular 4 SPA使用该Web api。但是,由于某些原因,即使其他声明也可以正常工作,范围声明始终为空。
我在Angular应用中使用的MSAL库版本为0.1.6,并且一直在遵循本指南:https://github.com/Azure-Samples/active-directory-b2c-javascript-angular2.4-spa
这是我的网络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))),
});
}
}
这是我的控制者:
[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"};
}
}
owner变量包含预期的GUID,但是scopes变量始终为NULL。
这是我的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;
}
}
最后,这是我的环境值:
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"]
};
以下是Azure设置的图片:
为什么范围变量的值为NULL?我错过了什么? owner变量包含一个值!
最诚挚的问候
答案 0 :(得分:0)
尝试运行提琴手以查看发生了什么情况。
请查看this issue是否与您相关。
答案 1 :(得分:0)
使用其他客户端库解决了该问题:https://github.com/damienbod/angular-auth-oidc-client
万一有人使用MSAL库发布了解决方案,我当然会将其标记为解决方案