我试图使用ws-federation与.net core来处理单点登录。我已经能够从我的联盟服务中接收到一个安全令牌,但是从安全令牌中获取的声明并没有被添加到正在被认证的用户中,而且即使在令牌被验证后,一个cookie被写入,用户也没有得到一个更新的身份或声明集,使用户处于一个HttpContext.User.Identity.IsAuthenticated总是被设置为false的状态。
我的ConfigureServies。
public void ConfigureServices(IServiceCollection services)
{
IdentityModelEventSource.ShowPII = true;
services.AddControllersWithViews();
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}
).AddWsFederation(options =>
{
WsFederationConfiguration configuration = new WsFederationConfiguration();
configuration.Issuer = "http://localhost/STSSpike2/V1";
configuration.TokenEndpoint = "http://localhost/STSSpike/V1";
options.Configuration = configuration;
options.Wtrealm = "http://localhost/STSAwareApp/Test";
options.Wreply = "http://localhost/STSAwareApp/signin-wsfed";
options.SecurityTokenHandlers.Add(new FakeTokenValidator());
options.Events.OnAuthenticationFailed = context =>
{
Console.WriteLine(context.Exception.ToString());
return Task.CompletedTask;
};
options.Events.OnAccessDenied = context =>
{
Console.WriteLine(context);
return Task.CompletedTask;
};
options.Events.OnRemoteFailure = context =>
{
Console.WriteLine(context.Failure);
return Task.CompletedTask;
};
options.Events.OnSecurityTokenReceived = context =>
{
Console.WriteLine(context.ProtocolMessage);
return Task.CompletedTask;
};
options.Events.OnSecurityTokenValidated = context =>
{
Console.WriteLine(context);
return Task.CompletedTask;
};
}).AddCookie(options =>
{
options.Cookie.Name = "TestStsAuth1";
options.ExpireTimeSpan = new TimeSpan(0, 30, 0);
options.Cookie.IsEssential = true;
//options.Cookie.HttpOnly = true;
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None;
options.Events = new CookieAuthenticationEvents
{
OnValidatePrincipal = val =>
{
Console.WriteLine("validated");
return Task.CompletedTask;
},
OnRedirectToAccessDenied = denied =>
{
Console.WriteLine("validated");
return Task.CompletedTask;
},
OnRedirectToReturnUrl = redirect =>
{
Console.WriteLine("validated");
return Task.CompletedTask;
},
OnSignedIn = signedIn =>
{
Console.WriteLine("Signedin");
return Task.CompletedTask;
},
OnSigningIn = signingIn =>
{
Console.WriteLine("signing in");
return Task.CompletedTask;
}
};
});
services.AddLogging(
builder =>
{
builder.AddFilter("Microsoft", LogLevel.Trace)
.AddFilter("System", LogLevel.Trace)
.AddConsole();
});
}
在上面的代码中,Events.OnSecurityTokenValidated和CookieOptions.Events.OnSignedIn指向的Principle是来自ws-federation返回的安全令牌。然而,HttpContext.User从来没有更新过新的身份。所以,一旦安全令牌被验证,客户端就会反复调用回联盟服务器请求令牌,唯一的日志信息是:Microsoft.AspNetCore.Authorization.DefaultAuthorizationService: Information.AspNetCore.Authorization.DefaultAuthorizationService:信息。授权失败。
问题来自于我的Configure调用,我在调用UseAuthorization之前调用了UseAuthentication。这个答案是找出问题所在的关键。