可以使用令牌端点中的_refresh_token_来更新声明。在配置OpenID Connect时,需要在OnTokenValidated事件中手动请求并使用刷新令牌获取新的声明。
示例代码如下:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.ForwardAuthenticate = OpenIdConnectDefaults.AuthenticationScheme;
options.ForwardSignIn = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddOpenIdConnect(options =>
{
options.ClientId = Configuration["OpenIdConnect:ClientId"];
options.ClientSecret = Configuration["OpenIdConnect:ClientSecret"];
options.Authority = Configuration["OpenIdConnect:Authority"];
options.CallbackPath = new PathString("/auth/signin-callback");
// Request refresh token
options.ResponseType = "code id_token token";
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("offline_access");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Events = new OpenIdConnectEvents
{
OnTokenValidated = async ctx =>
{
var refreshToken = ctx.TokenEndpointResponse.RefreshToken;
if (refreshToken != null)
{
var newClaims = new List
{
new Claim("newClaimType", "newClaimValue")
};
var appOptions = ctx.HttpContext.RequestServices.GetRequiredService>().Value;
var tokenClient = new TokenClient(appOptions.TokenEndpoint, appOptions.ClientId, appOptions.ClientSecret);
var tokenResult = await tokenClient.RequestRefreshTokenAsync(refreshToken);
if (tokenResult.IsError)
{
throw new Exception(tokenResult.Error);
}
foreach (var claim in tokenResult.Claims)
{
newClaims.Add(new Claim(claim.Type, claim.Value));
}
var identity = ctx.Principal.Identity as ClaimsIdentity;
identity?.AddClaims(newClaims);
}
}
};
});
注:在请求刷新令牌时,需要在OpenID Connect配置中设置options.ResponseType = "code id_token token"
以请求令牌响应中包含刷新令牌。