summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs')
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs267
1 files changed, 163 insertions, 104 deletions
diff --git a/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs b/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs
index acb37fc..6fb0d7a 100644
--- a/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs
@@ -6,6 +6,9 @@
namespace DotNetOpenAuth.Test.OpenId {
using System;
+ using System.Net.Http;
+ using System.Threading.Tasks;
+
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.OpenId;
@@ -24,76 +27,98 @@ namespace DotNetOpenAuth.Test.OpenId {
}
[Test]
- public void SharedAssociationPositive() {
- this.ParameterizedAuthenticationTest(true, true, false);
+ public async Task SharedAssociationPositive() {
+ await this.ParameterizedAuthenticationTestAsync(true, true, false);
}
/// <summary>
/// Verifies that a shared association protects against tampering.
/// </summary>
[Test]
- public void SharedAssociationTampered() {
- this.ParameterizedAuthenticationTest(true, true, true);
+ public async Task SharedAssociationTampered() {
+ await this.ParameterizedAuthenticationTestAsync(true, true, true);
}
[Test]
- public void SharedAssociationNegative() {
- this.ParameterizedAuthenticationTest(true, false, false);
+ public async Task SharedAssociationNegative() {
+ await this.ParameterizedAuthenticationTestAsync(true, false, false);
}
[Test]
- public void PrivateAssociationPositive() {
- this.ParameterizedAuthenticationTest(false, true, false);
+ public async Task PrivateAssociationPositive() {
+ await this.ParameterizedAuthenticationTestAsync(false, true, false);
}
/// <summary>
/// Verifies that a private association protects against tampering.
/// </summary>
[Test]
- public void PrivateAssociationTampered() {
- this.ParameterizedAuthenticationTest(false, true, true);
+ public async Task PrivateAssociationTampered() {
+ await this.ParameterizedAuthenticationTestAsync(false, true, true);
}
[Test]
- public void NoAssociationNegative() {
- this.ParameterizedAuthenticationTest(false, false, false);
+ public async Task NoAssociationNegative() {
+ await this.ParameterizedAuthenticationTestAsync(false, false, false);
}
[Test]
- public void UnsolicitedAssertion() {
- this.MockResponder.RegisterMockRPDiscovery();
- OpenIdCoordinator coordinator = new OpenIdCoordinator(
- rp => {
- rp.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
- IAuthenticationResponse response = rp.GetResponse();
- Assert.AreEqual(AuthenticationStatus.Authenticated, response.Status);
- },
- op => {
- op.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
+ public async Task UnsolicitedAssertion() {
+ var opStore = new StandardProviderApplicationStore();
+ var coordinator = new CoordinatorBase(
+ async (hostFactories, ct) => {
+ var op = new OpenIdProvider(opStore);
Identifier id = GetMockIdentifier(ProtocolVersion.V20);
- op.SendUnsolicitedAssertion(OPUri, RPRealmUri, id, OPLocalIdentifiers[0]);
- AutoProvider(op); // handle check_auth
- });
- coordinator.Run();
+ var assertion = await op.PrepareUnsolicitedAssertionAsync(OPUri, RPRealmUri, id, OPLocalIdentifiers[0], ct);
+
+ using (var httpClient = hostFactories.CreateHttpClient()) {
+ using (var response = await httpClient.GetAsync(assertion.Headers.Location)) {
+ response.EnsureSuccessStatusCode();
+ }
+ }
+ },
+ CoordinatorBase.Handle(RPRealmUri).By(async (hostFactories, req, ct) => {
+ var rp = new OpenIdRelyingParty(new StandardRelyingPartyApplicationStore(), hostFactories);
+ IAuthenticationResponse response = await rp.GetResponseAsync();
+ Assert.AreEqual(AuthenticationStatus.Authenticated, response.Status);
+ return new HttpResponseMessage();
+ }),
+ CoordinatorBase.Handle(OPUri).By(
+ async (req, ct) => {
+ var op = new OpenIdProvider(opStore);
+ return await this.AutoProviderActionAsync(op, req, ct);
+ }),
+ MockHttpRequest.RegisterMockRPDiscovery(ssl: false));
+ await coordinator.RunAsync();
}
[Test]
- public void UnsolicitedAssertionRejected() {
- this.MockResponder.RegisterMockRPDiscovery();
- OpenIdCoordinator coordinator = new OpenIdCoordinator(
- rp => {
- rp.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
+ public async Task UnsolicitedAssertionRejected() {
+ var opStore = new StandardProviderApplicationStore();
+ var coordinator = new CoordinatorBase(
+ async (hostFactories, ct) => {
+ var op = new OpenIdProvider(opStore);
+ Identifier id = GetMockIdentifier(ProtocolVersion.V20);
+ var assertion = await op.PrepareUnsolicitedAssertionAsync(OPUri, RPRealmUri, id, OPLocalIdentifiers[0], ct);
+ using (var httpClient = hostFactories.CreateHttpClient()) {
+ using (var response = await httpClient.GetAsync(assertion.Headers.Location, ct)) {
+ response.EnsureSuccessStatusCode();
+ }
+ }
+ },
+ CoordinatorBase.Handle(RPRealmUri).By(async (hostFactories, req, ct) => {
+ var rp = new OpenIdRelyingParty(new StandardRelyingPartyApplicationStore(), hostFactories);
rp.SecuritySettings.RejectUnsolicitedAssertions = true;
- IAuthenticationResponse response = rp.GetResponse();
+ IAuthenticationResponse response = await rp.GetResponseAsync(req, ct);
Assert.AreEqual(AuthenticationStatus.Failed, response.Status);
- },
- op => {
- op.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
- Identifier id = GetMockIdentifier(ProtocolVersion.V20);
- op.SendUnsolicitedAssertion(OPUri, RPRealmUri, id, OPLocalIdentifiers[0]);
- AutoProvider(op); // handle check_auth
- });
- coordinator.Run();
+ return new HttpResponseMessage();
+ }),
+ CoordinatorBase.Handle(OPUri).By(async (hostFactories, req, ct) => {
+ var op = new OpenIdProvider(opStore);
+ return await this.AutoProviderActionAsync(op, req, ct);
+ }),
+ MockHttpRequest.RegisterMockRPDiscovery(false));
+ await coordinator.RunAsync();
}
/// <summary>
@@ -101,25 +126,35 @@ namespace DotNetOpenAuth.Test.OpenId {
/// when the appropriate security setting is set.
/// </summary>
[Test]
- public void UnsolicitedDelegatingIdentifierRejection() {
- this.MockResponder.RegisterMockRPDiscovery();
- OpenIdCoordinator coordinator = new OpenIdCoordinator(
- rp => {
- rp.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
+ public async Task UnsolicitedDelegatingIdentifierRejection() {
+ var opStore = new StandardProviderApplicationStore();
+ var coordinator = new CoordinatorBase(
+ async (hostFactories, ct) => {
+ var op = new OpenIdProvider(opStore);
+ Identifier id = GetMockIdentifier(ProtocolVersion.V20, false, true);
+ var assertion = await op.PrepareUnsolicitedAssertionAsync(OPUri, RPRealmUri, id, OPLocalIdentifiers[0], ct);
+ using (var httpClient = hostFactories.CreateHttpClient()) {
+ using (var response = await httpClient.GetAsync(assertion.Headers.Location, ct)) {
+ response.EnsureSuccessStatusCode();
+ }
+ }
+ },
+ CoordinatorBase.Handle(RPRealmUri).By(async (hostFactories, req, ct) => {
+ var rp = new OpenIdRelyingParty(new StandardRelyingPartyApplicationStore(), hostFactories);
rp.SecuritySettings.RejectDelegatingIdentifiers = true;
- IAuthenticationResponse response = rp.GetResponse();
+ IAuthenticationResponse response = await rp.GetResponseAsync(req, ct);
Assert.AreEqual(AuthenticationStatus.Failed, response.Status);
- },
- op => {
- op.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
- Identifier id = GetMockIdentifier(ProtocolVersion.V20, false, true);
- op.SendUnsolicitedAssertion(OPUri, RPRealmUri, id, OPLocalIdentifiers[0]);
- AutoProvider(op); // handle check_auth
- });
- coordinator.Run();
+ return new HttpResponseMessage();
+ }),
+ CoordinatorBase.Handle(OPUri).By(async (hostFactories, req, ct) => {
+ var op = new OpenIdProvider(opStore);
+ return await this.AutoProviderActionAsync(op, req, ct);
+ }),
+ MockHttpRequest.RegisterMockRPDiscovery(false));
+ await coordinator.RunAsync();
}
- private void ParameterizedAuthenticationTest(bool sharedAssociation, bool positive, bool tamper) {
+ private async Task ParameterizedAuthenticationTestAsync(bool sharedAssociation, bool positive, bool tamper) {
foreach (Protocol protocol in Protocol.AllPracticalVersions) {
foreach (bool statelessRP in new[] { false, true }) {
if (sharedAssociation && statelessRP) {
@@ -129,21 +164,26 @@ namespace DotNetOpenAuth.Test.OpenId {
foreach (bool immediate in new[] { false, true }) {
TestLogger.InfoFormat("Beginning authentication test scenario. OpenID: {0}, Shared: {1}, positive: {2}, tamper: {3}, stateless: {4}, immediate: {5}", protocol.Version, sharedAssociation, positive, tamper, statelessRP, immediate);
- this.ParameterizedAuthenticationTest(protocol, statelessRP, sharedAssociation, positive, immediate, tamper);
+ await this.ParameterizedAuthenticationTestAsync(protocol, statelessRP, sharedAssociation, positive, immediate, tamper);
}
}
}
}
- private void ParameterizedAuthenticationTest(Protocol protocol, bool statelessRP, bool sharedAssociation, bool positive, bool immediate, bool tamper) {
+ private async Task ParameterizedAuthenticationTestAsync(Protocol protocol, bool statelessRP, bool sharedAssociation, bool positive, bool immediate, bool tamper) {
Requires.That(!statelessRP || !sharedAssociation, null, "The RP cannot be stateless while sharing an association with the OP.");
Requires.That(positive || !tamper, null, "Cannot tamper with a negative response.");
var securitySettings = new ProviderSecuritySettings();
var cryptoKeyStore = new MemoryCryptoKeyStore();
var associationStore = new ProviderAssociationHandleEncoder(cryptoKeyStore);
Association association = sharedAssociation ? HmacShaAssociationProvider.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart, associationStore, securitySettings) : null;
- var coordinator = new OpenIdCoordinator(
- rp => {
+ int opStep = 0;
+ var coordinator = new CoordinatorBase(
+ CoordinatorBase.RelyingPartyDriver(async (rp, ct) => {
+ if (statelessRP) {
+ rp = new OpenIdRelyingParty(null, rp.Channel.HostFactories);
+ }
+
var request = new CheckIdRequest(protocol.Version, OPUri, immediate ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup);
if (association != null) {
@@ -155,17 +195,25 @@ namespace DotNetOpenAuth.Test.OpenId {
request.LocalIdentifier = "http://localid";
request.ReturnTo = RPUri;
request.Realm = RPUri;
- rp.Channel.Respond(request);
+ var redirectRequest = await rp.Channel.PrepareResponseAsync(request, ct);
+ Uri redirectResponse;
+ using (var httpClient = rp.Channel.HostFactories.CreateHttpClient()) {
+ using (var response = await httpClient.GetAsync(redirectRequest.Headers.Location)) {
+ redirectResponse = response.Headers.Location;
+ }
+ }
+
+ var assertionMessage = new HttpRequestMessage(HttpMethod.Get, redirectResponse.AbsoluteUri);
if (positive) {
if (tamper) {
try {
- rp.Channel.ReadFromRequest<PositiveAssertionResponse>();
+ await rp.Channel.ReadFromRequestAsync<PositiveAssertionResponse>(assertionMessage, ct);
Assert.Fail("Expected exception {0} not thrown.", typeof(InvalidSignatureException).Name);
} catch (InvalidSignatureException) {
TestLogger.InfoFormat("Caught expected {0} exception after tampering with signed data.", typeof(InvalidSignatureException).Name);
}
} else {
- var response = rp.Channel.ReadFromRequest<PositiveAssertionResponse>();
+ var response = await rp.Channel.ReadFromRequestAsync<PositiveAssertionResponse>(assertionMessage, ct);
Assert.IsNotNull(response);
Assert.AreEqual(request.ClaimedIdentifier, response.ClaimedIdentifier);
Assert.AreEqual(request.LocalIdentifier, response.LocalIdentifier);
@@ -177,15 +225,16 @@ namespace DotNetOpenAuth.Test.OpenId {
// When the OP notices the replay we get a generic InvalidSignatureException.
// When the RP notices the replay we get a specific ReplayMessageException.
try {
- CoordinatingChannel channel = (CoordinatingChannel)rp.Channel;
- await channel.ReplayAsync(response);
+ // TODO: fix this.
+ ////CoordinatingChannel channel = (CoordinatingChannel)rp.Channel;
+ ////await channel.ReplayAsync(response);
Assert.Fail("Expected ProtocolException was not thrown.");
} catch (ProtocolException ex) {
Assert.IsTrue(ex is ReplayedMessageException || ex is InvalidSignatureException, "A {0} exception was thrown instead of the expected {1} or {2}.", ex.GetType(), typeof(ReplayedMessageException).Name, typeof(InvalidSignatureException).Name);
}
}
} else {
- var response = rp.Channel.ReadFromRequest<NegativeAssertionResponse>();
+ var response = await rp.Channel.ReadFromRequestAsync<NegativeAssertionResponse>(assertionMessage, ct);
Assert.IsNotNull(response);
if (immediate) {
// Only 1.1 was required to include user_setup_url
@@ -196,54 +245,64 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.IsNull(response.UserSetupUrl);
}
}
- },
- op => {
+ }),
+ CoordinatorBase.HandleProvider(async (op, req, ct) => {
if (association != null) {
var key = cryptoKeyStore.GetCurrentKey(ProviderAssociationHandleEncoder.AssociationHandleEncodingSecretBucket, TimeSpan.FromSeconds(1));
op.CryptoKeyStore.StoreKey(ProviderAssociationHandleEncoder.AssociationHandleEncodingSecretBucket, key.Key, key.Value);
}
- var request = op.Channel.ReadFromRequest<CheckIdRequest>();
- Assert.IsNotNull(request);
- IProtocolMessage response;
- if (positive) {
- response = new PositiveAssertionResponse(request);
- } else {
- response = new NegativeAssertionResponse(request, op.Channel);
- }
- op.Channel.Respond(response);
-
- if (positive && (statelessRP || !sharedAssociation)) {
- var checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>();
- var checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest);
- checkauthResponse.IsValid = checkauthRequest.IsValid;
- op.Channel.Respond(checkauthResponse);
-
- if (!tamper) {
- // Respond to the replay attack.
- checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>();
- checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest);
- checkauthResponse.IsValid = checkauthRequest.IsValid;
- op.Channel.Respond(checkauthResponse);
- }
+ switch (++opStep) {
+ case 1:
+ var request = await op.Channel.ReadFromRequestAsync<CheckIdRequest>(req, ct);
+ Assert.IsNotNull(request);
+ IProtocolMessage response;
+ if (positive) {
+ response = new PositiveAssertionResponse(request);
+ } else {
+ response = new NegativeAssertionResponse(request.Version, request.ReturnTo, request.Mode);
+ }
+
+ return await op.Channel.PrepareResponseAsync(response, ct);
+ case 2:
+ if (positive && (statelessRP || !sharedAssociation)) {
+ var checkauthRequest = await op.Channel.ReadFromRequestAsync<CheckAuthenticationRequest>(req, ct);
+ var checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest);
+ checkauthResponse.IsValid = checkauthRequest.IsValid;
+ return await op.Channel.PrepareResponseAsync(checkauthResponse, ct);
+ }
+
+ throw Assumes.NotReachable();
+ case 3:
+ if (positive && (statelessRP || !sharedAssociation)) {
+ if (!tamper) {
+ // Respond to the replay attack.
+ var checkauthRequest = await op.Channel.ReadFromRequestAsync<CheckAuthenticationRequest>(req, ct);
+ var checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest);
+ checkauthResponse.IsValid = checkauthRequest.IsValid;
+ return await op.Channel.PrepareResponseAsync(checkauthResponse, ct);
+ }
+ }
+
+ throw Assumes.NotReachable();
+ default:
+ throw Assumes.NotReachable();
}
- });
+ }));
if (tamper) {
- coordinator.IncomingMessageFilter = message => {
- var assertion = message as PositiveAssertionResponse;
- if (assertion != null) {
- // Alter the Local Identifier between the Provider and the Relying Party.
- // If the signature binding element does its job, this should cause the RP
- // to throw.
- assertion.LocalIdentifier = "http://victim";
- }
- };
- }
- if (statelessRP) {
- coordinator.RelyingParty = new OpenIdRelyingParty(null);
+ // TODO: fix this.
+ ////coordinator.IncomingMessageFilter = message => {
+ //// var assertion = message as PositiveAssertionResponse;
+ //// if (assertion != null) {
+ //// // Alter the Local Identifier between the Provider and the Relying Party.
+ //// // If the signature binding element does its job, this should cause the RP
+ //// // to throw.
+ //// assertion.LocalIdentifier = "http://victim";
+ //// }
+ ////};
}
- coordinator.Run();
+ await coordinator.RunAsync();
}
}
}