private void ValidateConfig(Saml2Configuration config) { _logger.LogDebug("ValidateConfiguration called"); if ( (config.ServiceProvider.SigningCertificate == null || !config.ServiceProvider.SigningCertificate.HasPrivateKey)) { //should probably error... } }
private Saml20AuthnRequest CreateAuthNRequest(Saml2Configuration config) { var authnRequest = Saml20AuthnRequest.GetDefault(config); var requestXml = authnRequest.GetXml(); if (config.ServiceProvider.AuthNRequestsSigned) { XmlSignatureUtils.SignDocument(requestXml, authnRequest.Id, config); } return(authnRequest); }
public Saml20SignonHandler(Saml2Configuration config) { _certificate = config.ServiceProvider.SigningCertificate; // Read the proper redirect url from config try { RedirectUrl = config.ServiceProvider.Endpoints.DefaultSignOnEndpoint.RedirectUrl; } catch (Exception e) { Logger.Error(e.Message, e); } }
private async Task <IActionResult> AuthnResponseAsync <T>(Saml2Configuration samlConfig, string inResponseTo, string relayState, string acsUrl, Saml2Binding <T> binding, Saml2StatusCodes status, SamlDownParty party = null, IEnumerable <Claim> claims = null) { binding.RelayState = relayState; var saml2AuthnResponse = new FoxIdsSaml2AuthnResponse(settings, samlConfig) { InResponseTo = new Saml2Id(inResponseTo), Status = status, Destination = new Uri(acsUrl), }; if (status == Saml2StatusCodes.Success && party != null && claims != null) { claims = await claimTransformationsLogic.Transform(party.ClaimTransformations?.ConvertAll(t => (ClaimTransformation)t), claims); saml2AuthnResponse.SessionIndex = claims.FindFirstValue(c => c.Type == Saml2ClaimTypes.SessionIndex); saml2AuthnResponse.NameId = GetNameId(claims); var tokenIssueTime = DateTimeOffset.UtcNow; var tokenDescriptor = saml2AuthnResponse.CreateTokenDescriptor(GetSubjectClaims(party, claims), party.Issuer, tokenIssueTime, party.IssuedTokenLifetime); var authnContext = claims.FindFirstValue(c => c.Type == ClaimTypes.AuthenticationMethod); var authenticationInstant = claims.FindFirstValue(c => c.Type == ClaimTypes.AuthenticationInstant); var authenticationStatement = saml2AuthnResponse.CreateAuthenticationStatement(authnContext, DateTime.Parse(authenticationInstant)); var subjectConfirmation = saml2AuthnResponse.CreateSubjectConfirmation(tokenIssueTime, party.SubjectConfirmationLifetime); await saml2AuthnResponse.CreateSecurityTokenAsync(tokenDescriptor, authenticationStatement, subjectConfirmation); } binding.Bind(saml2AuthnResponse); logger.ScopeTrace($"SAML Authn response '{saml2AuthnResponse.XmlDocument.OuterXml}'."); logger.ScopeTrace($"Acs url '{acsUrl}'."); logger.ScopeTrace("Down, SAML Authn response.", triggerEvent: true); await sequenceLogic.RemoveSequenceDataAsync <SamlDownSequenceData>(); await formActionLogic.RemoveFormActionSequenceDataAsync(); if (binding is Saml2Binding <Saml2RedirectBinding> ) { return(await Task.FromResult((binding as Saml2RedirectBinding).ToActionResult())); } else if (binding is Saml2Binding <Saml2PostBinding> ) { return(await Task.FromResult((binding as Saml2PostBinding).ToActionResult())); } else { throw new NotSupportedException(); } }
/// <summary> /// Constructor for LoginHandler /// </summary> /// <param name="configuration">SamlConfiguration</param> /// <param name="getFromCache">May be null unless doing artifact binding, this function will be called for artifact resolution</param> public SamlLoginHandler(SamlAuthenticationOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } this.options = options; configuration = options.Configuration; getFromCache = options.GetFromCache; setInCache = options.SetInCache; session = options.Session; }
/// <summary> /// Deserializes an assertion, verifies its signature and logs in the user if the assertion is valid. /// </summary> /// <param name="context">The context.</param> /// <param name="elem">The elem.</param> public static Saml20Assertion HandleAssertion(XmlElement elem, Saml2Configuration config, Func <string, object> getFromCache, Action <string, object, DateTime> setInCache) { logger.DebugFormat(TraceMessages.AssertionProcessing, elem.OuterXml); var issuer = GetIssuer(elem); var endp = IdpSelectionUtil.RetrieveIDPConfiguration(issuer, config); PreHandleAssertion(elem, endp); if (endp == null || endp.Metadata == null) { logger.Error(ErrorMessages.AssertionIdentityProviderUnknown); throw new Saml20Exception(ErrorMessages.AssertionIdentityProviderUnknown); } var quirksMode = endp.QuirksMode; var assertion = new Saml20Assertion(elem, null, quirksMode, config); // Check signatures if (!endp.OmitAssertionSignatureCheck) { var document = elem.OwnerDocument; if (!XmlSignatureUtils.CheckSignature(document)) { logger.Error(ErrorMessages.AssertionSignatureInvalid); throw new Saml20Exception(ErrorMessages.AssertionSignatureInvalid); } } // Check expiration if (assertion.IsExpired) { logger.Error(ErrorMessages.AssertionExpired); throw new Saml20Exception(ErrorMessages.AssertionExpired); } // Check one time use if (assertion.IsOneTimeUse) { if (getFromCache(assertion.Id) != null) { logger.Error(ErrorMessages.AssertionOneTimeUseExceeded); throw new Saml20Exception(ErrorMessages.AssertionOneTimeUseExceeded); } setInCache(assertion.Id, string.Empty, assertion.NotOnOrAfter); } logger.DebugFormat(TraceMessages.AssertionParsed, assertion.Id); return(assertion); }
/// <summary> /// Handles executing the logout. /// </summary> /// <param name="context">The context.</param> /// <param name="idpInitiated">if set to <c>true</c> identity provider is initiated.</param> private void DoLogout(HttpContext context, bool idpInitiated = false, Saml2Configuration config = null) { Logger.Debug(TraceMessages.LogoutActionsExecuting); // TODO: Event for logout actions //foreach (var action in Actions.Actions.GetActions(config)) //{ // Logger.DebugFormat("{0}.{1} called", action.GetType(), "LogoutAction()"); // action.LogoutAction(this, context, idpInitiated); // Logger.DebugFormat("{0}.{1} finished", action.GetType(), "LogoutAction()"); //} }
public MetadataUtils(Config.Saml2Configuration configuration, Logging.IInternalLogger logger) { if (configuration == null) { throw new ArgumentNullException("configuration"); } if (logger == null) { throw new ArgumentNullException("logger"); } this.configuration = configuration; this.logger = logger; }
public Logout(IInternalLogger logger, SAML2.Config.Saml2Configuration config) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (config == null) { throw new ArgumentNullException(nameof(config)); } this.logger = logger; this.config = config; }
public Logout(IInternalLogger logger, SAML2.DotNet35.Config.Saml2Configuration config) { if (logger == null) { throw new ArgumentNullException("logger"); } if (config == null) { throw new ArgumentNullException("config"); } this.logger = logger; this.config = config; }
public SAMLMetadataResult(Saml2Configuration config) { var metadata = new SAMLSilly.Saml20MetadataDocument().Load(config); metadata.Sign = true; StatusCode = (int)HttpStatusCode.OK; ContentType = Saml20Constants.MetadataMimetype; #if DEBUG ContentType = "text/xml"; #endif Content = metadata.ToXml(Encoding.UTF8, config.ServiceProvider.SigningCertificate, config.SigningAlgorithm); }
public AuthController(Models.IAuthenticationService authService) { _authService = authService; _samlConfig = new Saml2Configuration { Issuer = GlobalSettings.Get("CONFIG_CompanyName") + "-MAIN-ISSUER", SingleSignOnDestination = new Uri(GlobalSettings.Get("CONFIG_URL") + "/Auth/Login"), SingleLogoutDestination = new Uri(GlobalSettings.Get("CONFIG_URL") + "/Auth/Logout"), SigningCertificate = GlobalSettings._signingCertificate, CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.ChainTrust, RevocationMode = X509RevocationMode.NoCheck }; }
public EntityDescriptor(Saml2Configuration config) { if (config == null) { throw new ArgumentNullException(nameof(config)); } Config = config; EntityId = config.Issuer; Id = new Saml2Id(); MetadataSigningCertificate = config.SigningCertificate; CertificateIncludeOption = X509IncludeOption.EndCertOnly; }
/// <summary> /// Gets the decrypted assertion. /// </summary> /// <param name="elem">The elem.</param> /// <returns>The decrypted <see cref="Saml20EncryptedAssertion"/>.</returns> public Saml20EncryptedAssertion GetDecryptedAssertion(XmlElement elem, Saml2Configuration config) { _logger.LogDebug(TraceMessages.EncryptedAssertionDecrypting); var decryptedAssertion = new Saml20EncryptedAssertion((RSA)config.ServiceProvider.SigningCertificate.PrivateKey); decryptedAssertion.LoadXml(elem); decryptedAssertion.Decrypt(); _logger.LogDebug(TraceMessages.EncryptedAssertionDecrypted, decryptedAssertion.Assertion.DocumentElement.OuterXml); return(decryptedAssertion); }
/// <summary> /// Deserializes an assertion, verifies its signature and logs in the user if the assertion is valid. /// </summary> /// <param name="context">The context.</param> /// <param name="elem">The elem.</param> private void HandleAssertion(HttpContext context, XmlElement elem, Saml2Configuration config) { Logger.DebugFormat(TraceMessages.AssertionProcessing, elem.OuterXml); var issuer = GetIssuer(elem); var endp = IdpSelectionUtil.RetrieveIDPConfiguration(issuer, config); PreHandleAssertion(context, elem, endp); if (endp == null || endp.Metadata == null) { Logger.Error(ErrorMessages.AssertionIdentityProviderUnknown); throw new Saml20Exception(ErrorMessages.AssertionIdentityProviderUnknown); } var quirksMode = endp.QuirksMode; var assertion = new Saml20Assertion(elem, null, quirksMode, config); // Check signatures if (!endp.OmitAssertionSignatureCheck) { if (!assertion.CheckSignature(GetTrustedSigners(endp.Metadata.GetKeys(KeyTypes.Signing), endp))) { Logger.Error(ErrorMessages.AssertionSignatureInvalid); throw new Saml20Exception(ErrorMessages.AssertionSignatureInvalid); } } // Check expiration if (assertion.IsExpired) { Logger.Error(ErrorMessages.AssertionExpired); throw new Saml20Exception(ErrorMessages.AssertionExpired); } // Check one time use if (assertion.IsOneTimeUse) { if (context.Cache[assertion.Id] != null) { Logger.Error(ErrorMessages.AssertionOneTimeUseExceeded); throw new Saml20Exception(ErrorMessages.AssertionOneTimeUseExceeded); } context.Cache.Insert(assertion.Id, string.Empty, null, assertion.NotOnOrAfter, Cache.NoSlidingExpiration); } Logger.DebugFormat(TraceMessages.AssertionParsed, assertion.Id); DoSignOn(context, assertion, config); }
public static Saml2IdentityConfiguration GetIdentityConfiguration(Saml2Configuration config) { var configuration = new Saml2IdentityConfiguration(); #if NETFULL configuration.SaveBootstrapContext = config.SaveBootstrapContext; configuration.AudienceRestriction = GetAudienceRestriction(config.AudienceRestricted, config.AllowedAudienceUris); configuration.IssuerNameRegistry = new Saml2ResponseIssuerNameRegistry(); configuration.CertificateValidationMode = config.CertificateValidationMode; configuration.RevocationMode = config.RevocationMode; SetCustomCertificateValidator(configuration, config); if (config.CustomIssuerTokenResolver != null) { configuration.IssuerTokenResolver = config.CustomIssuerTokenResolver; } configuration.DetectReplayedTokens = config.DetectReplayedTokens; if (config.TokenReplayCache != null) { configuration.Caches = config.TokenReplayCache; } if (config.TokenReplayCacheExpirationPeriod.HasValue) { configuration.TokenReplayCacheExpirationPeriod = config.TokenReplayCacheExpirationPeriod.Value; } configuration.Initialize(); #else configuration.SaveSigninToken = config.SaveBootstrapContext; configuration.ValidateAudience = config.AudienceRestricted; configuration.ValidAudiences = config.AllowedAudienceUris.Select(a => a); configuration.ValidIssuer = config.AllowedIssuer; configuration.ValidateTokenReplay = config.DetectReplayedTokens; if (config.TokenReplayCache != null) { configuration.TokenReplayCache = config.TokenReplayCache; } configuration.NameClaimType = ClaimTypes.NameIdentifier; configuration.CertificateValidator = new Saml2CertificateValidator { CertificateValidationMode = config.CertificateValidationMode, RevocationMode = config.RevocationMode, }; SetCustomCertificateValidator(configuration, config); #endif return(configuration); }
internal static IdentityConfiguration GetIdentityConfiguration(Saml2Configuration config) { var identityConfiguration = new IdentityConfiguration { SaveBootstrapContext = config.SaveBootstrapContext, AudienceRestriction = GetAudienceRestriction(config.AudienceRestricted, config.AllowedAudienceUris), IssuerNameRegistry = new Saml2ResponseIssuerNameRegistry(), CertificateValidationMode = config.CertificateValidationMode, RevocationMode = config.RevocationMode, }; identityConfiguration.Initialize(); return(identityConfiguration); }
public Task Invoke(HttpContext context, Saml2Configuration config) { var metadata = new SAMLMetadataResult(config); context.Response.StatusCode = 200; context.Response.ContentType = metadata.ContentType; #if !DEBUG context.Response.Headers.Add("Content-Disposition", "attachment; filename=\"metadata.xml\""); #endif context.Response.WriteAsync(metadata.Content, encoding: System.Text.Encoding.UTF8); return(Task.CompletedTask); }
/// <summary> /// Handles a request. /// </summary> /// <param name="context">The context.</param> public void Handle(HttpContext context, Saml2Configuration config) { Logger.Debug(TraceMessages.LogoutHandlerCalled); // Some IDP's are known to fail to set an actual value in the SOAPAction header // so we just check for the existence of the header field. if (Array.Exists(context.Request.Headers.AllKeys, s => s == SoapConstants.SoapAction)) { HandleSoap(context, context.Request.InputStream, config); return; } if (!string.IsNullOrEmpty(context.Request.Params["SAMLart"])) { HandleArtifact(context, ConfigurationFactory.Instance.Configuration, HandleSoap); return; } if (!string.IsNullOrEmpty(context.Request.Params["SAMLResponse"])) { HandleResponse(context, config); } else if (!string.IsNullOrEmpty(context.Request.Params["SAMLRequest"])) { HandleRequest(context); } else { IdentityProvider idpEndpoint = null; // context.Session[IDPLoginSessionKey] may be null if IIS has been restarted if (context.Session[IdpSessionIdKey] != null) { idpEndpoint = IdpSelectionUtil.RetrieveIDPConfiguration((string)context.Session[IdpLoginSessionKey], config); } if (idpEndpoint == null) { // TODO: Reconsider how to accomplish this. context.User = null; FormsAuthentication.SignOut(); Logger.ErrorFormat(ErrorMessages.UnknownIdentityProvider, string.Empty); throw new Saml20Exception(string.Format(ErrorMessages.UnknownIdentityProvider, string.Empty)); } TransferClient(idpEndpoint, context, config); } }
/// <summary> /// Handle the authentication response from the IDP. /// </summary> /// <param name="context">The context.</param> public static Saml20Assertion HandleResponse(Saml2Configuration config, string samlResponse, IDictionary<string, object> session, Func<string, object> getFromCache, Action<string, object, DateTime> setInCache) { var defaultEncoding = Encoding.UTF8; var doc = Utility.GetDecodedSamlResponse(samlResponse, defaultEncoding); logger.DebugFormat(TraceMessages.SamlResponseReceived, doc.OuterXml); // Determine whether the assertion should be decrypted before being validated. bool isEncrypted; var assertion = Utility.GetAssertion(doc.DocumentElement, out isEncrypted); if (isEncrypted) { assertion = Utility.GetDecryptedAssertion(assertion, config).Assertion.DocumentElement; } // Check if an encoding-override exists for the IdP endpoint in question var issuer = Utility.GetIssuer(assertion); var endpoint = IdpSelectionUtil.RetrieveIDPConfiguration(issuer, config); if (!endpoint.AllowReplayAttacks) { Utility.CheckReplayAttack(doc.DocumentElement, !endpoint.AllowIdPInitiatedSso, session); } var status = Utility.GetStatusElement(doc.DocumentElement); if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success) { if (status.StatusCode.Value == Saml20Constants.StatusCodes.NoPassive) { logger.Error(ErrorMessages.ResponseStatusIsNoPassive); throw new Saml20Exception(ErrorMessages.ResponseStatusIsNoPassive); } logger.ErrorFormat(ErrorMessages.ResponseStatusNotSuccessful, status); throw new Saml20Exception(string.Format(ErrorMessages.ResponseStatusNotSuccessful, status)); } if (!string.IsNullOrEmpty(endpoint.ResponseEncoding)) { Encoding encodingOverride; try { encodingOverride = Encoding.GetEncoding(endpoint.ResponseEncoding); } catch (ArgumentException ex) { logger.ErrorFormat(ErrorMessages.UnknownEncoding, endpoint.ResponseEncoding); throw new ArgumentException(string.Format(ErrorMessages.UnknownEncoding, endpoint.ResponseEncoding), ex); } if (encodingOverride.CodePage != defaultEncoding.CodePage) { var doc1 = GetDecodedSamlResponse(samlResponse, encodingOverride); assertion = GetAssertion(doc1.DocumentElement, out isEncrypted); } } return HandleAssertion(assertion, config, getFromCache, setInCache); }
//[ExpectedException(typeof(Saml20Exception), ExpectedMessage = "Assertion is no longer valid.")] public void CanDecryptFOBSAssertion() { // Arrange var doc = AssertionUtil.LoadBase64EncodedXmlDocument(@"Assertions\fobs-assertion2"); var encryptedList = doc.GetElementsByTagName(EncryptedAssertion.ElementName, Saml20Constants.Assertion); // Do some mock configuration. var idpSource = new IdentityProviders(); var config = new Saml2Configuration { AllowedAudienceUris = new System.Collections.Generic.List <Uri>(), IdentityProvidersSource = idpSource }; config.AllowedAudienceUris.Add(new Uri("https://saml.safewhere.net")); idpSource.AddByMetadataDirectory(@"Protocol\MetadataDocs\FOBS"); // Set it manually. var cert = new X509Certificate2(@"Certificates\SafewhereTest_SFS.pfx", "test1234"); var encryptedAssertion = new Saml20EncryptedAssertion((RSA)cert.PrivateKey); encryptedAssertion.LoadXml((XmlElement)encryptedList[0]); // Act encryptedAssertion.Decrypt(); // Retrieve metadata var assertion = new Saml20Assertion(encryptedAssertion.Assertion.DocumentElement, null, false, TestConfiguration.Configuration); var endp = config.IdentityProvidersSource.GetById(assertion.Issuer); // Assert Assert.That(encryptedList.Count == 1); Assert.IsNotNull(endp, "Endpoint not found"); Assert.IsNotNull(endp.Metadata, "Metadata not found"); try { assertion.CheckValid(AssertionUtil.GetTrustedSigners(assertion.Issuer)); Assert.Fail("Verification should fail. Token does not include its signing key."); } catch (InvalidOperationException) { } Assert.IsNull(assertion.SigningKey, "Signing key is already present on assertion. Modify test."); //Assert.IsTrue("We have tested this next test" == ""); //Assert.That(assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endp.Metadata.GetKeys(KeyTypes.Signing), endp))); //Assert.IsNotNull(assertion.SigningKey, "Signing key was not set on assertion instance."); }
private Saml2Configuration GetLoginSaml2Config(RelyingParty relyingParty) { var loginSaml2Config = new Saml2Configuration { Issuer = saml2Config.Issuer, SigningCertificate = saml2Config.SigningCertificate, SignatureAlgorithm = saml2Config.SignatureAlgorithm, CertificateValidationMode = saml2Config.CertificateValidationMode, RevocationMode = saml2Config.RevocationMode }; loginSaml2Config.AllowedAudienceUris.AddRange(saml2Config.AllowedAudienceUris); loginSaml2Config.EncryptionCertificate = relyingParty.EncryptionCertificate; return(loginSaml2Config); }
private Saml2Configuration GetSamlConfiguration() { var myconfig = new Saml2Configuration { ServiceProvider = new ServiceProvider { SigningCertificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(FileEmbeddedResource("SelfHostOwinSPExample.sts_dev_certificate.pfx"), "test1234"), Server = "https://localhost:44333/core", Id = "https://localhost:44333/core" }, }; myconfig.ServiceProvider.Endpoints.Add(new ServiceProviderEndpoint { Type = EndpointType.SignOn, LocalPath = "/core/login", RedirectUrl = "/core" }); myconfig.ServiceProvider.Endpoints.Add(new ServiceProviderEndpoint { Type = EndpointType.Logout, LocalPath = "/core/logout", RedirectUrl = "/core" }); myconfig.ServiceProvider.Endpoints.Add(new ServiceProviderEndpoint { Type = EndpointType.Metadata, LocalPath = "/core/metadata" }); myconfig.IdentityProviders.MetadataLocation = "..\\..\\Metadata"; var shib = myconfig.IdentityProviders.FirstOrDefault(p => p.Id == "https://idp.testshib.org/idp/shibboleth"); if (shib != null) { //shib.Metadata.SSOEndpoints shib.Endpoints.Add(new IdentityProviderEndpoint { Binding = BindingType.Redirect, Type = EndpointType.SignOn, Url = "https://idp.testshib.org/idp/profile/Shibboleth/SSO" }); } //myconfig.IdentityProviders.Add(new IdentityProvider //{ // Id = "https://idp.testshib.org/idp/shibboleth", // Name = "Test shib" //}); SAML2.Logging.LoggerProvider.Configuration = myconfig; return(myconfig); }
private Task <IActionResult> AuthnResponseAsync(string partyId, Saml2Configuration samlConfig, string inResponseTo, string relayState, string acsUrl, SamlBindingType binding, Saml2StatusCodes status) { logger.ScopeTrace($"Authn response{(status != Saml2StatusCodes.Success ? " error" : string.Empty)}, Status code '{status}'."); logger.SetScopeProperty("downPartyId", partyId); logger.ScopeTrace($"Binding '{binding}'"); switch (binding) { case SamlBindingType.Redirect: return(AuthnResponseAsync(samlConfig, inResponseTo, relayState, acsUrl, new Saml2RedirectBinding(), status)); case SamlBindingType.Post: return(AuthnResponseAsync(samlConfig, inResponseTo, relayState, acsUrl, new Saml2PostBinding(), status)); default: throw new NotSupportedException($"SAML binding '{binding}' not supported."); } }
/// <summary> /// Initializes a new instance of the <see cref="HttpArtifactBindingBuilder"/> class. /// </summary> /// <param name="context">The current http context.</param> /// <param name="redirect">Action to perform when redirecting. Parameter will be destination URL</param> /// <param name="sendResponseMessage">Action to send messages to response stream</param> public HttpArtifactBindingBuilder(Saml2Configuration config, Action <string> redirect, Action <string> sendResponseMessage) { if (config == null) { throw new ArgumentNullException(nameof(config)); } if (redirect == null) { throw new ArgumentNullException(nameof(redirect)); } if (sendResponseMessage == null) { throw new ArgumentNullException(nameof(sendResponseMessage)); } this.redirect = redirect; this.config = config; this.sendResponseMessage = sendResponseMessage; }
public SamlService( IHttpRedirectBinding httpRedirectBinding, IHttpArtifactBinding httpArtifactBinding, ISaml2MessageFactory saml2MessageFactory, ICertificateProvider certificateProvider, ISamlProvider samlProvider, ISaml2Validator saml2Validator, Saml2Configuration saml2Configuration) { _httpRedirectBinding = httpRedirectBinding; _httpArtifactBinding = httpArtifactBinding; _saml2MessageFactory = saml2MessageFactory; _certificateProvider = certificateProvider; _samlProvider = samlProvider; _saml2Validator = saml2Validator; _saml2Configuration = saml2Configuration; _identityProviderConfiguration = saml2Configuration.IdentityProviderConfiguration; _serviceProviderConfiguration = saml2Configuration.ServiceProviderConfiguration; }
private Task <IActionResult> AuthnResponseAsync(SamlDownParty party, Saml2Configuration samlConfig, string inResponseTo, string relayState, string acsUrl, Saml2StatusCodes status, IEnumerable <Claim> claims = null) { logger.ScopeTrace(() => $"Down, SAML Authn response{(status != Saml2StatusCodes.Success ? " error" : string.Empty)}, Status code '{status}'."); var binding = party.AuthnBinding.ResponseBinding; logger.ScopeTrace(() => $"Binding '{binding}'"); switch (binding) { case SamlBindingTypes.Redirect: return(AuthnResponseAsync(party, samlConfig, inResponseTo, relayState, acsUrl, new Saml2RedirectBinding(), status, claims)); case SamlBindingTypes.Post: return(AuthnResponseAsync(party, samlConfig, inResponseTo, relayState, acsUrl, new Saml2PostBinding(), status, claims)); default: throw new NotSupportedException($"SAML binding '{binding}' not supported."); } }
private Task <IActionResult> LogoutResponseAsync(SamlDownParty party, Saml2Configuration samlConfig, string inResponseTo, string relayState, Saml2StatusCodes status, string sessionIndex = null) { logger.ScopeTrace($"Down, SAML Logout response{(status != Saml2StatusCodes.Success ? " error" : string.Empty)}, Status code '{status}'."); var binding = party.LogoutBinding.ResponseBinding; logger.ScopeTrace($"Binding '{binding}'"); switch (binding) { case SamlBindingTypes.Redirect: return(LogoutResponseAsync(samlConfig, inResponseTo, relayState, party.LoggedOutUrl, new Saml2RedirectBinding(), status, sessionIndex)); case SamlBindingTypes.Post: return(LogoutResponseAsync(samlConfig, inResponseTo, relayState, party.LoggedOutUrl, new Saml2PostBinding(), status, sessionIndex)); default: throw new NotSupportedException($"SAML binding '{binding}' not supported."); } }
/// <summary> /// Validates the SAML20Federation configuration. /// </summary> /// <returns>True if validation passes, false otherwise</returns> public static bool ValidateConfiguration(Saml2Configuration config) { if (config == null) { throw new ArgumentNullException("config", ErrorMessages.ConfigMissingSaml2Element); } if (config.ServiceProvider == null) { throw new ArgumentOutOfRangeException("config", ErrorMessages.ConfigMissingServiceProviderElement); } if (string.IsNullOrEmpty(config.ServiceProvider.Id)) { throw new ArgumentOutOfRangeException("config", ErrorMessages.ConfigMissingServiceProviderIdAttribute); } if (config.ServiceProvider.SigningCertificate == null) { throw new ArgumentOutOfRangeException("config", ErrorMessages.ConfigMissingSigningCertificateElement); } // This will throw if no certificate or multiple certificates are found var certificate = config.ServiceProvider.SigningCertificate; if (!certificate.HasPrivateKey) { throw new ArgumentOutOfRangeException("config", ErrorMessages.ConfigSigningCertificateMissingPrivateKey); } if (config.IdentityProviders == null) { throw new ArgumentOutOfRangeException("config", ErrorMessages.ConfigMissingIdentityProvidersElement); } if (config.IdentityProviders.MetadataLocation == null) { throw new ArgumentOutOfRangeException("config", ErrorMessages.ConfigMissingMetadataLocation); } return(true); }
public ActionResult InitiateLogin(User user) { var serviceProviderRealm = ConfigurationManager.AppSettings["serviceProviderRealm"]; var binding = new Saml2PostBinding(); binding.RelayState = $"RPID={Uri.EscapeDataString(serviceProviderRealm)}"; var config = new Saml2Configuration(); config.Issuer = new Uri(ConfigurationManager.AppSettings["issuer"]); config.SingleSignOnDestination = new Uri(ConfigurationManager.AppSettings["SingleSignOnDestination"]); //config.SigningCertificate = CertificateUtil.Load(HttpContext.Server.MapPath("~/App_Data/LnT.sso.saml2.testwebapp_Certificate.pfx")); //config.SignatureAlgorithm = SecurityAlgorithms.RsaSha256Signature; var entityDescriptor = new EntityDescriptor(); string metadataPath = System.Web.HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["metadataPath"]); entityDescriptor.ReadIdPSsoDescriptorFromFile(metadataPath); if (entityDescriptor.IdPSsoDescriptor != null) { config.SignatureValidationCertificates.AddRange(entityDescriptor.IdPSsoDescriptor.SigningCertificates); } var appliesToAddress = new Uri(ConfigurationManager.AppSettings["appliesToAddress"]); var response = new Saml2AuthnResponse(config); response.Status = Saml2StatusCodes.Success; var claimsIdentity = new ClaimsIdentity(CreateClaims()); response.NameId = new Saml2NameIdentifier(claimsIdentity.Claims.Where(c => c.Type == ClaimTypes.NameIdentifier).Select(c => c.Value).Single(), NameIdentifierFormats.Persistent); response.ClaimsIdentity = claimsIdentity; var token = response.CreateSecurityToken(appliesToAddress); return(binding.Bind(response).ToActionResult()); }