forked from Sustainsys/Saml2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add web client with support for client cert
- Loading branch information
1 parent
7000a47
commit 4bcdcb4
Showing
5 changed files
with
146 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Net; | ||
using System.Security.Cryptography.X509Certificates; | ||
using System.Text; | ||
|
||
namespace Sustainsys.Saml2.Internal | ||
{ | ||
/// <summary> | ||
/// A WebClient implementation that will add a list of client | ||
/// certificates to the requests it makes. | ||
/// </summary> | ||
internal class ClientCertificateWebClient : WebClient | ||
{ | ||
private readonly IEnumerable<X509Certificate2> certificates; | ||
/// <summary> | ||
/// Register the certificate to be used for this requets. | ||
/// </summary> | ||
/// <param name="certificates">Certificates to offer to server</param> | ||
public ClientCertificateWebClient(IEnumerable<X509Certificate2> certificates) | ||
{ | ||
this.certificates = certificates; | ||
} | ||
/// <summary> | ||
/// Override the base class to add the certificate | ||
/// to the reuqest before returning it. | ||
/// </summary> | ||
/// <param name="address"></param> | ||
/// <returns></returns> | ||
protected override WebRequest GetWebRequest(Uri address) | ||
{ | ||
var request = (HttpWebRequest)base.GetWebRequest(address); | ||
if (certificates != null) | ||
{ | ||
foreach(var c in certificates) | ||
{ | ||
request.ClientCertificates.Add(c); | ||
} | ||
} | ||
return request; | ||
} | ||
} | ||
} |
86 changes: 86 additions & 0 deletions
86
Tests/Tests.Shared/Internal/ClientCertificateWebclientTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Security.Cryptography.X509Certificates; | ||
using FluentAssertions; | ||
using Sustainsys.Saml2.Configuration; | ||
using Sustainsys.Saml2.Internal; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using System.Collections.Generic; | ||
|
||
namespace Sustainsys.Saml2.Tests.Internal | ||
{ | ||
namespace Sustainsys.Saml2.Tests.Internal | ||
{ | ||
[TestClass] | ||
public class ClientCertificateWebClientTests | ||
{ | ||
[TestMethod] | ||
public void Create_WithoutCertificate_ShouldAddNothingToRequest() | ||
{ | ||
var client = new TestableClientCertificateWebClient(null); | ||
var payload = "Doesn't matter"; | ||
var destination = new Uri("https://localhost/Endpoint"); | ||
try | ||
{ | ||
client.UploadString(destination, payload); | ||
} | ||
catch (Exception) | ||
{ | ||
//Destination is not listening, but we should get an exception that shows it | ||
// at least tried to connect there. | ||
} | ||
client.HasCertificatesInRequest.Should().BeFalse(); | ||
} | ||
|
||
[TestMethod] | ||
public void Create_WithCertificate_ShouldAddCertificateToRequest() | ||
{ | ||
var config = SustainsysSaml2Section.Current; | ||
var options = new SPOptions(config); | ||
|
||
var client = new TestableClientCertificateWebClient( | ||
options.ServiceCertificates | ||
.Where(sc => sc.Use.HasFlag(CertificateUse.TlsClient)) | ||
.Select(sc => sc.Certificate)); | ||
|
||
var payload = "Doesn't matter"; | ||
var destination = new Uri("https://localhost/Endpoint"); | ||
try | ||
{ | ||
client.UploadString(destination, payload); | ||
} | ||
catch (Exception) | ||
{ | ||
//Destination is not listening, but we should get an exception that shows it | ||
// at least tried to connect there. | ||
} | ||
client.HasCertificatesInRequest.Should().BeTrue(); | ||
} | ||
|
||
private class TestableClientCertificateWebClient : ClientCertificateWebClient | ||
{ | ||
public bool HasCertificatesInRequest; | ||
private readonly IList<X509Certificate2> expectedCertificates; | ||
public TestableClientCertificateWebClient(IEnumerable<X509Certificate2> certificates) | ||
: base(certificates) | ||
{ | ||
expectedCertificates = certificates?.ToList(); // Copy to not rely on shared ref that can be altered. | ||
} | ||
protected override WebRequest GetWebRequest(Uri address) | ||
{ | ||
var request = base.GetWebRequest(address); | ||
var httpWebRequest = (HttpWebRequest)request; | ||
if (httpWebRequest != null) | ||
{ | ||
HasCertificatesInRequest = | ||
expectedCertificates != null | ||
&& expectedCertificates.Count == httpWebRequest.ClientCertificates.Count | ||
&& expectedCertificates.All(ec => httpWebRequest.ClientCertificates.Contains(ec)); | ||
} | ||
return request; | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters