ADAL 到 MSAL 迁移保护 Web API
Posted
技术标签:
【中文标题】ADAL 到 MSAL 迁移保护 Web API【英文标题】:ADAL to MSAL Migration Securing Web API 【发布时间】:2021-07-16 03:50:09 【问题描述】:我正在开展一个将 ADAL 迁移到 MSAL 的项目。 UI 部分是 Angular,Web API 是 .Net Framework 4.7.2。 在 Startup.Auth.cs 中,我看到代码在验证传入的 API 请求时非常有效。但是,当我在 Angular 中更改从 MSAL 获取的令牌并将熊令牌发送到 API 时,API 无法告知用户已通过身份验证,也无法告知用户是谁(它将始终返回 false)。
我看到很多来自 .net Core 的例子,有没有什么好的方法可以在 .net Framework 中进行更改?
public void ConfigureAuth(IAppBuilder app)
var constants = UnityConfig.GetConfiguredContainer().Resolve<IConstants>();
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
Tenant = constants.TenantId,
TokenValidationParameters = new TokenValidationParameters
ValidAudiences = new List<string> constants.Audience, constants.ClientId
,
AuthenticationType = "OAuth2Bearer",
AuthenticationMode = AuthenticationMode.Active
);
【问题讨论】:
【参考方案1】:你可以使用我的 nuget,MSALTokenGeneratorv3。
public static async Task ConfidentialClientBuilderApp(string resource = null, string clientId = null, 字符串 clientSecret = null,字符串权限 = null,IEnumerable scopes = null) // 我们将使用 MSAL.NET 获取令牌以代表当前用户调用 API 尝试 // 使用构建模式创建一个 ConfidentialClientApplication (https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Client-Applications) ExponentialRetryStrategy retryStrategy = new ExponentialRetryStrategy();
_confidentialClientApp = ConfidentialClientApplicationBuilder.Create(clientId)
.WithAuthority(String.Format(CultureInfo.InvariantCulture, authority))
.WithClientSecret(clientSecret).WithLegacyCacheCompatibility(false)
.Build();
// In memory distributed token cache
_confidentialClientApp.AddInMemoryTokenCache();
// Acquiring an AuthenticationResult for the scope user.read, impersonating the user represented by userAssertion, using the OBO flow
await RetryHelper.RetryAsync(async () =>
_authenticationResult = await _confidentialClientApp.AcquireTokenForClient(scopes).ExecuteAsync().ConfigureAwait(false);
, (exception) =>
return true;
, retryStrategy.ShouldRetry(), new Action<Exception, RetryErrorType, int>(LogTokenGenerationFailure)).ConfigureAwait(false);
if (_authenticationResult != null && !string.IsNullOrEmpty(_authenticationResult.AccessToken))
accessToken = _authenticationResult.AccessToken;
if (accessToken == null)
throw new Exception("Access Token could not be acquired.");
return accessToken;
catch (MsalUiRequiredException)
/*
* If you used the scope `.default` on the client application, the user would have been prompted to consent for Graph API back there
* and no incremental consents are required (this exception is not expected). However, if you are using the scope `access_as_user`,
* this exception will be thrown at the first time the API tries to access Graph on behalf of the user for an incremental consent.
* You must then, add the logic to delegate the consent screen to your client application here.
* This sample doesn't use the incremental consent strategy.
*/
throw;
catch (Exception)
throw;
public static async Task PublicClientBuilderApp(IEnumerable scope, string tenantId, string clientId = null, 字符串用户名 = null,字符串密码 = null) ConvertStringToSecureString convertToSecureString = new ConvertStringToSecureString(); ExponentialRetryStrategy retryStrategy = new ExponentialRetryStrategy();
// We will use MSAL.NET to get a token to call the API On Behalf Of the current user
try
_publicClientApp = PublicClientApplicationBuilder.Create(clientId).WithAuthority(AzureCloudInstance.AzurePublic,
tenantId).WithLegacyCacheCompatibility(false).Build();
// Acquiring an AuthenticationResult for the scope user.read, impersonating the user represented by userAssertion, using the OBO flow
await RetryHelper.RetryAsync(async () =>
//To clear the token cache every time the new request comes , else it uses cached userassertion
var accounts = await _publicClientApp.GetAccountsAsync().ConfigureAwait(false);
IEnumerator<IAccount> enumerator = accounts.GetEnumerator();
while (enumerator.Current != null)
await _publicClientApp.RemoveAsync(enumerator.Current).ConfigureAwait(false);
// Acquiring an AuthenticationResult for the scope user.read, impersonating the user represented by userAssertion, using the OBO flow
_authenticationResult = await _publicClientApp.AcquireTokenByUsernamePassword(scope, userName, convertToSecureString.StringToSecureString(password)).ExecuteAsync().ConfigureAwait(false);
, (exception) =>
return true;
, retryStrategy.ShouldRetry(), new Action<Exception, RetryErrorType, int>(LogTokenGenerationFailure)).ConfigureAwait(false);
if (_authenticationResult != null && !string.IsNullOrEmpty(_authenticationResult.AccessToken))
accessToken = _authenticationResult.AccessToken;
if (accessToken == null)
throw new Exception("Access Token could not be acquired.");
return accessToken;
catch (MsalUiRequiredException)
/*
* If you used the scope `.default` on the client application, the user would have been prompted to consent for Graph API back there
* and no incremental consents are required (this exception is not expected). However, if you are using the scope `access_as_user`,
* this exception will be thrown at the first time the API tries to access Graph on behalf of the user for an incremental consent.
* You must then, add the logic to delegate the consent screen to your client application here.
* This sample doesn't use the incremental consent strategy.
*/
throw;
catch (Exception)
throw;
public static void LogTokenGenerationFailure(Exception exception, RetryErrorType errorType, int retryCount)
【讨论】:
您的代码格式在这个答案中不是很一致(其中一些最终成为常规文本)。你能修复 C# 代码的降价吗?此外,您可能应该添加一些信息,说明您的包到底是做什么的,它拥有什么许可证,以及它是否是开源的等。在 Nuget 上,没有指向项目网站或 repo 的链接。谢谢! 非常好的反馈,周末会更新,非常感谢您的指出。以上是关于ADAL 到 MSAL 迁移保护 Web API的主要内容,如果未能解决你的问题,请参考以下文章
使用 MSAL 保护 ASP.Net Core Web API 和 Angular App
使用 react-aad-msal 缺少范围从 react SPA 调用 web api
如何在不使用 ADAL.js 或 MSAL.js 的情况下将我的 activiti 应用程序(版本 6)与 Azure Active Directory 端点 v2.0 集成