/// <summary> /// Handles all artifact creations and redirects. /// </summary> /// <param name="destination">The destination.</param> /// <param name="localEndpointIndex">Index of the local endpoint.</param> /// <param name="signedSamlMessage">The signed saml message.</param> /// <param name="relayState">The query string relay state value to add to the communication</param> private void ArtifactRedirect(IDPEndPointElement destination, Int16 localEndpointIndex, XmlDocument signedSamlMessage, string relayState) { SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); string sourceId = config.ServiceProvider.ID; byte[] sourceIdHash = ArtifactUtil.GenerateSourceIdHash(sourceId); byte[] messageHandle = ArtifactUtil.GenerateMessageHandle(); string artifact = ArtifactUtil.CreateArtifact(HttpArtifactBindingConstants.ArtifactTypeCode, localEndpointIndex, sourceIdHash, messageHandle); _context.Cache.Insert(artifact, signedSamlMessage, null, DateTime.Now.AddMinutes(1), SamlCache.NoSlidingExpiration); string destinationUrl = destination.Url + "?" + HttpArtifactBindingConstants.ArtifactQueryStringName + "=" + HttpUtility.UrlEncode(artifact); if (!string.IsNullOrEmpty(relayState)) { destinationUrl += "&relayState=" + relayState; } if (Trace.ShouldTrace(TraceEventType.Information)) { Trace.TraceData(TraceEventType.Information, string.Format(Tracing.CreatedArtifact, artifact, signedSamlMessage.OuterXml)); } _context.Response.Redirect(destinationUrl); }
public void CanParseCreatedArtifact() { // Arrange var sourceIdUrl = "https://kleopatra.safewhere.local/Saml2ExtWeb/artifact.ashx"; var sourceIdHash = ArtifactUtil.GenerateSourceIdHash(sourceIdUrl); var messageHandle = ArtifactUtil.GenerateMessageHandle(); short typeCode = 4; short endpointIndex = 1; // Act var artifact = ArtifactUtil.CreateArtifact(typeCode, endpointIndex, sourceIdHash, messageHandle); short parsedTypeCode = -1; short parsedEndpointIndex = -1; var parsedSourceIdHash = new byte[20]; var parsedMessageHandle = new byte[20]; var result = ArtifactUtil.TryParseArtifact(artifact, ref parsedTypeCode, ref parsedEndpointIndex, ref parsedSourceIdHash, ref parsedMessageHandle); // Assert Assert.True(result, "Unable to parse artifact"); Assert.True(typeCode == parsedTypeCode, "Original and parsed typeCode did not match"); Assert.True(endpointIndex == parsedEndpointIndex, "Original and parsed endpointIndex did not match"); Assert.Equal(sourceIdHash, parsedSourceIdHash); //Assert.Fail("Original and parsed sourceIdHash are not identical"); Assert.Equal(messageHandle, parsedMessageHandle); //Assert.Fail("Original and parsed messageHandle are not identical"); }
public void ArtifactCreateParse() { string sourceIdUrl = "https://kleopatra.safewhere.local/Saml2ExtWeb/artifact.ashx"; byte[] sourceIdHash = ArtifactUtil.GenerateSourceIdHash(sourceIdUrl); Assert.That(sourceIdHash.Length == 20, "Unexpected hash length"); byte[] messageHandle = ArtifactUtil.GenerateMessageHandle(); Assert.That(messageHandle.Length == 20, "Unexpected hash length"); Int16 typeCode = 4; Int16 endpointIndex = 1; string artifact = ArtifactUtil.CreateArtifact(typeCode, endpointIndex, sourceIdHash, messageHandle); Int16 parsedTypeCode = -1; Int16 parsedEndpointIndex = -1; byte[] parsedSourceIdHash = new byte[20]; byte[] parsedMessageHandle = new byte[20]; Assert.That( ArtifactUtil.TryParseArtifact(artifact, ref parsedTypeCode, ref parsedEndpointIndex, ref parsedSourceIdHash, ref parsedMessageHandle), "Unable to parse artifact"); Assert.That(typeCode == parsedTypeCode, "Original and parsed typeCode did not match"); Assert.That(endpointIndex == parsedEndpointIndex, "Original and parsed endpointIndex did not match"); for (int i = 0; i < 20; i++) { if (sourceIdHash[i] != parsedSourceIdHash[i]) { Assert.Fail("Original and parsed sourceIdHash are not identical"); } } for (int i = 0; i < 20; i++) { if (messageHandle[i] != parsedMessageHandle[i]) { Assert.Fail("Original and parsed messageHandle are not identical"); } } }
/// <summary> /// Determines which IdP an artifact has been sent from. /// </summary> /// <param name="artifact">The artifact.</param> /// <returns>An IdP configuration element</returns> private IdentityProvider DetermineIdp(string artifact) { short typeCodeValue = -1; short endPointIndex = -1; var sourceIdHash = new byte[20]; var messageHandle = new byte[20]; if (ArtifactUtil.TryParseArtifact(artifact, ref typeCodeValue, ref endPointIndex, ref sourceIdHash, ref messageHandle)) { foreach (IdentityProvider ep in config.IdentityProviders) { var hash = ArtifactUtil.GenerateSourceIdHash(ep.Id); if (ByteArraysAreEqual(sourceIdHash, hash)) { return(ep); } } } return(null); }
/// <summary> /// Determines which IdP an artifact has been sent from. /// </summary> /// <param name="artifact">The artifact.</param> /// <returns>An IdP configuration element</returns> private IDPEndPoint DetermineIdp(string artifact) { SAML20FederationConfig config = SAML20FederationConfig.GetConfig(); short typeCodeValue = -1; short endPointIndex = -1; byte[] sourceIdHash = new byte[20]; byte[] messageHandle = new byte[20]; if (ArtifactUtil.TryParseArtifact(artifact, ref typeCodeValue, ref endPointIndex, ref sourceIdHash, ref messageHandle)) { foreach(IDPEndPoint ep in config.IDPEndPoints) { byte[] hash = ArtifactUtil.GenerateSourceIdHash(ep.Id); if (AreEqual(sourceIdHash, hash)) return ep; } } return null; }
/// <summary> /// Handles all artifact creations and redirects. /// </summary> /// <param name="destination">The destination.</param> /// <param name="localEndpointIndex">Index of the local endpoint.</param> /// <param name="signedSamlMessage">The signed SAML message.</param> /// <param name="relayState">The query string relay state value to add to the communication</param> private void ArtifactRedirect(IdentityProviderEndpoint destination, short localEndpointIndex, XmlDocument signedSamlMessage, string relayState) { Logger.DebugFormat(TraceMessages.ArtifactRedirectReceived, signedSamlMessage.OuterXml); var sourceId = config.ServiceProvider.Id; var sourceIdHash = ArtifactUtil.GenerateSourceIdHash(sourceId); var messageHandle = ArtifactUtil.GenerateMessageHandle(); var artifact = ArtifactUtil.CreateArtifact(HttpArtifactBindingConstants.ArtifactTypeCode, localEndpointIndex, sourceIdHash, messageHandle); Context.Cache.Insert(artifact, signedSamlMessage, null, DateTime.Now.AddMinutes(1), Cache.NoSlidingExpiration); var destinationUrl = destination.Url + "?" + HttpArtifactBindingConstants.ArtifactQueryStringName + "=" + HttpUtility.UrlEncode(artifact); if (!string.IsNullOrEmpty(relayState)) { destinationUrl += "&relayState=" + relayState; } Logger.DebugFormat(TraceMessages.ArtifactCreated, artifact); Context.Response.Redirect(destinationUrl); }
/// <summary> /// Handles all artifact creations and redirects. /// </summary> /// <param name="destination">The destination.</param> /// <param name="localEndpointIndex">Index of the local endpoint.</param> /// <param name="signedSamlMessage">The signed SAML message.</param> /// <param name="relayState">The query string relay state value to add to the communication</param> private void ArtifactRedirect(IdentityProviderEndpoint destination, short localEndpointIndex, XmlDocument signedSamlMessage, string relayState, Action <string, object> cacheInsert) { _logger.LogDebug(TraceMessages.ArtifactRedirectReceived, signedSamlMessage.OuterXml); var sourceId = config.ServiceProvider.Id; var sourceIdHash = ArtifactUtil.GenerateSourceIdHash(sourceId); var messageHandle = ArtifactUtil.GenerateMessageHandle(); var artifact = ArtifactUtil.CreateArtifact(HttpArtifactBindingConstants.ArtifactTypeCode, localEndpointIndex, sourceIdHash, messageHandle); cacheInsert(artifact, signedSamlMessage); var destinationUrl = destination.Url + "?" + HttpArtifactBindingConstants.ArtifactQueryStringName + "=" + Uri.EscapeDataString(artifact); if (!string.IsNullOrEmpty(relayState)) { destinationUrl += "&relayState=" + relayState; } _logger.LogDebug(TraceMessages.ArtifactCreated, artifact); redirect(destinationUrl); }