使用MSAL访问Azure AD并获取身份验证id令牌时出现版本问题 Asp.NETCoreV2.2.0 Microsoft.AspNetCore.Authentication.AzureAD.UI v2.2.0 Microsoft.Identity.Client v4.2.1
我在登录Azure AD并请求验证id令牌时收到以下错误: 在搜索解决方案时,我发现最接近的一点是,使用两个不同版本的auth api存在问题。V2使用login.microsoftonline.com,V1使用sts.windows.net。我的问题是如何让MSAL库中的所有内容都使用V2 这是我的创业课程。它主要基于从文档中复制的内容:使用MSAL访问Azure AD并获取身份验证id令牌时出现版本问题 Asp.NETCoreV2.2.0 Microsoft.AspNetCore.Authentication.AzureAD.UI v2.2.0 Microsoft.Identity.Client v4.2.1,authentication,asp.net-core,azure-active-directory,msal,Authentication,Asp.net Core,Azure Active Directory,Msal,我在登录Azure AD并请求验证id令牌时收到以下错误: 在搜索解决方案时,我发现最接近的一点是,使用两个不同版本的auth api存在问题。V2使用login.microsoftonline.com,V1使用sts.windows.net。我的问题是如何让MSAL库中的所有内容都使用V2 这是我的创业课程。它主要基于从文档中复制的内容: 问题是我用的是 AzureADDefaults.OpenIdScheme 而不是 AzureADDefaults.AuthenticationScheme
问题是我用的是 AzureADDefaults.OpenIdScheme 而不是 AzureADDefaults.AuthenticationScheme默认Azure AD方案 考虑到这个问题,这很有道理
public class Startup
{
private const string AzureAdConfigSectionName = "AzureAd";
private ConfidentialClientApplicationOptions applicationOptions;
private AzureADOptions azureAdOptions;
private MsalPerUserSessionTokenCacheProvider userTokenCacheProvider;
private MsalAppSessionTokenCacheProvider appTokenCacheProvider;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
applicationOptions = new ConfidentialClientApplicationOptions();
Configuration.Bind(AzureAdConfigSectionName, applicationOptions);
azureAdOptions = new AzureADOptions();
Configuration.Bind(AzureAdConfigSectionName, azureAdOptions);
//services.AddOptions<AzureADOptions>();
var adOptionsMonitor = services.BuildServiceProvider().GetService<IOptionsMonitor<AzureADOptions>>();
userTokenCacheProvider = new MsalPerUserSessionTokenCacheProvider();
appTokenCacheProvider = new MsalAppSessionTokenCacheProvider(adOptionsMonitor);
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind(AzureAdConfigSectionName, options));
ConfigureSession(services);
ConfigureTokenHandling(services);
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
private void ConfigureSession(IServiceCollection services)
{
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
}
private void ConfigureTokenHandling(IServiceCollection services)
{
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
// Response type. We ask ASP.NET to request an Auth Code, and an IDToken
options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
// This "offline_access" scope is needed to get a refresh token when users sign in with
// their Microsoft personal accounts
// (it's required by MSAL.NET and automatically provided by Azure AD when users
// sign in with work or school accounts, but not with their Microsoft personal accounts)
options.Scope.Add("offline_access");
options.Scope.Add("user.read"); // for instance
// Handling the auth redemption by MSAL.NET so that a token is available in the token cache
// where it will be usable from Controllers later (through the TokenAcquisition service)
var handler = options.Events.OnAuthorizationCodeReceived;
options.Events.OnAuthorizationCodeReceived = async context =>
{
// As AcquireTokenByAuthorizationCode is asynchronous we want to tell ASP.NET core
// that we are handing the code even if it's not done yet, so that it does
// not concurrently call the Token endpoint.
context.HandleCodeRedemption();
// Call MSAL.NET AcquireTokenByAuthorizationCode
var application = BuildConfidentialClientApplication(context.HttpContext,
context.Principal);
var scopes = new [] { "user.read" };
var scopesRequestedByMsalNet = new[] { "openid", "profile", "offline_access" };
var result = await application
.AcquireTokenByAuthorizationCode(scopes.Except(scopesRequestedByMsalNet),
context.ProtocolMessage.Code)
.ExecuteAsync();
// Do not share the access token with ASP.NET Core otherwise ASP.NET will cache it
// and will not send the OAuth 2.0 request in case a further call to
// AcquireTokenByAuthorizationCodeAsync in the future for incremental consent
// (getting a code requesting more scopes)
// Share the ID Token so that the identity of the user is known in the application (in
// HttpContext.User)
context.HandleCodeRedemption(null, result.IdToken);
// Call the previous handler if any
await handler(context);
};
});
}
/// <summary>
/// Creates an MSAL Confidential client application
/// </summary>
/// <param name="httpContext">HttpContext associated with the OIDC response</param>
/// <param name="claimsPrincipal">Identity for the signed-in user</param>
/// <returns></returns>
private IConfidentialClientApplication BuildConfidentialClientApplication(HttpContext httpContext,
ClaimsPrincipal claimsPrincipal)
{
var request = httpContext.Request;
// Find the URI of the application)
var currentUri = UriHelper.BuildAbsolute(request.Scheme,
request.Host,
request.PathBase,
azureAdOptions.CallbackPath ?? String.Empty);
// Updates the authority from the instance (including national clouds) and the tenant
var authority = $"{azureAdOptions.Instance}{azureAdOptions.TenantId}/";
// Instantiates the application based on the application options (including the client secret)
var app = ConfidentialClientApplicationBuilder.CreateWithApplicationOptions(applicationOptions)
.WithRedirectUri(currentUri)
.WithAuthority(authority)
.Build();
// Initialize token cache providers. In the case of Web applications, there must be one
// token cache per user (here the key of the token cache is in the claimsPrincipal which
// contains the identity of the signed-in user)
userTokenCacheProvider?.Initialize(app.UserTokenCache, httpContext, claimsPrincipal);
appTokenCacheProvider?.Initialize(app.AppTokenCache, httpContext);
return app;
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
IdentityModelEventSource.ShowPII = true;
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios,
// see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseSession();
app.UseAuthentication();
app.UseMvc();
}
}
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "{domain}",
"TenantId": "{tenant id}",
"ClientId": "{client id}",
"CallbackPath": "/signin-oidc",
"ClientSecret": "{client secret}"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}