Code
Der gezeigte Code ist nur eine Auswahl des Beispielcodes in GitHub.
Das ITfoxtec Identity Saml2 Paket wird in eine ASP.NET MVC Core Relying Party (RP) Anwendung durch Konfiguration in Startup und durch Hinzufügen eines Auth Controllers mit den folgenden vier Methoden integriert. Die gezeigte Binding kann je nach Anforderungen angepasst werden.
Außerdem ist es möglich, einige optionale Parameter für Saml2AuthnRequest und Saml2LogoutRequest zu setzen. Bei Saml2AuthnRequest wird z. B. ForceAuthn unterstützt, was den Benutzer zwingt, Anmeldeinformationen einzugeben, auch wenn bereits ein SSO Kontext beim Security Token Service (STS) / Identity Provider (IdP) existiert.
Fügen Sie die Konfiguration zur ConfigureServices Methode in Startup hinzu
Konfiguration mit IdP Metadaten.
services.Configure<Saml2Configuration>(Configuration.GetSection("Saml2"));
services.Configure<Saml2Configuration>(saml2Configuration =>
{
saml2Configuration.SigningCertificate = CertificateUtil.Load(AppEnvironment.MapToPhysicalFilePath(
Configuration["Saml2:SigningCertificateFile"]), Configuration["Saml2:SigningCertificatePassword"]);
saml2Configuration.AllowedAudienceUris.Add(saml2Configuration.Issuer);
var entityDescriptor = new EntityDescriptor();
entityDescriptor.ReadIdPSsoDescriptorFromUrl(new Uri(Configuration["Saml2:IdPMetadata"]));
if (entityDescriptor.IdPSsoDescriptor != null)
{
saml2Configuration.SingleSignOnDestination = entityDescriptor.IdPSsoDescriptor.SingleSignOnServices.First().Location;
saml2Configuration.SingleLogoutDestination = entityDescriptor.IdPSsoDescriptor.SingleLogoutServices.First().Location;
saml2Configuration.SignatureValidationCertificates.AddRange(entityDescriptor.IdPSsoDescriptor.SigningCertificates);
}
else
{
throw new Exception("IdPSsoDescriptor not loaded from metadata.");
}
});
services.AddSaml2();
Konfiguration ohne Metadaten.
services.Configure<Saml2Configuration>(Configuration.GetSection("Saml2"));
services.Configure<Saml2Configuration>(saml2Configuration =>
{
saml2Configuration.SigningCertificate = CertificateUtil.Load(AppEnvironment.MapToPhysicalFilePath(
Configuration["Saml2:SigningCertificateFile"]), Configuration["Saml2:SigningCertificatePassword"]);
saml2Configuration.AllowedAudienceUris.Add(saml2Configuration.Issuer);
saml2Configuration.SignatureValidationCertificates.Add(CertificateUtil.Load(AppEnvironment.MapToPhysicalFilePath(
Configuration["Saml2:SignatureValidationCertificateFile"])));
});
services.AddSaml2();
Login Methode im Auth Controller
[Route("Login")]
public IActionResult Login(string returnUrl = null)
{
var binding = new Saml2RedirectBinding();
binding.SetRelayStateQuery(new Dictionary<string, string>
{ { relayStateReturnUrl, returnUrl ?? Url.Content("~/") } });
return binding.Bind(new Saml2AuthnRequest(config)).ToActionResult();
}
AssertionConsumerService Methode im Auth Controller
Nach erfolgreichem oder fehlgeschlagenem Login erhält die ACS Methode die Antwort.
[Route("AssertionConsumerService")]
public async Task<IActionResult> AssertionConsumerService()
{
var httpRequest = Request.ToGenericHttpRequest(validate: true);
var saml2AuthnResponse = new Saml2AuthnResponse(config);
httpRequest.Binding.Unbind(httpRequest, saml2AuthnResponse);
await saml2AuthnResponse.CreateSession(HttpContext,
ClaimsTransform: (claimsPrincipal) => ClaimsTransform.Transform(claimsPrincipal));
var returnUrl = httpRequest.Binding.GetRelayStateQuery()[relayStateReturnUrl];
return Redirect(string.IsNullOrWhiteSpace(returnUrl) ? Url.Content("~/") : returnUrl);
}
Logout Methode im Auth Controller
[HttpPost("Logout")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout()
{
if (!User.Identity.IsAuthenticated)
{
return Redirect(Url.Content("~/"));
}
var binding = new Saml2PostBinding();
var saml2LogoutRequest = await new Saml2LogoutRequest(config, User).DeleteSession(HttpContext);
return binding.Bind(saml2LogoutRequest).ToActionResult();
}
LoggedOut Methode im Auth Controller
Nach erfolgreichem oder fehlgeschlagenem Logout erhält die LoggedOut Methode die Antwort.
[Route("LoggedOut")]
public IActionResult LoggedOut()
{
var httpRequest = Request.ToGenericHttpRequest(validate: true);
httpRequest.Binding.Unbind(httpRequest, new Saml2LogoutResponse(config));
return Redirect(Url.Content("~/"));
}
SingleLogout Methode im Auth Controller
Empfängt eine Single Logout Anfrage und sendet eine Antwort.
[Route("SingleLogout")]
public async Task<IActionResult> SingleLogout()
{
Saml2StatusCodes status;
var httpRequest = Request.ToGenericHttpRequest(validate: true);
var logoutRequest = new Saml2LogoutRequest(config, User);
try
{
httpRequest.Binding.Unbind(httpRequest, logoutRequest);
status = Saml2StatusCodes.Success;
await logoutRequest.DeleteSession(HttpContext);
}
catch (Exception exc)
{
// log exception
Debug.WriteLine("SingleLogout error: " + exc.ToString());
status = Saml2StatusCodes.RequestDenied;
}
var responseBinding = new Saml2PostBinding();
responseBinding.RelayState = httpRequest.Binding.RelayState;
var saml2LogoutResponse = new Saml2LogoutResponse(config)
{
InResponseToAsString = logoutRequest.IdAsString,
Status = status,
};
return responseBinding.Bind(saml2LogoutResponse).ToActionResult();
}