У меня есть новое приложение .Net Core Razor, которое использует локальные учетные записи, и я пытаюсь добавить федеративную аутентификацию, используя IDP нашей компании (сервис SAML2 от Computer Associates).IDP не предоставляет MetadabaseAddress, поэтому мне приходится все настраивать вручную.Я могу нажать новую кнопку «Вход» и быть перенаправлен на страницу входа в систему IDP, и после входа в систему я перенаправлен на страницу входа в мои приложения, но там я получаю сообщение об ошибке «Нет сообщения».
Я отследил источник ошибки до класса WsFederationHandler.cs здесь , и оказалось, что обработчик не может найти токен saml, однако, используя браузерыИнструменты разработчика. Я вижу, что данные формы содержат маркер в виде (как представляется) строки в кодировке base-64.
Вот мой код:
public class Startup
{
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)
{
services.AddDbContext<ApplicationContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
// Password settings for local accounts
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequiredUniqueChars = 2;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.User.RequireUniqueEmail = true;
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@!$";
})
.AddEntityFrameworkStores<ApplicationContext>()
.AddDefaultTokenProviders();
// Creating the configuration object for WsFederation so we can access more settings
// This is used in lieu of retrieving the MetadataBase xml file from the IDP
var wsfConfig = new WsFederationConfiguration
{
TokenEndpoint = Configuration.GetValue<string>("MyAccess:TokenEndpoint"), // This is where the user gets redirected to, provided by the MyAccess team. Example: https://federatetest.smext.faa.gov/affwebservices/public/saml2sso?SPID=https://training.amc.faa.gov
Issuer = Configuration.GetValue<string>("MyAccess:Issuer") // This is the entityId from the settings Xml file, typically the URI of the application
};
// Add the certificate that will be used by the IDP to sign (encrypt) the token; this way we know how to decrypt the token
// The cert is a base64 encoded string
wsfConfig.SigningKeys.Add(new X509SecurityKey(new X509Certificate2(Convert.FromBase64String(Configuration.GetValue<string>("MyAccess:Certificate")))));
services.AddAuthentication(authOptions =>
{
authOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
authOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
authOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
})
.AddWsFederation(WsFederationDefaults.AuthenticationScheme, "My Access", options =>
{
options.Configuration = wsfConfig;
options.Wreply = Configuration.GetValue<string>("MyAccess:Reply");
options.Wtrealm = Configuration.GetValue<string>("MyAccess:Realm");
options.TokenValidationParameters.NameClaimType = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress";
//options.SkipUnrecognizedRequests = true;
// Uncomment if IDP requires a wct value
//options.Events.OnRedirectToIdentityProvider = context =>
// {
// context.ProtocolMessage.Wct = DateTimeOffset.UtcNow.ToString();
// return Task.CompletedTask;
// };
})
.AddCookie();
//Configure D I
services.AddScoped<IEmployeeStore, EmployeeStore>();
services.AddScoped<IDepartmentStore, DepartmentStore>();
// Configure additional services
services.AddMvc();
// Adds a default in-memory implementation of IDistributedCache.
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
// Set the session timeout
options.IdleTimeout = TimeSpan.FromMinutes(45);
options.Cookie.Name = ".EmployeeTracker.Session";
});
// This is where we define our authorization policies
services.AddAuthorization(options =>
{
options.AddPolicy("EmployeeViewer", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireClaim("Role", "admin");
});
});
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(45);
options.LoginPath = "/Login/Login";
options.SlidingExpiration = true;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, UserManager<ApplicationUser> userManager)
{
GlobalDiagnosticsContext.Set("configDir", Configuration.GetSection("AppSettings")["NLogDir"]);
GlobalDiagnosticsContext.Set("connectionString", Configuration.GetConnectionString("DefaultConnection"));
if (env.IsDevelopment())
{
// Only enable BrowserLink if it's really needed. It's a resource hog.
//app.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// Configure security settings
app.UseXContentTypeOptions(); // sets the X-Content-Type-Options to no-sniff
app.UseReferrerPolicy(opts => opts.NoReferrer());
app.UseXXssProtection(options => options.EnabledWithBlockMode());
app.UseXfo(options => options.Deny()); // Block iframes
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts(hsts => hsts.MaxAge(1).IncludeSubdomains());
}
// Configure middleware
app.UseAuthentication();
app.UseStaticFiles();
app.UseStatusCodePagesWithReExecute("/Status{0}"); // Status403.cshtml, Status404.cshtml, etc.
app.UseCookiePolicy();
app.UseSession();
app.UseMvc();
}
}
Вот что яв инструментах разработчика:
Поскольку мне приходится настраивать вещи вручную, из этого следует, что я что-то упустил.Кроме того, просто чтобы подтвердить свои подозрения, я добавил опцию в SkipUnrecognizedRequests и получил другую ошибку.
TIA для любой помощи, которую вы можете предоставить.