【发布时间】:2022-03-04 06:30:06
【问题描述】:
我有一个将 access_token 传递给下游 API 的 asp.netcore MVC 应用程序。
经过一番努力,我想出了如何使用 MSAL.Net 获取 access_token。但是访问令牌每小时都会过期,所以我不得不刷新它。所以我使用AcquireTokenSilent,它接受account作为参数。
我的 Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.Events= new CookieAuthenticationEvents()
{
OnValidatePrincipal = OnValidatePrincipal
};
})
.AddOpenIdConnect(options =>
{
options.Authority = "https://login.microsoftonline.com/{tenantId}/v2.0";
options.ClientId = Configuration["AzureAD:ClientId"];
options.ClientSecret = Configuration["AzureAD:ClientSecret"];
options.CallbackPath = Configuration["AzureAD:CallbackPath"];
options.ResponseType = "code id_token";
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("offline_access");
options.Scope.Add("api://{ClientidOfAPI}/user_impersonation");
options.SaveTokens = true;
options.Events= new OpenIdConnectEvents()
{
OnAuthorizationCodeReceived = OnAuthorizationCodeReceived
};
});
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
private async Task OnValidatePrincipal(CookieValidatePrincipalContext context)
{
var application = GetOrBuildConfidentialClientApplication(context.HttpContext, context.Principal);
var accounts = await application.GetAccountsAsync();
AuthenticationResult result = await application.AcquireTokenSilent(
new []{ "openid", "profile", "offline_access", "api://{ClientidOfAPI}/user_impersonation" },
accounts.FirstOrDefault()).ExecuteAsync();
}
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
{
var application = GetOrBuildConfidentialClientApplication(context.HttpContext, context.Principal);
var result = await application.AcquireTokenByAuthorizationCode(new [] { "api://{ClientidOfAPI}/user_impersonation" }, context.ProtocolMessage.Code)
.ExecuteAsync();
context.HandleCodeRedemption(result.AccessToken, result.IdToken);
}
private IConfidentialClientApplication GetOrBuildConfidentialClientApplication(HttpContext httpContext, ClaimsPrincipal claimsPrincipal)
{
var request = httpContext.Request;
string currentUri = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, "/signin-oidc" ?? string.Empty);
string authority = $"https://login.microsoftonline.com/{tenantid}/v2.0";
var app = ConfidentialClientApplicationBuilder.CreateWithApplicationOptions(new ConfidentialClientApplicationOptions()
{
ClientId = "Clientid of Client"
ClientSecret = "password of Client"
})
.WithRedirectUri(currentUri)
.WithAuthority(authority)
.Build();
return app;
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
...
app.UseAuthentication();
app.UseMvc();
}
但调用 AcquireTokenSilent 方法的 OnValidatePrincipal 无法获取账户,账户返回为空。
var accounts = await application.GetAccountsAsync();
不知道为什么我得到一个空的帐户列表。有没有更好的方法来刷新 access_token?
更新:
我稍微更改了 Startup.cs。我已经从 Startup 中删除了 OnValidatePrinciple () 并将该功能添加到 AquireTokenSilently() 到 Controller 操作。结果还是一样。
我是否需要实现缓存以从 GetAccountsAsync() 中获取价值?据我所知,我不会手动进行缓存?
【问题讨论】:
-
您好,您找到解决方案了吗?有同样的问题。谢谢!
标签: c# asp.net-core oauth-2.0 azure-active-directory