//----------------------------------------------------------------------- // // Copyright (c) Andrew Arnott. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.Test.OpenId.Messages { using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Bindings; using DotNetOpenAuth.OpenId; using DotNetOpenAuth.OpenId.ChannelElements; using DotNetOpenAuth.OpenId.Messages; using DotNetOpenAuth.OpenId.RelyingParty; using NUnit.Framework; [TestFixture] public class IndirectSignedResponseTests : OpenIdTestBase { private const string CreationDateString = "2005-05-15T17:11:51Z"; private readonly DateTime creationDate = DateTime.Parse(CreationDateString, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal); private CheckIdRequest request; private IndirectSignedResponse response; private IndirectSignedResponse unsolicited; private Protocol protocol; [SetUp] public override void SetUp() { base.SetUp(); this.protocol = Protocol.V20; this.request = new CheckIdRequest(this.protocol.Version, OPUri, AuthenticationRequestMode.Setup); this.request.ReturnTo = RPUri; this.response = new IndirectSignedResponse(this.request); this.unsolicited = new IndirectSignedResponse(this.protocol.Version, RPUri); } [TestCase] public void CtorFromRequest() { Assert.AreEqual(this.protocol.Args.Mode.id_res, this.response.Mode); Assert.AreEqual(this.request.Version, this.response.Version); Assert.AreEqual(this.request.ReturnTo, this.response.Recipient); Assert.AreEqual(OPUri, this.response.ProviderEndpoint); Assert.IsTrue(DateTime.UtcNow - ((ITamperResistantOpenIdMessage)this.response).UtcCreationDate < TimeSpan.FromSeconds(5)); } [TestCase] public void CtorUnsolicited() { Assert.AreEqual(this.protocol.Args.Mode.id_res, this.unsolicited.Mode); Assert.AreEqual(this.protocol.Version, this.unsolicited.Version); Assert.AreEqual(RPUri, this.unsolicited.Recipient); Assert.IsTrue(DateTime.UtcNow - ((ITamperResistantOpenIdMessage)this.unsolicited).UtcCreationDate < TimeSpan.FromSeconds(5)); Assert.IsNull(this.unsolicited.ProviderEndpoint); this.unsolicited.ProviderEndpoint = OPUri; Assert.AreEqual(OPUri, this.unsolicited.ProviderEndpoint); } [TestCase] public void ResponseNonceSetter() { const string HybridValue = CreationDateString + "UNIQUE"; var responseAccessor = IndirectSignedResponse_Accessor.AttachShadow(this.response); IReplayProtectedProtocolMessage responseReplay = this.response; responseAccessor.ResponseNonce = HybridValue; Assert.AreEqual(HybridValue, responseAccessor.ResponseNonce); Assert.AreEqual(this.creationDate, responseReplay.UtcCreationDate); Assert.AreEqual("UNIQUE", responseReplay.Nonce); responseAccessor.ResponseNonce = null; Assert.IsNull(responseReplay.Nonce); } [TestCase] public void ResponseNonceGetter() { var responseAccessor = IndirectSignedResponse_Accessor.AttachShadow(this.response); IReplayProtectedProtocolMessage responseReplay = this.response; responseReplay.Nonce = "UnIqUe"; responseReplay.UtcCreationDate = this.creationDate; Assert.AreEqual(CreationDateString + "UnIqUe", responseAccessor.ResponseNonce); Assert.AreEqual("UnIqUe", responseReplay.Nonce); Assert.AreEqual(this.creationDate, responseReplay.UtcCreationDate); } [TestCase] public void UtcCreationDateConvertsToUniversal() { IReplayProtectedProtocolMessage responseReplay = this.response; DateTime local = DateTime.Parse("1982-01-01", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal); if (local.Kind != DateTimeKind.Local) { Assert.Inconclusive("Test cannot manage to create a local time."); } responseReplay.UtcCreationDate = local; DateTime utcCreationDate = responseReplay.UtcCreationDate; Assert.AreEqual(DateTimeKind.Utc, utcCreationDate.Kind, "Local time should have been converted to universal time."); Assert.AreNotEqual(local.Hour, utcCreationDate.Hour, "The hour was expected to change (unless local time _is_ UTC time for this PC!)"); // Now try setting UTC time just to make sure it DOESN'T mangle the hour if (this.creationDate.Kind != DateTimeKind.Utc) { Assert.Inconclusive("We need a UTC datetime to set with."); } responseReplay.UtcCreationDate = this.creationDate; utcCreationDate = responseReplay.UtcCreationDate; Assert.AreEqual(DateTimeKind.Utc, utcCreationDate.Kind); Assert.AreEqual(this.creationDate.Hour, utcCreationDate.Hour, "The hour should match since both times are UTC time."); } [TestCase] public void ReturnToDoesNotMatchRecipient() { // Make sure its valid first, so we know that when it's invalid // it is due to our tampering. this.response.EnsureValidMessage(); UriBuilder returnToBuilder = new UriBuilder(this.response.ReturnTo); var extraArgs = new Dictionary(); extraArgs["a"] = "b"; MessagingUtilities.AppendQueryArgs(returnToBuilder, extraArgs); this.response.ReturnTo = returnToBuilder.Uri; try { this.response.EnsureValidMessage(); Assert.Fail("Expected ProtocolException not thrown."); } catch (ProtocolException) { } } [TestCase, ExpectedException(typeof(ArgumentException))] public void GetReturnToArgumentNullKey() { this.response.GetReturnToArgument(null); } [TestCase, ExpectedException(typeof(ArgumentException))] public void GetReturnToArgumentEmptyKey() { this.response.GetReturnToArgument(string.Empty); } [TestCase] public void GetReturnToArgumentDoesNotReturnExtraArgs() { this.response.ExtraData["a"] = "b"; Assert.IsNull(this.response.GetReturnToArgument("a")); Assert.AreEqual(0, this.response.GetReturnToParameterNames().Count()); } [TestCase] public void GetReturnToArgumentAndNames() { UriBuilder returnToBuilder = new UriBuilder(this.response.ReturnTo); returnToBuilder.AppendQueryArgs(new Dictionary { { "a", "b" } }); this.request.ReturnTo = returnToBuilder.Uri; // First pretend that the return_to args were signed. this.response = new IndirectSignedResponse(this.request); this.response.ReturnToParametersSignatureValidated = true; Assert.AreEqual(1, this.response.GetReturnToParameterNames().Count()); Assert.IsTrue(this.response.GetReturnToParameterNames().Contains("a")); Assert.AreEqual("b", this.response.GetReturnToArgument("a")); // Now simulate them NOT being signed. They should still be visible at this level. this.response = new IndirectSignedResponse(this.request); this.response.ReturnToParametersSignatureValidated = false; Assert.AreEqual(1, this.response.GetReturnToParameterNames().Count()); Assert.IsTrue(this.response.GetReturnToParameterNames().Contains("a")); Assert.AreEqual("b", this.response.GetReturnToArgument("a")); } } }