diff options
15 files changed, 2312 insertions, 2312 deletions
diff --git a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs index 1f54b32..ba98f08 100644 --- a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs @@ -1,188 +1,188 @@ -//-----------------------------------------------------------------------
-// <copyright file="AssociationHandshakeTests.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.Test.OpenId {
- using System;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OpenId;
- using DotNetOpenAuth.OpenId.Messages;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- [TestClass]
- public class AssociationHandshakeTests : OpenIdTestBase {
- [TestInitialize]
- public override void SetUp() {
- base.SetUp();
- }
-
- [TestMethod]
- public void AssociateUnencrypted() {
- this.ParameterizedAssociationTest(new Uri("https://host"));
- }
-
- [TestMethod]
- public void AssociateDiffieHellmanOverHttp() {
- this.ParameterizedAssociationTest(new Uri("http://host"));
- }
-
- [TestMethod, Ignore]
- public void AssociateDiffieHellmanOverHttps() {
- // TODO: test the RP and OP agreeing to use Diffie-Hellman over HTTPS.
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Verifies that the RP and OP can renegotiate an association type if the RP's
- /// initial request for an association is for a type the OP doesn't support.
- /// </summary>
- [TestMethod, Ignore]
- public void AssociateRenegotiateBitLength() {
- // TODO: test where the RP asks for an association type that the OP doesn't support
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Verifies that the RP cannot get caught in an infinite loop if a bad OP
- /// keeps sending it association retry messages.
- /// </summary>
- [TestMethod, Ignore]
- public void AssociateRenegotiateBitLengthRPStopsAfterOneRetry() {
- // TODO: code here
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Verifies security settings limit RP's initial associate request
- /// </summary>
- [TestMethod, Ignore]
- public void AssociateRequestDeterminedBySecuritySettings() {
- // TODO: Code here
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Verifies security settings limit RP's acceptance of OP's counter-suggestion
- /// </summary>
- [TestMethod, Ignore]
- public void AssociateRenegotiateLimitedByRPSecuritySettings() {
- // TODO: Code here
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Verifies security settings limit OP's set of acceptable association types.
- /// </summary>
- [TestMethod, Ignore]
- public void AssociateLimitedByOPSecuritySettings() {
- // TODO: Code here
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Verifies the RP can recover with no association after receiving an
- /// associate error response from the OP when no suggested association
- /// type is included.
- /// </summary>
- [TestMethod, Ignore]
- public void AssociateContinueAfterOpenIdError() {
- // TODO: Code here
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Verifies that the RP can recover from an invalid or non-existent
- /// response from the OP, for example in the HTTP timeout case.
- /// </summary>
- [TestMethod, Ignore]
- public void AssociateContinueAfterHttpError() {
- // TODO: Code here
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Runs a parameterized association flow test using all supported OpenID versions.
- /// </summary>
- /// <param name="opEndpoint">The OP endpoint to simulate using.</param>
- private void ParameterizedAssociationTest(Uri opEndpoint) {
- foreach (Protocol protocol in Protocol.AllPracticalVersions) {
- var endpoint = new ProviderEndpointDescription(opEndpoint, protocol.Version);
- var associationType = protocol.Version.Major < 2 ? protocol.Args.SignatureAlgorithm.HMAC_SHA1 : protocol.Args.SignatureAlgorithm.HMAC_SHA256;
- this.ParameterizedAssociationTest(endpoint, associationType);
- }
- }
-
- /// <summary>
- /// Runs a parameterized association flow test.
- /// </summary>
- /// <param name="opDescription">
- /// The description of the Provider that the relying party uses to formulate the request.
- /// The specific host is not used, but the scheme is significant.
- /// </param>
- /// <param name="expectedAssociationType">
- /// The value of the openid.assoc_type parameter expected,
- /// or null if a failure is anticipated.
- /// </param>
- private void ParameterizedAssociationTest(
- ProviderEndpointDescription opDescription,
- string expectedAssociationType) {
- Protocol protocol = Protocol.Lookup(opDescription.ProtocolVersion);
- bool expectSuccess = expectedAssociationType != null;
- bool expectDiffieHellman = !opDescription.Endpoint.IsTransportSecure();
- Association rpAssociation = null, opAssociation;
- AssociateSuccessfulResponse associateSuccessfulResponse = null;
- AssociateUnsuccessfulResponse associateUnsuccessfulResponse = null;
- OpenIdCoordinator coordinator = new OpenIdCoordinator(
- rp => {
- rp.SecuritySettings = this.RelyingPartySecuritySettings;
- rpAssociation = rp.GetAssociation(opDescription);
- },
- op => {
- op.SecuritySettings = this.ProviderSecuritySettings;
- op.AutoRespond();
- });
- coordinator.IncomingMessageFilter = message => {
- Assert.AreSame(opDescription.ProtocolVersion, message.Version, "The message was recognized as version {0} but was expected to be {1}.", message.Version, opDescription.ProtocolVersion);
- var associateSuccess = message as AssociateSuccessfulResponse;
- var associateFailed = message as AssociateUnsuccessfulResponse;
- if (associateSuccess != null) {
- associateSuccessfulResponse = associateSuccess;
- }
- if (associateFailed != null) {
- associateUnsuccessfulResponse = associateFailed;
- }
- };
- coordinator.OutgoingMessageFilter = message => {
- Assert.AreSame(opDescription.ProtocolVersion, message.Version, "The message was for version {0} but was expected to be for {1}.", message.Version, opDescription.ProtocolVersion);
- };
- coordinator.Run();
-
- if (expectSuccess) {
- Assert.IsNotNull(rpAssociation);
- Assert.AreSame(rpAssociation, coordinator.RelyingParty.AssociationStore.GetAssociation(opDescription.Endpoint, rpAssociation.Handle));
- opAssociation = coordinator.Provider.AssociationStore.GetAssociation(AssociationRelyingPartyType.Smart, rpAssociation.Handle);
- Assert.IsNotNull(opAssociation, "The Provider should have stored the association.");
-
- Assert.AreEqual(opAssociation.Handle, rpAssociation.Handle);
- Assert.AreEqual(expectedAssociationType, rpAssociation.GetAssociationType(protocol));
- Assert.AreEqual(expectedAssociationType, opAssociation.GetAssociationType(protocol));
- Assert.IsTrue(Math.Abs(opAssociation.SecondsTillExpiration - rpAssociation.SecondsTillExpiration) < 60);
- Assert.IsTrue(MessagingUtilities.AreEquivalent(opAssociation.SecretKey, rpAssociation.SecretKey));
-
- if (expectDiffieHellman) {
- Assert.IsInstanceOfType(associateSuccessfulResponse, typeof(AssociateDiffieHellmanResponse));
- var diffieHellmanResponse = (AssociateDiffieHellmanResponse)associateSuccessfulResponse;
- Assert.IsFalse(MessagingUtilities.AreEquivalent(diffieHellmanResponse.EncodedMacKey, rpAssociation.SecretKey), "Key should have been encrypted.");
- } else {
- Assert.IsInstanceOfType(associateSuccessfulResponse, typeof(AssociateUnencryptedResponse));
- var unencryptedResponse = (AssociateUnencryptedResponse)associateSuccessfulResponse;
- }
- } else {
- Assert.IsNull(coordinator.RelyingParty.AssociationStore.GetAssociation(opDescription.Endpoint));
- Assert.IsNull(coordinator.Provider.AssociationStore.GetAssociation(AssociationRelyingPartyType.Smart));
- }
- }
- }
-}
+//----------------------------------------------------------------------- +// <copyright file="AssociationHandshakeTests.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.OpenId { + using System; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OpenId; + using DotNetOpenAuth.OpenId.Messages; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class AssociationHandshakeTests : OpenIdTestBase { + [TestInitialize] + public override void SetUp() { + base.SetUp(); + } + + [TestMethod] + public void AssociateUnencrypted() { + this.ParameterizedAssociationTest(new Uri("https://host")); + } + + [TestMethod] + public void AssociateDiffieHellmanOverHttp() { + this.ParameterizedAssociationTest(new Uri("http://host")); + } + + [TestMethod, Ignore] + public void AssociateDiffieHellmanOverHttps() { + // TODO: test the RP and OP agreeing to use Diffie-Hellman over HTTPS. + throw new NotImplementedException(); + } + + /// <summary> + /// Verifies that the RP and OP can renegotiate an association type if the RP's + /// initial request for an association is for a type the OP doesn't support. + /// </summary> + [TestMethod, Ignore] + public void AssociateRenegotiateBitLength() { + // TODO: test where the RP asks for an association type that the OP doesn't support + throw new NotImplementedException(); + } + + /// <summary> + /// Verifies that the RP cannot get caught in an infinite loop if a bad OP + /// keeps sending it association retry messages. + /// </summary> + [TestMethod, Ignore] + public void AssociateRenegotiateBitLengthRPStopsAfterOneRetry() { + // TODO: code here + throw new NotImplementedException(); + } + + /// <summary> + /// Verifies security settings limit RP's initial associate request + /// </summary> + [TestMethod, Ignore] + public void AssociateRequestDeterminedBySecuritySettings() { + // TODO: Code here + throw new NotImplementedException(); + } + + /// <summary> + /// Verifies security settings limit RP's acceptance of OP's counter-suggestion + /// </summary> + [TestMethod, Ignore] + public void AssociateRenegotiateLimitedByRPSecuritySettings() { + // TODO: Code here + throw new NotImplementedException(); + } + + /// <summary> + /// Verifies security settings limit OP's set of acceptable association types. + /// </summary> + [TestMethod, Ignore] + public void AssociateLimitedByOPSecuritySettings() { + // TODO: Code here + throw new NotImplementedException(); + } + + /// <summary> + /// Verifies the RP can recover with no association after receiving an + /// associate error response from the OP when no suggested association + /// type is included. + /// </summary> + [TestMethod, Ignore] + public void AssociateContinueAfterOpenIdError() { + // TODO: Code here + throw new NotImplementedException(); + } + + /// <summary> + /// Verifies that the RP can recover from an invalid or non-existent + /// response from the OP, for example in the HTTP timeout case. + /// </summary> + [TestMethod, Ignore] + public void AssociateContinueAfterHttpError() { + // TODO: Code here + throw new NotImplementedException(); + } + + /// <summary> + /// Runs a parameterized association flow test using all supported OpenID versions. + /// </summary> + /// <param name="opEndpoint">The OP endpoint to simulate using.</param> + private void ParameterizedAssociationTest(Uri opEndpoint) { + foreach (Protocol protocol in Protocol.AllPracticalVersions) { + var endpoint = new ProviderEndpointDescription(opEndpoint, protocol.Version); + var associationType = protocol.Version.Major < 2 ? protocol.Args.SignatureAlgorithm.HMAC_SHA1 : protocol.Args.SignatureAlgorithm.HMAC_SHA256; + this.ParameterizedAssociationTest(endpoint, associationType); + } + } + + /// <summary> + /// Runs a parameterized association flow test. + /// </summary> + /// <param name="opDescription"> + /// The description of the Provider that the relying party uses to formulate the request. + /// The specific host is not used, but the scheme is significant. + /// </param> + /// <param name="expectedAssociationType"> + /// The value of the openid.assoc_type parameter expected, + /// or null if a failure is anticipated. + /// </param> + private void ParameterizedAssociationTest( + ProviderEndpointDescription opDescription, + string expectedAssociationType) { + Protocol protocol = Protocol.Lookup(opDescription.ProtocolVersion); + bool expectSuccess = expectedAssociationType != null; + bool expectDiffieHellman = !opDescription.Endpoint.IsTransportSecure(); + Association rpAssociation = null, opAssociation; + AssociateSuccessfulResponse associateSuccessfulResponse = null; + AssociateUnsuccessfulResponse associateUnsuccessfulResponse = null; + OpenIdCoordinator coordinator = new OpenIdCoordinator( + rp => { + rp.SecuritySettings = this.RelyingPartySecuritySettings; + rpAssociation = rp.GetAssociation(opDescription); + }, + op => { + op.SecuritySettings = this.ProviderSecuritySettings; + op.AutoRespond(); + }); + coordinator.IncomingMessageFilter = message => { + Assert.AreSame(opDescription.ProtocolVersion, message.Version, "The message was recognized as version {0} but was expected to be {1}.", message.Version, opDescription.ProtocolVersion); + var associateSuccess = message as AssociateSuccessfulResponse; + var associateFailed = message as AssociateUnsuccessfulResponse; + if (associateSuccess != null) { + associateSuccessfulResponse = associateSuccess; + } + if (associateFailed != null) { + associateUnsuccessfulResponse = associateFailed; + } + }; + coordinator.OutgoingMessageFilter = message => { + Assert.AreSame(opDescription.ProtocolVersion, message.Version, "The message was for version {0} but was expected to be for {1}.", message.Version, opDescription.ProtocolVersion); + }; + coordinator.Run(); + + if (expectSuccess) { + Assert.IsNotNull(rpAssociation); + Assert.AreSame(rpAssociation, coordinator.RelyingParty.AssociationStore.GetAssociation(opDescription.Endpoint, rpAssociation.Handle)); + opAssociation = coordinator.Provider.AssociationStore.GetAssociation(AssociationRelyingPartyType.Smart, rpAssociation.Handle); + Assert.IsNotNull(opAssociation, "The Provider should have stored the association."); + + Assert.AreEqual(opAssociation.Handle, rpAssociation.Handle); + Assert.AreEqual(expectedAssociationType, rpAssociation.GetAssociationType(protocol)); + Assert.AreEqual(expectedAssociationType, opAssociation.GetAssociationType(protocol)); + Assert.IsTrue(Math.Abs(opAssociation.SecondsTillExpiration - rpAssociation.SecondsTillExpiration) < 60); + Assert.IsTrue(MessagingUtilities.AreEquivalent(opAssociation.SecretKey, rpAssociation.SecretKey)); + + if (expectDiffieHellman) { + Assert.IsInstanceOfType(associateSuccessfulResponse, typeof(AssociateDiffieHellmanResponse)); + var diffieHellmanResponse = (AssociateDiffieHellmanResponse)associateSuccessfulResponse; + Assert.IsFalse(MessagingUtilities.AreEquivalent(diffieHellmanResponse.EncodedMacKey, rpAssociation.SecretKey), "Key should have been encrypted."); + } else { + Assert.IsInstanceOfType(associateSuccessfulResponse, typeof(AssociateUnencryptedResponse)); + var unencryptedResponse = (AssociateUnencryptedResponse)associateSuccessfulResponse; + } + } else { + Assert.IsNull(coordinator.RelyingParty.AssociationStore.GetAssociation(opDescription.Endpoint)); + Assert.IsNull(coordinator.Provider.AssociationStore.GetAssociation(AssociationRelyingPartyType.Smart)); + } + } + } +} diff --git a/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs b/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs index 99c3ad1..d05ddd8 100644 --- a/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs @@ -1,166 +1,166 @@ -//-----------------------------------------------------------------------
-// <copyright file="AuthenticationTests.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.Test.OpenId {
- using System;
- using System.Collections.Generic;
- 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 DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- [TestClass]
- public class AuthenticationTests : OpenIdTestBase {
- [TestInitialize]
- public override void SetUp() {
- base.SetUp();
- }
-
- [TestMethod]
- public void SharedAssociationPositive() {
- this.ParameterizedPositiveAuthenticationTest(true, true, false);
- }
-
- /// <summary>
- /// Verifies that a shared association protects against tampering.
- /// </summary>
- [TestMethod]
- public void SharedAssociationTampered() {
- this.ParameterizedPositiveAuthenticationTest(true, true, true);
- }
-
- [TestMethod]
- public void SharedAssociationNegative() {
- this.ParameterizedPositiveAuthenticationTest(true, false, false);
- }
-
- [TestMethod]
- public void PrivateAssociationPositive() {
- this.ParameterizedPositiveAuthenticationTest(false, true, false);
- }
-
- /// <summary>
- /// Verifies that a private association protects against tampering.
- /// </summary>
- [TestMethod]
- public void PrivateAssociationTampered() {
- this.ParameterizedPositiveAuthenticationTest(false, true, true);
- }
-
- [TestMethod]
- public void NoAssociationNegative() {
- this.ParameterizedPositiveAuthenticationTest(false, false, false);
- }
-
- private void ParameterizedPositiveAuthenticationTest(bool sharedAssociation, bool positive, bool tamper) {
- foreach (Protocol protocol in Protocol.AllPracticalVersions) {
- this.ParameterizedPositiveAuthenticationTest(protocol, sharedAssociation, positive, tamper);
- }
- }
-
- private void ParameterizedPositiveAuthenticationTest(Protocol protocol, bool sharedAssociation, bool positive, bool tamper) {
- ErrorUtilities.VerifyArgument(positive || !tamper, "Cannot tamper with a negative response.");
- Uri userSetupUrl = protocol.Version.Major < 2 ? new Uri("http://usersetupurl") : null;
- Association association = sharedAssociation ? HmacShaAssociation.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart) : null;
- var coordinator = new OpenIdCoordinator(
- rp => {
- var request = new CheckIdRequest(protocol.Version, ProviderUri, AuthenticationRequestMode.Immediate);
-
- if (association != null) {
- rp.AssociationStore.StoreAssociation(ProviderUri, association);
- request.AssociationHandle = association.Handle;
- }
-
- request.ClaimedIdentifier = "http://claimedid";
- request.LocalIdentifier = "http://localid";
- request.ReturnTo = RPUri;
- rp.Channel.Send(request);
- if (positive) {
- if (tamper) {
- try {
- rp.Channel.ReadFromRequest<PositiveAssertionResponse>();
- 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>();
- Assert.IsNotNull(response);
- Assert.AreEqual(request.ClaimedIdentifier, response.ClaimedIdentifier);
- Assert.AreEqual(request.LocalIdentifier, response.LocalIdentifier);
- Assert.AreEqual(request.ReturnTo, response.ReturnTo);
-
- // Attempt to replay the message and verify that it fails.
- // Because in various scenarios and protocol versions different components
- // notice the replay, we can get one of two exceptions thrown.
- // When the OP notices the replay we get a generic InvalidSignatureException.
- // When the RP notices the replay we get a specific ReplayMessageException.
- Type expectedExceptionType = sharedAssociation || protocol.Version.Major < 2 ? typeof(ReplayedMessageException) : typeof(InvalidSignatureException);
- try {
- CoordinatingChannel channel = (CoordinatingChannel)rp.Channel;
- channel.Replay(response);
- Assert.Fail("Expected exception {0} was not thrown.", expectedExceptionType.Name);
- } catch (ProtocolException ex) {
- Assert.IsInstanceOfType(ex, expectedExceptionType);
- }
- }
- } else {
- var response = rp.Channel.ReadFromRequest<NegativeAssertionResponse>();
- Assert.IsNotNull(response);
- Assert.AreEqual(userSetupUrl, response.UserSetupUrl);
- }
- },
- op => {
- if (association != null) {
- op.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, association);
- }
-
- var request = op.Channel.ReadFromRequest<CheckIdRequest>();
- Assert.IsNotNull(request);
- IProtocolMessage response;
- if (positive) {
- response = new PositiveAssertionResponse(request);
- } else {
- response = new NegativeAssertionResponse(request) { UserSetupUrl = userSetupUrl };
- }
- op.Channel.Send(response);
-
- if (positive && !sharedAssociation) {
- var checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>();
- var checkauthResponse = new CheckAuthenticationResponse(checkauthRequest);
- checkauthResponse.IsValid = checkauthRequest.IsValid;
- op.Channel.Send(checkauthResponse);
-
- if (!tamper) {
- // Respond to the replay attack.
- checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>();
- checkauthResponse = new CheckAuthenticationResponse(checkauthRequest);
- checkauthResponse.IsValid = checkauthRequest.IsValid;
- op.Channel.Send(checkauthResponse);
- }
- }
- });
- 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";
- }
- };
- }
- coordinator.Run();
- }
- }
-}
+//----------------------------------------------------------------------- +// <copyright file="AuthenticationTests.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.OpenId { + using System; + using System.Collections.Generic; + 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 DotNetOpenAuth.Test.Mocks; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class AuthenticationTests : OpenIdTestBase { + [TestInitialize] + public override void SetUp() { + base.SetUp(); + } + + [TestMethod] + public void SharedAssociationPositive() { + this.ParameterizedPositiveAuthenticationTest(true, true, false); + } + + /// <summary> + /// Verifies that a shared association protects against tampering. + /// </summary> + [TestMethod] + public void SharedAssociationTampered() { + this.ParameterizedPositiveAuthenticationTest(true, true, true); + } + + [TestMethod] + public void SharedAssociationNegative() { + this.ParameterizedPositiveAuthenticationTest(true, false, false); + } + + [TestMethod] + public void PrivateAssociationPositive() { + this.ParameterizedPositiveAuthenticationTest(false, true, false); + } + + /// <summary> + /// Verifies that a private association protects against tampering. + /// </summary> + [TestMethod] + public void PrivateAssociationTampered() { + this.ParameterizedPositiveAuthenticationTest(false, true, true); + } + + [TestMethod] + public void NoAssociationNegative() { + this.ParameterizedPositiveAuthenticationTest(false, false, false); + } + + private void ParameterizedPositiveAuthenticationTest(bool sharedAssociation, bool positive, bool tamper) { + foreach (Protocol protocol in Protocol.AllPracticalVersions) { + this.ParameterizedPositiveAuthenticationTest(protocol, sharedAssociation, positive, tamper); + } + } + + private void ParameterizedPositiveAuthenticationTest(Protocol protocol, bool sharedAssociation, bool positive, bool tamper) { + ErrorUtilities.VerifyArgument(positive || !tamper, "Cannot tamper with a negative response."); + Uri userSetupUrl = protocol.Version.Major < 2 ? new Uri("http://usersetupurl") : null; + Association association = sharedAssociation ? HmacShaAssociation.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart) : null; + var coordinator = new OpenIdCoordinator( + rp => { + var request = new CheckIdRequest(protocol.Version, ProviderUri, AuthenticationRequestMode.Immediate); + + if (association != null) { + rp.AssociationStore.StoreAssociation(ProviderUri, association); + request.AssociationHandle = association.Handle; + } + + request.ClaimedIdentifier = "http://claimedid"; + request.LocalIdentifier = "http://localid"; + request.ReturnTo = RPUri; + rp.Channel.Send(request); + if (positive) { + if (tamper) { + try { + rp.Channel.ReadFromRequest<PositiveAssertionResponse>(); + 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>(); + Assert.IsNotNull(response); + Assert.AreEqual(request.ClaimedIdentifier, response.ClaimedIdentifier); + Assert.AreEqual(request.LocalIdentifier, response.LocalIdentifier); + Assert.AreEqual(request.ReturnTo, response.ReturnTo); + + // Attempt to replay the message and verify that it fails. + // Because in various scenarios and protocol versions different components + // notice the replay, we can get one of two exceptions thrown. + // When the OP notices the replay we get a generic InvalidSignatureException. + // When the RP notices the replay we get a specific ReplayMessageException. + Type expectedExceptionType = sharedAssociation || protocol.Version.Major < 2 ? typeof(ReplayedMessageException) : typeof(InvalidSignatureException); + try { + CoordinatingChannel channel = (CoordinatingChannel)rp.Channel; + channel.Replay(response); + Assert.Fail("Expected exception {0} was not thrown.", expectedExceptionType.Name); + } catch (ProtocolException ex) { + Assert.IsInstanceOfType(ex, expectedExceptionType); + } + } + } else { + var response = rp.Channel.ReadFromRequest<NegativeAssertionResponse>(); + Assert.IsNotNull(response); + Assert.AreEqual(userSetupUrl, response.UserSetupUrl); + } + }, + op => { + if (association != null) { + op.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, association); + } + + var request = op.Channel.ReadFromRequest<CheckIdRequest>(); + Assert.IsNotNull(request); + IProtocolMessage response; + if (positive) { + response = new PositiveAssertionResponse(request); + } else { + response = new NegativeAssertionResponse(request) { UserSetupUrl = userSetupUrl }; + } + op.Channel.Send(response); + + if (positive && !sharedAssociation) { + var checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>(); + var checkauthResponse = new CheckAuthenticationResponse(checkauthRequest); + checkauthResponse.IsValid = checkauthRequest.IsValid; + op.Channel.Send(checkauthResponse); + + if (!tamper) { + // Respond to the replay attack. + checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>(); + checkauthResponse = new CheckAuthenticationResponse(checkauthRequest); + checkauthResponse.IsValid = checkauthRequest.IsValid; + op.Channel.Send(checkauthResponse); + } + } + }); + 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"; + } + }; + } + coordinator.Run(); + } + } +} diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs index 6ab27b4..298b6d4 100644 --- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs @@ -1,105 +1,105 @@ -//-----------------------------------------------------------------------
-// <copyright file="ExtensionsBindingElementTests.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text.RegularExpressions;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OpenId;
- using DotNetOpenAuth.OpenId.ChannelElements;
- using DotNetOpenAuth.OpenId.Extensions;
- using DotNetOpenAuth.OpenId.Messages;
- using DotNetOpenAuth.OpenId.RelyingParty;
- using DotNetOpenAuth.Test.Mocks;
- using DotNetOpenAuth.Test.OpenId.Extensions;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- [TestClass]
- public class ExtensionsBindingElementTests : OpenIdTestBase {
- private OpenIdExtensionFactory factory;
- private ExtensionsBindingElement element;
- private IProtocolMessageWithExtensions request;
-
- [TestInitialize]
- public override void SetUp() {
- base.SetUp();
-
- this.factory = new OpenIdExtensionFactory();
- this.factory.RegisterExtension(MockOpenIdExtension.Factory);
- this.element = new ExtensionsBindingElement(this.factory);
- this.request = new SignedResponseRequest(Protocol.Default.Version, OpenIdTestBase.ProviderUri, AuthenticationRequestMode.Immediate);
- }
-
- [TestMethod]
- public void RoundTripFullStackTest() {
- IOpenIdMessageExtension request = new MockOpenIdExtension("requestPart", "requestData");
- IOpenIdMessageExtension response = new MockOpenIdExtension("responsePart", "responseData");
- ExtensionTestUtilities.Roundtrip(
- Protocol.Default,
- new IOpenIdMessageExtension[] { request },
- new IOpenIdMessageExtension[] { response });
- }
-
- [TestMethod]
- public void ExtensionFactory() {
- Assert.AreSame(this.factory, this.element.ExtensionFactory);
- }
-
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
- public void PrepareMessageForSendingNull() {
- this.element.PrepareMessageForSending(null);
- }
-
- /// <summary>
- /// Verifies that false is returned when a non-extendable message is sent.
- /// </summary>
- [TestMethod]
- public void PrepareMessageForSendingNonExtendableMessage() {
- IProtocolMessage request = new AssociateDiffieHellmanRequest(Protocol.Default.Version, OpenIdTestBase.ProviderUri);
- Assert.IsFalse(this.element.PrepareMessageForSending(request));
- }
-
- [TestMethod]
- public void PrepareMessageForSending() {
- this.request.Extensions.Add(new MockOpenIdExtension("part", "extra"));
- Assert.IsTrue(this.element.PrepareMessageForSending(this.request));
-
- string alias = GetAliases(this.request.ExtraData).Single();
- Assert.AreEqual(MockOpenIdExtension.MockTypeUri, this.request.ExtraData["openid.ns." + alias]);
- Assert.AreEqual("part", this.request.ExtraData["openid." + alias + ".Part"]);
- Assert.AreEqual("extra", this.request.ExtraData["openid." + alias + ".data"]);
- }
-
- [TestMethod]
- public void PrepareMessageForReceiving() {
- this.request.ExtraData["openid.ns.mock"] = MockOpenIdExtension.MockTypeUri;
- this.request.ExtraData["openid.mock.Part"] = "part";
- this.request.ExtraData["openid.mock.data"] = "extra";
- Assert.IsTrue(this.element.PrepareMessageForReceiving(this.request));
- MockOpenIdExtension ext = this.request.Extensions.OfType<MockOpenIdExtension>().Single();
- Assert.AreEqual("part", ext.Part);
- Assert.AreEqual("extra", ext.Data);
- }
-
- /// <summary>
- /// Verifies that unsigned extension responses (where any or all fields are unsigned) are ignored.
- /// </summary>
- [TestMethod, Ignore]
- public void UnsignedExtensionsAreIgnored() {
- Assert.Inconclusive("Not yet implemented.");
- }
-
- private static IEnumerable<string> GetAliases(IDictionary<string, string> extraData) {
- Regex regex = new Regex(@"^openid\.ns\.(\w+)");
- return from key in extraData.Keys
- let m = regex.Match(key)
- where m.Success
- select m.Groups[1].Value;
- }
- }
-}
+//----------------------------------------------------------------------- +// <copyright file="ExtensionsBindingElementTests.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.OpenId.ChannelElements { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text.RegularExpressions; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OpenId; + using DotNetOpenAuth.OpenId.ChannelElements; + using DotNetOpenAuth.OpenId.Extensions; + using DotNetOpenAuth.OpenId.Messages; + using DotNetOpenAuth.OpenId.RelyingParty; + using DotNetOpenAuth.Test.Mocks; + using DotNetOpenAuth.Test.OpenId.Extensions; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class ExtensionsBindingElementTests : OpenIdTestBase { + private OpenIdExtensionFactory factory; + private ExtensionsBindingElement element; + private IProtocolMessageWithExtensions request; + + [TestInitialize] + public override void SetUp() { + base.SetUp(); + + this.factory = new OpenIdExtensionFactory(); + this.factory.RegisterExtension(MockOpenIdExtension.Factory); + this.element = new ExtensionsBindingElement(this.factory); + this.request = new SignedResponseRequest(Protocol.Default.Version, OpenIdTestBase.ProviderUri, AuthenticationRequestMode.Immediate); + } + + [TestMethod] + public void RoundTripFullStackTest() { + IOpenIdMessageExtension request = new MockOpenIdExtension("requestPart", "requestData"); + IOpenIdMessageExtension response = new MockOpenIdExtension("responsePart", "responseData"); + ExtensionTestUtilities.Roundtrip( + Protocol.Default, + new IOpenIdMessageExtension[] { request }, + new IOpenIdMessageExtension[] { response }); + } + + [TestMethod] + public void ExtensionFactory() { + Assert.AreSame(this.factory, this.element.ExtensionFactory); + } + + [TestMethod, ExpectedException(typeof(ArgumentNullException))] + public void PrepareMessageForSendingNull() { + this.element.PrepareMessageForSending(null); + } + + /// <summary> + /// Verifies that false is returned when a non-extendable message is sent. + /// </summary> + [TestMethod] + public void PrepareMessageForSendingNonExtendableMessage() { + IProtocolMessage request = new AssociateDiffieHellmanRequest(Protocol.Default.Version, OpenIdTestBase.ProviderUri); + Assert.IsFalse(this.element.PrepareMessageForSending(request)); + } + + [TestMethod] + public void PrepareMessageForSending() { + this.request.Extensions.Add(new MockOpenIdExtension("part", "extra")); + Assert.IsTrue(this.element.PrepareMessageForSending(this.request)); + + string alias = GetAliases(this.request.ExtraData).Single(); + Assert.AreEqual(MockOpenIdExtension.MockTypeUri, this.request.ExtraData["openid.ns." + alias]); + Assert.AreEqual("part", this.request.ExtraData["openid." + alias + ".Part"]); + Assert.AreEqual("extra", this.request.ExtraData["openid." + alias + ".data"]); + } + + [TestMethod] + public void PrepareMessageForReceiving() { + this.request.ExtraData["openid.ns.mock"] = MockOpenIdExtension.MockTypeUri; + this.request.ExtraData["openid.mock.Part"] = "part"; + this.request.ExtraData["openid.mock.data"] = "extra"; + Assert.IsTrue(this.element.PrepareMessageForReceiving(this.request)); + MockOpenIdExtension ext = this.request.Extensions.OfType<MockOpenIdExtension>().Single(); + Assert.AreEqual("part", ext.Part); + Assert.AreEqual("extra", ext.Data); + } + + /// <summary> + /// Verifies that unsigned extension responses (where any or all fields are unsigned) are ignored. + /// </summary> + [TestMethod, Ignore] + public void UnsignedExtensionsAreIgnored() { + Assert.Inconclusive("Not yet implemented."); + } + + private static IEnumerable<string> GetAliases(IDictionary<string, string> extraData) { + Regex regex = new Regex(@"^openid\.ns\.(\w+)"); + return from key in extraData.Keys + let m = regex.Match(key) + where m.Success + select m.Groups[1].Value; + } + } +} diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestBase.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestBase.cs index fe518f3..c616ed3 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestBase.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestBase.cs @@ -1,68 +1,68 @@ -//-----------------------------------------------------------------------
-// <copyright file="ExtensionTestBase.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.Test.OpenId.Extensions {
- using System.Collections.Generic;
- using System.Linq;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OpenId;
- using DotNetOpenAuth.OpenId.ChannelElements;
- using DotNetOpenAuth.OpenId.Extensions;
- using DotNetOpenAuth.OpenId.Messages;
- using DotNetOpenAuth.OpenId.RelyingParty;
- using DotNetOpenAuth.Test.Messaging;
-
- public static class ExtensionTestUtilities {
- internal static void Roundtrip(
- Protocol protocol,
- IEnumerable<IOpenIdMessageExtension> requests,
- IEnumerable<IOpenIdMessageExtension> responses) {
- Association association = HmacShaAssociation.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart);
- var coordinator = new OpenIdCoordinator(
- rp => {
- RegisterExtension(rp.Channel, Mocks.MockOpenIdExtension.Factory);
- var requestBase = new CheckIdRequest(protocol.Version, OpenIdTestBase.ProviderUri, AuthenticationRequestMode.Immediate);
- rp.AssociationStore.StoreAssociation(OpenIdTestBase.ProviderUri, association);
- requestBase.AssociationHandle = association.Handle;
- requestBase.ClaimedIdentifier = "http://claimedid";
- requestBase.LocalIdentifier = "http://localid";
- requestBase.ReturnTo = OpenIdTestBase.RPUri;
-
- foreach (IOpenIdMessageExtension extension in requests) {
- requestBase.Extensions.Add(extension);
- }
-
- rp.Channel.Send(requestBase);
- var response = rp.Channel.ReadFromRequest<PositiveAssertionResponse>();
-
- var receivedResponses = response.Extensions.Cast<IOpenIdMessageExtension>();
- CollectionAssert<IOpenIdMessageExtension>.AreEquivalentByEquality(responses.ToArray(), receivedResponses.ToArray());
- },
- op => {
- RegisterExtension(op.Channel, Mocks.MockOpenIdExtension.Factory);
- op.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, association);
- var request = op.Channel.ReadFromRequest<CheckIdRequest>();
- var response = new PositiveAssertionResponse(request);
- var receivedRequests = request.Extensions.Cast<IOpenIdMessageExtension>();
- CollectionAssert<IOpenIdMessageExtension>.AreEquivalentByEquality(requests.ToArray(), receivedRequests.ToArray());
-
- foreach (var extensionResponse in responses) {
- response.Extensions.Add(extensionResponse);
- }
-
- op.Channel.Send(response);
- });
- coordinator.Run();
- }
-
- internal static void RegisterExtension(Channel channel, OpenIdExtensionFactory.CreateDelegate extensionFactory) {
- ErrorUtilities.VerifyArgumentNotNull(channel, "channel");
-
- OpenIdExtensionFactory factory = (OpenIdExtensionFactory)channel.BindingElements.OfType<ExtensionsBindingElement>().Single().ExtensionFactory;
- factory.RegisterExtension(extensionFactory);
- }
- }
-}
+//----------------------------------------------------------------------- +// <copyright file="ExtensionTestBase.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.OpenId.Extensions { + using System.Collections.Generic; + using System.Linq; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OpenId; + using DotNetOpenAuth.OpenId.ChannelElements; + using DotNetOpenAuth.OpenId.Extensions; + using DotNetOpenAuth.OpenId.Messages; + using DotNetOpenAuth.OpenId.RelyingParty; + using DotNetOpenAuth.Test.Messaging; + + public static class ExtensionTestUtilities { + internal static void Roundtrip( + Protocol protocol, + IEnumerable<IOpenIdMessageExtension> requests, + IEnumerable<IOpenIdMessageExtension> responses) { + Association association = HmacShaAssociation.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart); + var coordinator = new OpenIdCoordinator( + rp => { + RegisterExtension(rp.Channel, Mocks.MockOpenIdExtension.Factory); + var requestBase = new CheckIdRequest(protocol.Version, OpenIdTestBase.ProviderUri, AuthenticationRequestMode.Immediate); + rp.AssociationStore.StoreAssociation(OpenIdTestBase.ProviderUri, association); + requestBase.AssociationHandle = association.Handle; + requestBase.ClaimedIdentifier = "http://claimedid"; + requestBase.LocalIdentifier = "http://localid"; + requestBase.ReturnTo = OpenIdTestBase.RPUri; + + foreach (IOpenIdMessageExtension extension in requests) { + requestBase.Extensions.Add(extension); + } + + rp.Channel.Send(requestBase); + var response = rp.Channel.ReadFromRequest<PositiveAssertionResponse>(); + + var receivedResponses = response.Extensions.Cast<IOpenIdMessageExtension>(); + CollectionAssert<IOpenIdMessageExtension>.AreEquivalentByEquality(responses.ToArray(), receivedResponses.ToArray()); + }, + op => { + RegisterExtension(op.Channel, Mocks.MockOpenIdExtension.Factory); + op.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, association); + var request = op.Channel.ReadFromRequest<CheckIdRequest>(); + var response = new PositiveAssertionResponse(request); + var receivedRequests = request.Extensions.Cast<IOpenIdMessageExtension>(); + CollectionAssert<IOpenIdMessageExtension>.AreEquivalentByEquality(requests.ToArray(), receivedRequests.ToArray()); + + foreach (var extensionResponse in responses) { + response.Extensions.Add(extensionResponse); + } + + op.Channel.Send(response); + }); + coordinator.Run(); + } + + internal static void RegisterExtension(Channel channel, OpenIdExtensionFactory.CreateDelegate extensionFactory) { + ErrorUtilities.VerifyArgumentNotNull(channel, "channel"); + + OpenIdExtensionFactory factory = (OpenIdExtensionFactory)channel.BindingElements.OfType<ExtensionsBindingElement>().Single().ExtensionFactory; + factory.RegisterExtension(extensionFactory); + } + } +} diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs index d12aa29..093518d 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs @@ -1,45 +1,45 @@ -//-----------------------------------------------------------------------
-// <copyright file="IndirectErrorResponseTests.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.Test.OpenId.Messages {
- using System;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OpenId;
- using DotNetOpenAuth.OpenId.Messages;
- using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- [TestClass]
- public class IndirectErrorResponseTests : OpenIdTestBase {
- private IndirectErrorResponse response;
-
- [TestInitialize]
- public void Setup() {
- CheckIdRequest request = new CheckIdRequest(Protocol.V20.Version, ProviderUri, AuthenticationRequestMode.Immediate);
- request.ReturnTo = RPUri;
- this.response = new IndirectErrorResponse(request);
- }
-
- [TestMethod]
- public void Ctor() {
- Assert.AreEqual(RPUri, this.response.Recipient);
- }
-
- [TestMethod]
- public void ParameterNames() {
- this.response.ErrorMessage = "Some Error";
- this.response.Contact = "Andrew Arnott";
- this.response.Reference = "http://blog.nerdbank.net/";
-
- MessageSerializer serializer = MessageSerializer.Get(this.response.GetType());
- var fields = serializer.Serialize(this.response);
- Assert.AreEqual(Protocol.OpenId2Namespace, fields["openid.ns"]);
- Assert.AreEqual("Some Error", fields["openid.error"]);
- Assert.AreEqual("Andrew Arnott", fields["openid.contact"]);
- Assert.AreEqual("http://blog.nerdbank.net/", fields["openid.reference"]);
- }
- }
+//----------------------------------------------------------------------- +// <copyright file="IndirectErrorResponseTests.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.OpenId.Messages { + using System; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OpenId; + using DotNetOpenAuth.OpenId.Messages; + using DotNetOpenAuth.OpenId.RelyingParty; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class IndirectErrorResponseTests : OpenIdTestBase { + private IndirectErrorResponse response; + + [TestInitialize] + public void Setup() { + CheckIdRequest request = new CheckIdRequest(Protocol.V20.Version, ProviderUri, AuthenticationRequestMode.Immediate); + request.ReturnTo = RPUri; + this.response = new IndirectErrorResponse(request); + } + + [TestMethod] + public void Ctor() { + Assert.AreEqual(RPUri, this.response.Recipient); + } + + [TestMethod] + public void ParameterNames() { + this.response.ErrorMessage = "Some Error"; + this.response.Contact = "Andrew Arnott"; + this.response.Reference = "http://blog.nerdbank.net/"; + + MessageSerializer serializer = MessageSerializer.Get(this.response.GetType()); + var fields = serializer.Serialize(this.response); + Assert.AreEqual(Protocol.OpenId2Namespace, fields["openid.ns"]); + Assert.AreEqual("Some Error", fields["openid.error"]); + Assert.AreEqual("Andrew Arnott", fields["openid.contact"]); + Assert.AreEqual("http://blog.nerdbank.net/", fields["openid.reference"]); + } + } }
\ No newline at end of file diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj index fa89999..994548a 100644 --- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj +++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj @@ -1,308 +1,308 @@ -<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>DotNetOpenAuth</RootNamespace>
- <AssemblyName>DotNetOpenAuth</AssemblyName>
- <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>..\..\bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
- <DocumentationFile>..\..\bin\Debug\DotNetOpenAuth.xml</DocumentationFile>
- <RunCodeAnalysis>false</RunCodeAnalysis>
- <CodeAnalysisRules>-Microsoft.Design#CA1054;-Microsoft.Design#CA1056;-Microsoft.Design#CA1055</CodeAnalysisRules>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>..\..\bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
- <DocumentationFile>..\..\bin\debug\DotNetOpenAuth.xml</DocumentationFile>
- <RunCodeAnalysis>true</RunCodeAnalysis>
- <CodeAnalysisRules>-Microsoft.Design#CA1054;-Microsoft.Design#CA1056;-Microsoft.Design#CA1055</CodeAnalysisRules>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Sign)' == 'true' ">
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\official-build-key.pfx</AssemblyOriginatorKeyFile>
- <DefineConstants>$(DefineConstants);StrongNameSigned</DefineConstants>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\lib\log4net.dll</HintPath>
- </Reference>
- <Reference Include="System" />
- <Reference Include="System.configuration" />
- <Reference Include="System.Core">
- <RequiredTargetFramework>3.5</RequiredTargetFramework>
- </Reference>
- <Reference Include="System.Data" />
- <Reference Include="System.ServiceModel">
- <RequiredTargetFramework>3.0</RequiredTargetFramework>
- </Reference>
- <Reference Include="System.Web" />
- <Reference Include="System.XML" />
- <Reference Include="System.Xml.Linq">
- <RequiredTargetFramework>3.5</RequiredTargetFramework>
- </Reference>
- </ItemGroup>
- <ItemGroup>
- <Compile Include="Configuration\ProviderSection.cs" />
- <Compile Include="Configuration\ProviderSecuritySettingsElement.cs" />
- <Compile Include="Configuration\RelyingPartySection.cs" />
- <Compile Include="Configuration\RelyingPartySecuritySettingsElement.cs" />
- <Compile Include="Configuration\TypeConfigurationElement.cs" />
- <Compile Include="Configuration\UntrustedWebRequestSection.cs" />
- <Compile Include="Configuration\HostNameOrRegexCollection.cs" />
- <Compile Include="Configuration\HostNameElement.cs" />
- <Compile Include="Messaging\IExtensionMessage.cs" />
- <Compile Include="Messaging\IMessage.cs" />
- <Compile Include="Messaging\DirectWebResponse.cs" />
- <Compile Include="Messaging\IDirectResponseProtocolMessage.cs" />
- <Compile Include="Messaging\EmptyDictionary.cs" />
- <Compile Include="Messaging\EmptyEnumerator.cs" />
- <Compile Include="Messaging\EmptyList.cs" />
- <Compile Include="Messaging\ErrorUtilities.cs" />
- <Compile Include="Messaging\IDirectSslWebRequestHandler.cs" />
- <Compile Include="Messaging\IProtocolMessageWithExtensions.cs" />
- <Compile Include="Messaging\InternalErrorException.cs" />
- <Compile Include="Messaging\Reflection\IMessagePartEncoder.cs" />
- <Compile Include="OAuth\ChannelElements\OAuthConsumerMessageFactory.cs" />
- <Compile Include="OAuth\ChannelElements\ITokenGenerator.cs" />
- <Compile Include="OAuth\ChannelElements\ITokenManager.cs" />
- <Compile Include="OAuth\ChannelElements\OAuthHttpMethodBindingElement.cs" />
- <Compile Include="OAuth\ChannelElements\PlaintextSigningBindingElement.cs" />
- <Compile Include="OAuth\ChannelElements\HmacSha1SigningBindingElement.cs" />
- <Compile Include="OAuth\ChannelElements\SigningBindingElementChain.cs" />
- <Compile Include="OAuth\ChannelElements\StandardTokenGenerator.cs" />
- <Compile Include="OAuth\ChannelElements\TokenType.cs" />
- <Compile Include="OAuth\ConsumerBase.cs" />
- <Compile Include="OAuth\DesktopConsumer.cs" />
- <Compile Include="GlobalSuppressions.cs" />
- <Compile Include="OAuth\Messages\ITokenSecretContainingMessage.cs" />
- <Compile Include="Messaging\ChannelEventArgs.cs" />
- <Compile Include="Messaging\ITamperProtectionChannelBindingElement.cs" />
- <Compile Include="OAuth\OAuthStrings.Designer.cs">
- <AutoGen>True</AutoGen>
- <DesignTime>True</DesignTime>
- <DependentUpon>OAuthStrings.resx</DependentUpon>
- </Compile>
- <Compile Include="OAuth\ServiceProviderDescription.cs" />
- <Compile Include="OAuth\Messages\ITokenContainingMessage.cs" />
- <Compile Include="OAuth\Messages\SignedMessageBase.cs" />
- <Compile Include="Messaging\Bindings\NonceMemoryStore.cs" />
- <Compile Include="OAuth\ChannelElements\SigningBindingElementBase.cs" />
- <Compile Include="OAuth\WebConsumer.cs" />
- <Compile Include="Messaging\IDirectWebRequestHandler.cs" />
- <Compile Include="OAuth\ChannelElements\ITamperResistantOAuthMessage.cs" />
- <Compile Include="OAuth\Messages\MessageBase.cs" />
- <Compile Include="OAuth\Messages\AuthorizedTokenRequest.cs" />
- <Compile Include="Messaging\Bindings\INonceStore.cs" />
- <Compile Include="Messaging\Bindings\StandardReplayProtectionBindingElement.cs" />
- <Compile Include="Messaging\MessagePartAttribute.cs" />
- <Compile Include="Messaging\MessageProtections.cs" />
- <Compile Include="Messaging\IChannelBindingElement.cs" />
- <Compile Include="Messaging\Bindings\ReplayedMessageException.cs" />
- <Compile Include="Messaging\Bindings\ExpiredMessageException.cs" />
- <Compile Include="Messaging\Bindings\InvalidSignatureException.cs" />
- <Compile Include="Messaging\Bindings\IReplayProtectedProtocolMessage.cs" />
- <Compile Include="Messaging\Bindings\IExpiringProtocolMessage.cs" />
- <Compile Include="OAuth\Messages\AccessProtectedResourceRequest.cs" />
- <Compile Include="OAuth\Messages\AuthorizedTokenResponse.cs" />
- <Compile Include="OAuth\Messages\UserAuthorizationResponse.cs" />
- <Compile Include="OAuth\Messages\UserAuthorizationRequest.cs" />
- <Compile Include="OAuth\Messages\UnauthorizedTokenResponse.cs" />
- <Compile Include="Messaging\Channel.cs" />
- <Compile Include="Messaging\HttpRequestInfo.cs" />
- <Compile Include="Messaging\IDirectedProtocolMessage.cs" />
- <Compile Include="Messaging\IMessageFactory.cs" />
- <Compile Include="Messaging\ITamperResistantProtocolMessage.cs" />
- <Compile Include="Messaging\MessageSerializer.cs" />
- <Compile Include="Messaging\MessagingStrings.Designer.cs">
- <AutoGen>True</AutoGen>
- <DesignTime>True</DesignTime>
- <DependentUpon>MessagingStrings.resx</DependentUpon>
- </Compile>
- <Compile Include="Messaging\MessagingUtilities.cs" />
- <Compile Include="Messaging\Bindings\StandardExpirationBindingElement.cs" />
- <Compile Include="Messaging\Reflection\ValueMapping.cs" />
- <Compile Include="Messaging\Reflection\MessageDescription.cs" />
- <Compile Include="Messaging\Reflection\MessageDictionary.cs" />
- <Compile Include="Messaging\Reflection\MessagePart.cs" />
- <Compile Include="Messaging\UnprotectedMessageException.cs" />
- <Compile Include="OAuth\ChannelElements\OAuthChannel.cs" />
- <Compile Include="Messaging\UserAgentResponse.cs" />
- <Compile Include="Messaging\IProtocolMessage.cs" />
- <Compile Include="Logger.cs" />
- <Compile Include="Loggers\ILog.cs" />
- <Compile Include="Loggers\Log4NetLogger.cs" />
- <Compile Include="Loggers\NoOpLogger.cs" />
- <Compile Include="Loggers\TraceLogger.cs" />
- <Compile Include="Messaging\HttpDeliveryMethods.cs" />
- <Compile Include="Messaging\MessageTransport.cs" />
- <Compile Include="OAuth\ChannelElements\OAuthServiceProviderMessageFactory.cs" />
- <Compile Include="Messaging\ProtocolException.cs" />
- <Compile Include="OpenId\Association.cs" />
- <Compile Include="OpenId\AssociationMemoryStore.cs" />
- <Compile Include="OpenId\Associations.cs" />
- <Compile Include="OpenId\ChannelElements\BackwardCompatibilityBindingElement.cs" />
- <Compile Include="OpenId\ChannelElements\ExtensionsBindingElement.cs" />
- <Compile Include="OpenId\ChannelElements\IOpenIdExtensionFactory.cs" />
- <Compile Include="OpenId\ChannelElements\IPrivateSecretStore.cs" />
- <Compile Include="OpenId\ChannelElements\ITamperResistantOpenIdMessage.cs" />
- <Compile Include="OpenId\ChannelElements\OriginalStringUriEncoder.cs" />
- <Compile Include="OpenId\ChannelElements\ReturnToNonceBindingElement.cs" />
- <Compile Include="OpenId\ChannelElements\SigningBindingElement.cs" />
- <Compile Include="OpenId\ChannelElements\KeyValueFormEncoding.cs" />
- <Compile Include="OpenId\ChannelElements\OpenIdChannel.cs" />
- <Compile Include="OpenId\ChannelElements\OpenIdMessageFactory.cs" />
- <Compile Include="OpenId\ChannelElements\ReturnToSignatureBindingElement.cs" />
- <Compile Include="OpenId\Configuration.cs" />
- <Compile Include="OpenId\Extensions\AliasManager.cs" />
- <Compile Include="OpenId\Extensions\ExtensionBase.cs" />
- <Compile Include="OpenId\Extensions\ExtensionArgumentsManager.cs" />
- <Compile Include="OpenId\Extensions\OpenIdExtensionFactory.cs" />
- <Compile Include="OpenId\Extensions\SimpleRegistration\ClaimsRequest.cs" />
- <Compile Include="OpenId\Extensions\SimpleRegistration\ClaimsResponse.cs" />
- <Compile Include="OpenId\Extensions\SimpleRegistration\Constants.cs" />
- <Compile Include="OpenId\Extensions\SimpleRegistration\DemandLevel.cs" />
- <Compile Include="OpenId\Extensions\SimpleRegistration\Gender.cs" />
- <Compile Include="OpenId\Identifier.cs" />
- <Compile Include="OpenId\Messages\CheckAuthenticationRequest.cs" />
- <Compile Include="OpenId\Messages\CheckAuthenticationResponse.cs" />
- <Compile Include="OpenId\Messages\CheckIdRequest.cs" />
- <Compile Include="OpenId\Messages\IndirectResponseBase.cs" />
- <Compile Include="OpenId\Messages\IndirectSignedResponse.cs" />
- <Compile Include="OpenId\Messages\IOpenIdMessageExtension.cs" />
- <Compile Include="OpenId\Messages\NegativeAssertionResponse.cs" />
- <Compile Include="OpenId\Messages\PositiveAssertionResponse.cs" />
- <Compile Include="OpenId\Messages\SignedResponseRequest.cs" />
- <Compile Include="OpenId\NoDiscoveryIdentifier.cs" />
- <Compile Include="OpenId\OpenIdUtilities.cs" />
- <Compile Include="OpenId\PrivateSecretMemoryStore.cs" />
- <Compile Include="OpenId\Realm.cs" />
- <Compile Include="OpenId\RelyingPartyDescription.cs" />
- <Compile Include="OpenId\DiffieHellmanUtilities.cs" />
- <Compile Include="OpenId\DiffieHellman\DHKeyGeneration.cs" />
- <Compile Include="OpenId\DiffieHellman\DHParameters.cs" />
- <Compile Include="OpenId\DiffieHellman\DiffieHellman.cs" />
- <Compile Include="OpenId\DiffieHellman\DiffieHellmanManaged.cs" />
- <Compile Include="OpenId\DiffieHellman\mono\BigInteger.cs" />
- <Compile Include="OpenId\DiffieHellman\mono\ConfidenceFactor.cs" />
- <Compile Include="OpenId\DiffieHellman\mono\NextPrimeFinder.cs" />
- <Compile Include="OpenId\DiffieHellman\mono\PrimalityTests.cs" />
- <Compile Include="OpenId\DiffieHellman\mono\PrimeGeneratorBase.cs" />
- <Compile Include="OpenId\DiffieHellman\mono\SequentialSearchPrimeGeneratorBase.cs" />
- <Compile Include="OpenId\HmacShaAssociation.cs" />
- <Compile Include="OpenId\IAssociationStore.cs" />
- <Compile Include="OpenId\Messages\AssociateUnencryptedRequest.cs" />
- <Compile Include="OpenId\Provider\OpenIdProvider.cs" />
- <Compile Include="OpenId\Messages\AssociateDiffieHellmanRequest.cs" />
- <Compile Include="OpenId\Messages\AssociateDiffieHellmanResponse.cs" />
- <Compile Include="OpenId\Messages\AssociateRequest.cs" />
- <Compile Include="OpenId\Messages\AssociateSuccessfulResponse.cs" />
- <Compile Include="OpenId\Messages\AssociateUnencryptedResponse.cs" />
- <Compile Include="OpenId\Messages\AssociateUnsuccessfulResponse.cs" />
- <Compile Include="OpenId\Messages\IndirectErrorResponse.cs" />
- <Compile Include="OpenId\Messages\DirectErrorResponse.cs" />
- <Compile Include="OpenId\Messages\RequestBase.cs" />
- <Compile Include="OpenId\Messages\DirectResponseBase.cs" />
- <Compile Include="OpenId\RelyingParty\AuthenticationRequestMode.cs" />
- <Compile Include="OpenId\RelyingParty\IProviderEndpoint.cs" />
- <Compile Include="OpenId\RelyingParty\IXrdsProviderEndpoint.cs" />
- <Compile Include="OpenId\RelyingParty\OpenIdRelyingParty.cs" />
- <Compile Include="OpenId\OpenIdStrings.Designer.cs">
- <DependentUpon>OpenIdStrings.resx</DependentUpon>
- <DesignTime>True</DesignTime>
- <AutoGen>True</AutoGen>
- </Compile>
- <Compile Include="OpenId\Protocol.cs" />
- <Compile Include="OpenId\ProviderEndpointDescription.cs" />
- <Compile Include="OpenId\Provider\ProviderSecuritySettings.cs" />
- <Compile Include="OpenId\RelyingParty\RelyingPartySecuritySettings.cs" />
- <Compile Include="OpenId\RelyingParty\ServiceEndpoint.cs" />
- <Compile Include="OpenId\OpenIdXrdsHelper.cs" />
- <Compile Include="OpenId\SecuritySettings.cs" />
- <Compile Include="Messaging\UntrustedWebRequestHandler.cs" />
- <Compile Include="OpenId\UriIdentifier.cs" />
- <Compile Include="OpenId\XriIdentifier.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="OAuth\Messages\UnauthorizedTokenRequest.cs" />
- <Compile Include="OAuth\ChannelElements\RsaSha1SigningBindingElement.cs" />
- <Compile Include="Messaging\StandardWebRequestHandler.cs" />
- <Compile Include="Messaging\MessageReceivingEndpoint.cs" />
- <Compile Include="Util.cs" />
- <Compile Include="OAuth\Protocol.cs" />
- <Compile Include="OAuth\ServiceProvider.cs" />
- <Compile Include="Strings.Designer.cs">
- <AutoGen>True</AutoGen>
- <DesignTime>True</DesignTime>
- <DependentUpon>Strings.resx</DependentUpon>
- </Compile>
- <Compile Include="UriUtil.cs" />
- <Compile Include="Xrds\XrdsStrings.Designer.cs">
- <AutoGen>True</AutoGen>
- <DesignTime>True</DesignTime>
- <DependentUpon>XrdsStrings.resx</DependentUpon>
- </Compile>
- <Compile Include="Yadis\ContentTypes.cs" />
- <Compile Include="Yadis\DiscoveryResult.cs" />
- <Compile Include="Yadis\HtmlParser.cs" />
- <Compile Include="Xrds\ServiceElement.cs" />
- <Compile Include="Xrds\TypeElement.cs" />
- <Compile Include="Xrds\UriElement.cs" />
- <Compile Include="Xrds\XrdElement.cs" />
- <Compile Include="Xrds\XrdsDocument.cs" />
- <Compile Include="Xrds\XrdsNode.cs" />
- <Compile Include="Yadis\Yadis.cs" />
- </ItemGroup>
- <ItemGroup>
- <None Include="OAuth\ClassDiagram.cd" />
- <None Include="OAuth\Messages\OAuth Messages.cd" />
- <None Include="Messaging\Bindings\Bindings.cd" />
- <None Include="Messaging\Exceptions.cd" />
- <None Include="Messaging\Messaging.cd" />
- </ItemGroup>
- <ItemGroup>
- <EmbeddedResource Include="Messaging\MessagingStrings.resx">
- <Generator>ResXFileCodeGenerator</Generator>
- <LastGenOutput>MessagingStrings.Designer.cs</LastGenOutput>
- </EmbeddedResource>
- <EmbeddedResource Include="OAuth\OAuthStrings.resx">
- <Generator>ResXFileCodeGenerator</Generator>
- <LastGenOutput>OAuthStrings.Designer.cs</LastGenOutput>
- </EmbeddedResource>
- <EmbeddedResource Include="OpenId\OpenIdStrings.resx">
- <Generator>ResXFileCodeGenerator</Generator>
- <LastGenOutput>OpenIdStrings.Designer.cs</LastGenOutput>
- </EmbeddedResource>
- <EmbeddedResource Include="Strings.resx">
- <Generator>ResXFileCodeGenerator</Generator>
- <LastGenOutput>Strings.Designer.cs</LastGenOutput>
- <SubType>Designer</SubType>
- </EmbeddedResource>
- <EmbeddedResource Include="Xrds\XrdsStrings.resx">
- <Generator>ResXFileCodeGenerator</Generator>
- <LastGenOutput>XrdsStrings.Designer.cs</LastGenOutput>
- </EmbeddedResource>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="..\..\tools\DotNetOpenAuth.Versioning.targets" />
+<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.30729</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>DotNetOpenAuth</RootNamespace> + <AssemblyName>DotNetOpenAuth</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <AllowUnsafeBlocks>false</AllowUnsafeBlocks> + <DocumentationFile>..\..\bin\Debug\DotNetOpenAuth.xml</DocumentationFile> + <RunCodeAnalysis>false</RunCodeAnalysis> + <CodeAnalysisRules>-Microsoft.Design#CA1054;-Microsoft.Design#CA1056;-Microsoft.Design#CA1055</CodeAnalysisRules> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>..\..\bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <AllowUnsafeBlocks>false</AllowUnsafeBlocks> + <DocumentationFile>..\..\bin\debug\DotNetOpenAuth.xml</DocumentationFile> + <RunCodeAnalysis>true</RunCodeAnalysis> + <CodeAnalysisRules>-Microsoft.Design#CA1054;-Microsoft.Design#CA1056;-Microsoft.Design#CA1055</CodeAnalysisRules> + </PropertyGroup> + <PropertyGroup Condition=" '$(Sign)' == 'true' "> + <SignAssembly>true</SignAssembly> + <AssemblyOriginatorKeyFile>..\official-build-key.pfx</AssemblyOriginatorKeyFile> + <DefineConstants>$(DefineConstants);StrongNameSigned</DefineConstants> + </PropertyGroup> + <ItemGroup> + <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\lib\log4net.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.configuration" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data" /> + <Reference Include="System.ServiceModel"> + <RequiredTargetFramework>3.0</RequiredTargetFramework> + </Reference> + <Reference Include="System.Web" /> + <Reference Include="System.XML" /> + <Reference Include="System.Xml.Linq"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Configuration\ProviderSection.cs" /> + <Compile Include="Configuration\ProviderSecuritySettingsElement.cs" /> + <Compile Include="Configuration\RelyingPartySection.cs" /> + <Compile Include="Configuration\RelyingPartySecuritySettingsElement.cs" /> + <Compile Include="Configuration\TypeConfigurationElement.cs" /> + <Compile Include="Configuration\UntrustedWebRequestSection.cs" /> + <Compile Include="Configuration\HostNameOrRegexCollection.cs" /> + <Compile Include="Configuration\HostNameElement.cs" /> + <Compile Include="Messaging\IExtensionMessage.cs" /> + <Compile Include="Messaging\IMessage.cs" /> + <Compile Include="Messaging\DirectWebResponse.cs" /> + <Compile Include="Messaging\IDirectResponseProtocolMessage.cs" /> + <Compile Include="Messaging\EmptyDictionary.cs" /> + <Compile Include="Messaging\EmptyEnumerator.cs" /> + <Compile Include="Messaging\EmptyList.cs" /> + <Compile Include="Messaging\ErrorUtilities.cs" /> + <Compile Include="Messaging\IDirectSslWebRequestHandler.cs" /> + <Compile Include="Messaging\IProtocolMessageWithExtensions.cs" /> + <Compile Include="Messaging\InternalErrorException.cs" /> + <Compile Include="Messaging\Reflection\IMessagePartEncoder.cs" /> + <Compile Include="OAuth\ChannelElements\OAuthConsumerMessageFactory.cs" /> + <Compile Include="OAuth\ChannelElements\ITokenGenerator.cs" /> + <Compile Include="OAuth\ChannelElements\ITokenManager.cs" /> + <Compile Include="OAuth\ChannelElements\OAuthHttpMethodBindingElement.cs" /> + <Compile Include="OAuth\ChannelElements\PlaintextSigningBindingElement.cs" /> + <Compile Include="OAuth\ChannelElements\HmacSha1SigningBindingElement.cs" /> + <Compile Include="OAuth\ChannelElements\SigningBindingElementChain.cs" /> + <Compile Include="OAuth\ChannelElements\StandardTokenGenerator.cs" /> + <Compile Include="OAuth\ChannelElements\TokenType.cs" /> + <Compile Include="OAuth\ConsumerBase.cs" /> + <Compile Include="OAuth\DesktopConsumer.cs" /> + <Compile Include="GlobalSuppressions.cs" /> + <Compile Include="OAuth\Messages\ITokenSecretContainingMessage.cs" /> + <Compile Include="Messaging\ChannelEventArgs.cs" /> + <Compile Include="Messaging\ITamperProtectionChannelBindingElement.cs" /> + <Compile Include="OAuth\OAuthStrings.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>OAuthStrings.resx</DependentUpon> + </Compile> + <Compile Include="OAuth\ServiceProviderDescription.cs" /> + <Compile Include="OAuth\Messages\ITokenContainingMessage.cs" /> + <Compile Include="OAuth\Messages\SignedMessageBase.cs" /> + <Compile Include="Messaging\Bindings\NonceMemoryStore.cs" /> + <Compile Include="OAuth\ChannelElements\SigningBindingElementBase.cs" /> + <Compile Include="OAuth\WebConsumer.cs" /> + <Compile Include="Messaging\IDirectWebRequestHandler.cs" /> + <Compile Include="OAuth\ChannelElements\ITamperResistantOAuthMessage.cs" /> + <Compile Include="OAuth\Messages\MessageBase.cs" /> + <Compile Include="OAuth\Messages\AuthorizedTokenRequest.cs" /> + <Compile Include="Messaging\Bindings\INonceStore.cs" /> + <Compile Include="Messaging\Bindings\StandardReplayProtectionBindingElement.cs" /> + <Compile Include="Messaging\MessagePartAttribute.cs" /> + <Compile Include="Messaging\MessageProtections.cs" /> + <Compile Include="Messaging\IChannelBindingElement.cs" /> + <Compile Include="Messaging\Bindings\ReplayedMessageException.cs" /> + <Compile Include="Messaging\Bindings\ExpiredMessageException.cs" /> + <Compile Include="Messaging\Bindings\InvalidSignatureException.cs" /> + <Compile Include="Messaging\Bindings\IReplayProtectedProtocolMessage.cs" /> + <Compile Include="Messaging\Bindings\IExpiringProtocolMessage.cs" /> + <Compile Include="OAuth\Messages\AccessProtectedResourceRequest.cs" /> + <Compile Include="OAuth\Messages\AuthorizedTokenResponse.cs" /> + <Compile Include="OAuth\Messages\UserAuthorizationResponse.cs" /> + <Compile Include="OAuth\Messages\UserAuthorizationRequest.cs" /> + <Compile Include="OAuth\Messages\UnauthorizedTokenResponse.cs" /> + <Compile Include="Messaging\Channel.cs" /> + <Compile Include="Messaging\HttpRequestInfo.cs" /> + <Compile Include="Messaging\IDirectedProtocolMessage.cs" /> + <Compile Include="Messaging\IMessageFactory.cs" /> + <Compile Include="Messaging\ITamperResistantProtocolMessage.cs" /> + <Compile Include="Messaging\MessageSerializer.cs" /> + <Compile Include="Messaging\MessagingStrings.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>MessagingStrings.resx</DependentUpon> + </Compile> + <Compile Include="Messaging\MessagingUtilities.cs" /> + <Compile Include="Messaging\Bindings\StandardExpirationBindingElement.cs" /> + <Compile Include="Messaging\Reflection\ValueMapping.cs" /> + <Compile Include="Messaging\Reflection\MessageDescription.cs" /> + <Compile Include="Messaging\Reflection\MessageDictionary.cs" /> + <Compile Include="Messaging\Reflection\MessagePart.cs" /> + <Compile Include="Messaging\UnprotectedMessageException.cs" /> + <Compile Include="OAuth\ChannelElements\OAuthChannel.cs" /> + <Compile Include="Messaging\UserAgentResponse.cs" /> + <Compile Include="Messaging\IProtocolMessage.cs" /> + <Compile Include="Logger.cs" /> + <Compile Include="Loggers\ILog.cs" /> + <Compile Include="Loggers\Log4NetLogger.cs" /> + <Compile Include="Loggers\NoOpLogger.cs" /> + <Compile Include="Loggers\TraceLogger.cs" /> + <Compile Include="Messaging\HttpDeliveryMethods.cs" /> + <Compile Include="Messaging\MessageTransport.cs" /> + <Compile Include="OAuth\ChannelElements\OAuthServiceProviderMessageFactory.cs" /> + <Compile Include="Messaging\ProtocolException.cs" /> + <Compile Include="OpenId\Association.cs" /> + <Compile Include="OpenId\AssociationMemoryStore.cs" /> + <Compile Include="OpenId\Associations.cs" /> + <Compile Include="OpenId\ChannelElements\BackwardCompatibilityBindingElement.cs" /> + <Compile Include="OpenId\ChannelElements\ExtensionsBindingElement.cs" /> + <Compile Include="OpenId\ChannelElements\IOpenIdExtensionFactory.cs" /> + <Compile Include="OpenId\ChannelElements\IPrivateSecretStore.cs" /> + <Compile Include="OpenId\ChannelElements\ITamperResistantOpenIdMessage.cs" /> + <Compile Include="OpenId\ChannelElements\OriginalStringUriEncoder.cs" /> + <Compile Include="OpenId\ChannelElements\ReturnToNonceBindingElement.cs" /> + <Compile Include="OpenId\ChannelElements\SigningBindingElement.cs" /> + <Compile Include="OpenId\ChannelElements\KeyValueFormEncoding.cs" /> + <Compile Include="OpenId\ChannelElements\OpenIdChannel.cs" /> + <Compile Include="OpenId\ChannelElements\OpenIdMessageFactory.cs" /> + <Compile Include="OpenId\ChannelElements\ReturnToSignatureBindingElement.cs" /> + <Compile Include="OpenId\Configuration.cs" /> + <Compile Include="OpenId\Extensions\AliasManager.cs" /> + <Compile Include="OpenId\Extensions\ExtensionBase.cs" /> + <Compile Include="OpenId\Extensions\ExtensionArgumentsManager.cs" /> + <Compile Include="OpenId\Extensions\OpenIdExtensionFactory.cs" /> + <Compile Include="OpenId\Extensions\SimpleRegistration\ClaimsRequest.cs" /> + <Compile Include="OpenId\Extensions\SimpleRegistration\ClaimsResponse.cs" /> + <Compile Include="OpenId\Extensions\SimpleRegistration\Constants.cs" /> + <Compile Include="OpenId\Extensions\SimpleRegistration\DemandLevel.cs" /> + <Compile Include="OpenId\Extensions\SimpleRegistration\Gender.cs" /> + <Compile Include="OpenId\Identifier.cs" /> + <Compile Include="OpenId\Messages\CheckAuthenticationRequest.cs" /> + <Compile Include="OpenId\Messages\CheckAuthenticationResponse.cs" /> + <Compile Include="OpenId\Messages\CheckIdRequest.cs" /> + <Compile Include="OpenId\Messages\IndirectResponseBase.cs" /> + <Compile Include="OpenId\Messages\IndirectSignedResponse.cs" /> + <Compile Include="OpenId\Messages\IOpenIdMessageExtension.cs" /> + <Compile Include="OpenId\Messages\NegativeAssertionResponse.cs" /> + <Compile Include="OpenId\Messages\PositiveAssertionResponse.cs" /> + <Compile Include="OpenId\Messages\SignedResponseRequest.cs" /> + <Compile Include="OpenId\NoDiscoveryIdentifier.cs" /> + <Compile Include="OpenId\OpenIdUtilities.cs" /> + <Compile Include="OpenId\PrivateSecretMemoryStore.cs" /> + <Compile Include="OpenId\Realm.cs" /> + <Compile Include="OpenId\RelyingPartyDescription.cs" /> + <Compile Include="OpenId\DiffieHellmanUtilities.cs" /> + <Compile Include="OpenId\DiffieHellman\DHKeyGeneration.cs" /> + <Compile Include="OpenId\DiffieHellman\DHParameters.cs" /> + <Compile Include="OpenId\DiffieHellman\DiffieHellman.cs" /> + <Compile Include="OpenId\DiffieHellman\DiffieHellmanManaged.cs" /> + <Compile Include="OpenId\DiffieHellman\mono\BigInteger.cs" /> + <Compile Include="OpenId\DiffieHellman\mono\ConfidenceFactor.cs" /> + <Compile Include="OpenId\DiffieHellman\mono\NextPrimeFinder.cs" /> + <Compile Include="OpenId\DiffieHellman\mono\PrimalityTests.cs" /> + <Compile Include="OpenId\DiffieHellman\mono\PrimeGeneratorBase.cs" /> + <Compile Include="OpenId\DiffieHellman\mono\SequentialSearchPrimeGeneratorBase.cs" /> + <Compile Include="OpenId\HmacShaAssociation.cs" /> + <Compile Include="OpenId\IAssociationStore.cs" /> + <Compile Include="OpenId\Messages\AssociateUnencryptedRequest.cs" /> + <Compile Include="OpenId\Provider\OpenIdProvider.cs" /> + <Compile Include="OpenId\Messages\AssociateDiffieHellmanRequest.cs" /> + <Compile Include="OpenId\Messages\AssociateDiffieHellmanResponse.cs" /> + <Compile Include="OpenId\Messages\AssociateRequest.cs" /> + <Compile Include="OpenId\Messages\AssociateSuccessfulResponse.cs" /> + <Compile Include="OpenId\Messages\AssociateUnencryptedResponse.cs" /> + <Compile Include="OpenId\Messages\AssociateUnsuccessfulResponse.cs" /> + <Compile Include="OpenId\Messages\IndirectErrorResponse.cs" /> + <Compile Include="OpenId\Messages\DirectErrorResponse.cs" /> + <Compile Include="OpenId\Messages\RequestBase.cs" /> + <Compile Include="OpenId\Messages\DirectResponseBase.cs" /> + <Compile Include="OpenId\RelyingParty\AuthenticationRequestMode.cs" /> + <Compile Include="OpenId\RelyingParty\IProviderEndpoint.cs" /> + <Compile Include="OpenId\RelyingParty\IXrdsProviderEndpoint.cs" /> + <Compile Include="OpenId\RelyingParty\OpenIdRelyingParty.cs" /> + <Compile Include="OpenId\OpenIdStrings.Designer.cs"> + <DependentUpon>OpenIdStrings.resx</DependentUpon> + <DesignTime>True</DesignTime> + <AutoGen>True</AutoGen> + </Compile> + <Compile Include="OpenId\Protocol.cs" /> + <Compile Include="OpenId\ProviderEndpointDescription.cs" /> + <Compile Include="OpenId\Provider\ProviderSecuritySettings.cs" /> + <Compile Include="OpenId\RelyingParty\RelyingPartySecuritySettings.cs" /> + <Compile Include="OpenId\RelyingParty\ServiceEndpoint.cs" /> + <Compile Include="OpenId\OpenIdXrdsHelper.cs" /> + <Compile Include="OpenId\SecuritySettings.cs" /> + <Compile Include="Messaging\UntrustedWebRequestHandler.cs" /> + <Compile Include="OpenId\UriIdentifier.cs" /> + <Compile Include="OpenId\XriIdentifier.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="OAuth\Messages\UnauthorizedTokenRequest.cs" /> + <Compile Include="OAuth\ChannelElements\RsaSha1SigningBindingElement.cs" /> + <Compile Include="Messaging\StandardWebRequestHandler.cs" /> + <Compile Include="Messaging\MessageReceivingEndpoint.cs" /> + <Compile Include="Util.cs" /> + <Compile Include="OAuth\Protocol.cs" /> + <Compile Include="OAuth\ServiceProvider.cs" /> + <Compile Include="Strings.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Strings.resx</DependentUpon> + </Compile> + <Compile Include="UriUtil.cs" /> + <Compile Include="Xrds\XrdsStrings.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>XrdsStrings.resx</DependentUpon> + </Compile> + <Compile Include="Yadis\ContentTypes.cs" /> + <Compile Include="Yadis\DiscoveryResult.cs" /> + <Compile Include="Yadis\HtmlParser.cs" /> + <Compile Include="Xrds\ServiceElement.cs" /> + <Compile Include="Xrds\TypeElement.cs" /> + <Compile Include="Xrds\UriElement.cs" /> + <Compile Include="Xrds\XrdElement.cs" /> + <Compile Include="Xrds\XrdsDocument.cs" /> + <Compile Include="Xrds\XrdsNode.cs" /> + <Compile Include="Yadis\Yadis.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="OAuth\ClassDiagram.cd" /> + <None Include="OAuth\Messages\OAuth Messages.cd" /> + <None Include="Messaging\Bindings\Bindings.cd" /> + <None Include="Messaging\Exceptions.cd" /> + <None Include="Messaging\Messaging.cd" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Messaging\MessagingStrings.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>MessagingStrings.Designer.cs</LastGenOutput> + </EmbeddedResource> + <EmbeddedResource Include="OAuth\OAuthStrings.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>OAuthStrings.Designer.cs</LastGenOutput> + </EmbeddedResource> + <EmbeddedResource Include="OpenId\OpenIdStrings.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>OpenIdStrings.Designer.cs</LastGenOutput> + </EmbeddedResource> + <EmbeddedResource Include="Strings.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Strings.Designer.cs</LastGenOutput> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="Xrds\XrdsStrings.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>XrdsStrings.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="..\..\tools\DotNetOpenAuth.Versioning.targets" /> </Project>
\ No newline at end of file diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs index 4191f28..6234153 100644 --- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs +++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs @@ -1,471 +1,471 @@ -//-----------------------------------------------------------------------
-// <copyright file="MessagingUtilities.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.Messaging {
- using System;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using System.Diagnostics.CodeAnalysis;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Security.Cryptography;
- using System.Text;
- using System.Web;
- using DotNetOpenAuth.Messaging.Reflection;
-
- /// <summary>
- /// A grab-bag of utility methods useful for the channel stack of the protocol.
- /// </summary>
- public static class MessagingUtilities {
- /// <summary>
- /// The cryptographically strong random data generator used for creating secrets.
- /// </summary>
- /// <remarks>The random number generator is thread-safe.</remarks>
- internal static readonly RandomNumberGenerator CryptoRandomDataGenerator = new RNGCryptoServiceProvider();
-
- /// <summary>
- /// Gets the original request URL, as seen from the browser before any URL rewrites on the server if any.
- /// Cookieless session directory (if applicable) is also included.
- /// </summary>
- /// <returns>The URL in the user agent's Location bar.</returns>
- [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "The Uri merging requires use of a string value.")]
- [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Expensive call should not be a property.")]
- public static Uri GetRequestUrlFromContext() {
- HttpContext context = HttpContext.Current;
- if (context == null) {
- throw new InvalidOperationException(MessagingStrings.CurrentHttpContextRequired);
- }
-
- // We use Request.Url for the full path to the server, and modify it
- // with Request.RawUrl to capture both the cookieless session "directory" if it exists
- // and the original path in case URL rewriting is going on. We don't want to be
- // fooled by URL rewriting because we're comparing the actual URL with what's in
- // the return_to parameter in some cases.
- // Response.ApplyAppPathModifier(builder.Path) would have worked for the cookieless
- // session, but not the URL rewriting problem.
- return new Uri(context.Request.Url, context.Request.RawUrl);
- }
-
- /// <summary>
- /// Strips any and all URI query parameters that start with some prefix.
- /// </summary>
- /// <param name="uri">The URI that may have a query with parameters to remove.</param>
- /// <param name="prefix">The prefix for parameters to remove.</param>
- /// <returns>Either a new Uri with the parameters removed if there were any to remove, or the same Uri instance if no parameters needed to be removed.</returns>
- public static Uri StripQueryArgumentsWithPrefix(this Uri uri, string prefix) {
- NameValueCollection queryArgs = HttpUtility.ParseQueryString(uri.Query);
- var matchingKeys = queryArgs.Keys.OfType<string>().Where(key => key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)).ToList();
- if (matchingKeys.Count > 0) {
- UriBuilder builder = new UriBuilder(uri);
- foreach (string key in matchingKeys) {
- queryArgs.Remove(key);
- }
- builder.Query = CreateQueryString(queryArgs.ToDictionary());
- return builder.Uri;
- } else {
- return uri;
- }
- }
-
- /// <summary>
- /// Gets a cryptographically strong random sequence of values.
- /// </summary>
- /// <param name="length">The length of the sequence to generate.</param>
- /// <returns>The generated values, which may contain zeros.</returns>
- internal static byte[] GetCryptoRandomData(int length) {
- byte[] buffer = new byte[length];
- CryptoRandomDataGenerator.GetBytes(buffer);
- return buffer;
- }
-
- /// <summary>
- /// Gets a cryptographically strong random sequence of values.
- /// </summary>
- /// <param name="binaryLength">The length of the byte sequence to generate.</param>
- /// <returns>A base64 encoding of the generated random data,
- /// whose length in characters will likely be greater than <paramref name="binaryLength"/>.</returns>
- internal static string GetCryptoRandomDataAsBase64(int binaryLength) {
- byte[] uniq_bytes = GetCryptoRandomData(binaryLength);
- string uniq = Convert.ToBase64String(uniq_bytes);
- return uniq;
- }
-
- /// <summary>
- /// Adds a set of HTTP headers to an <see cref="HttpResponse"/> instance,
- /// taking care to set some headers to the appropriate properties of
- /// <see cref="HttpResponse" />
- /// </summary>
- /// <param name="headers">The headers to add.</param>
- /// <param name="response">The <see cref="HttpResponse"/> instance to set the appropriate values to.</param>
- internal static void ApplyHeadersToResponse(WebHeaderCollection headers, HttpResponse response) {
- if (headers == null) {
- throw new ArgumentNullException("headers");
- }
- if (response == null) {
- throw new ArgumentNullException("response");
- }
- foreach (string headerName in headers) {
- switch (headerName) {
- case "Content-Type":
- response.ContentType = headers[HttpResponseHeader.ContentType];
- break;
-
- // Add more special cases here as necessary.
- default:
- response.AddHeader(headerName, headers[headerName]);
- break;
- }
- }
- }
-
- /// <summary>
- /// Copies the contents of one stream to another.
- /// </summary>
- /// <param name="copyFrom">The stream to copy from, at the position where copying should begin.</param>
- /// <param name="copyTo">The stream to copy to, at the position where bytes should be written.</param>
- /// <returns>The total number of bytes copied.</returns>
- /// <remarks>
- /// Copying begins at the streams' current positions.
- /// The positions are NOT reset after copying is complete.
- /// </remarks>
- internal static int CopyTo(this Stream copyFrom, Stream copyTo) {
- return CopyTo(copyFrom, copyTo, int.MaxValue);
- }
-
- /// <summary>
- /// Copies the contents of one stream to another.
- /// </summary>
- /// <param name="copyFrom">The stream to copy from, at the position where copying should begin.</param>
- /// <param name="copyTo">The stream to copy to, at the position where bytes should be written.</param>
- /// <param name="maximumBytesToCopy">The maximum bytes to copy.</param>
- /// <returns>The total number of bytes copied.</returns>
- /// <remarks>
- /// Copying begins at the streams' current positions.
- /// The positions are NOT reset after copying is complete.
- /// </remarks>
- internal static int CopyTo(this Stream copyFrom, Stream copyTo, int maximumBytesToCopy) {
- ErrorUtilities.VerifyArgumentNotNull(copyFrom, "copyFrom");
- ErrorUtilities.VerifyArgumentNotNull(copyTo, "copyTo");
- ErrorUtilities.VerifyArgument(copyFrom.CanRead, MessagingStrings.StreamUnreadable);
- ErrorUtilities.VerifyArgument(copyTo.CanWrite, MessagingStrings.StreamUnwritable, "copyTo");
-
- byte[] buffer = new byte[1024];
- int readBytes;
- int totalCopiedBytes = 0;
- while ((readBytes = copyFrom.Read(buffer, 0, Math.Min(1024, maximumBytesToCopy))) > 0) {
- int writeBytes = Math.Min(maximumBytesToCopy, readBytes);
- copyTo.Write(buffer, 0, writeBytes);
- totalCopiedBytes += writeBytes;
- maximumBytesToCopy -= writeBytes;
- }
-
- return totalCopiedBytes;
- }
-
- /// <summary>
- /// Creates a snapshot of some stream so it is seekable, and the original can be closed.
- /// </summary>
- /// <param name="copyFrom">The stream to copy bytes from.</param>
- /// <returns>A seekable stream with the same contents as the original.</returns>
- internal static Stream CreateSnapshot(this Stream copyFrom) {
- ErrorUtilities.VerifyArgumentNotNull(copyFrom, "copyFrom");
-
- MemoryStream copyTo = new MemoryStream(copyFrom.CanSeek ? (int)copyFrom.Length : 4 * 1024);
- copyFrom.CopyTo(copyTo);
- copyTo.Position = 0;
- return copyTo;
- }
-
- /// <summary>
- /// Clones an <see cref="HttpWebRequest"/> in order to send it again.
- /// </summary>
- /// <param name="request">The request to clone.</param>
- /// <returns>The newly created instance.</returns>
- internal static HttpWebRequest Clone(this HttpWebRequest request) {
- ErrorUtilities.VerifyArgumentNotNull(request, "request");
- return Clone(request, request.RequestUri);
- }
-
- /// <summary>
- /// Clones an <see cref="HttpWebRequest"/> in order to send it again.
- /// </summary>
- /// <param name="request">The request to clone.</param>
- /// <param name="newRequestUri">The new recipient of the request.</param>
- /// <returns>The newly created instance.</returns>
- internal static HttpWebRequest Clone(this HttpWebRequest request, Uri newRequestUri) {
- ErrorUtilities.VerifyArgumentNotNull(request, "request");
- ErrorUtilities.VerifyArgumentNotNull(newRequestUri, "newRequestUri");
-
- var newRequest = (HttpWebRequest)WebRequest.Create(newRequestUri);
- newRequest.Accept = request.Accept;
- newRequest.AllowAutoRedirect = request.AllowAutoRedirect;
- newRequest.AllowWriteStreamBuffering = request.AllowWriteStreamBuffering;
- newRequest.AuthenticationLevel = request.AuthenticationLevel;
- newRequest.AutomaticDecompression = request.AutomaticDecompression;
- newRequest.CachePolicy = request.CachePolicy;
- newRequest.ClientCertificates = request.ClientCertificates;
- newRequest.ConnectionGroupName = request.ConnectionGroupName;
- if (request.ContentLength >= 0) {
- newRequest.ContentLength = request.ContentLength;
- }
- newRequest.ContentType = request.ContentType;
- newRequest.ContinueDelegate = request.ContinueDelegate;
- newRequest.CookieContainer = request.CookieContainer;
- newRequest.Credentials = request.Credentials;
- newRequest.Expect = request.Expect;
- newRequest.IfModifiedSince = request.IfModifiedSince;
- newRequest.ImpersonationLevel = request.ImpersonationLevel;
- newRequest.KeepAlive = request.KeepAlive;
- newRequest.MaximumAutomaticRedirections = request.MaximumAutomaticRedirections;
- newRequest.MaximumResponseHeadersLength = request.MaximumResponseHeadersLength;
- newRequest.MediaType = request.MediaType;
- newRequest.Method = request.Method;
- newRequest.Pipelined = request.Pipelined;
- newRequest.PreAuthenticate = request.PreAuthenticate;
- newRequest.ProtocolVersion = request.ProtocolVersion;
- newRequest.Proxy = request.Proxy;
- newRequest.ReadWriteTimeout = request.ReadWriteTimeout;
- newRequest.Referer = request.Referer;
- newRequest.SendChunked = request.SendChunked;
- newRequest.Timeout = request.Timeout;
- newRequest.TransferEncoding = request.TransferEncoding;
- newRequest.UnsafeAuthenticatedConnectionSharing = request.UnsafeAuthenticatedConnectionSharing;
- newRequest.UseDefaultCredentials = request.UseDefaultCredentials;
- newRequest.UserAgent = request.UserAgent;
-
- // We copy headers last, and only those that do not yet exist as a result
- // of setting these properties, so as to avoid exceptions thrown because
- // there are properties .NET wants us to use rather than direct headers.
- foreach (string header in request.Headers) {
- if (string.IsNullOrEmpty(newRequest.Headers[header])) {
- newRequest.Headers.Add(header, request.Headers[header]);
- }
- }
-
- return newRequest;
- }
-
- /// <summary>
- /// Tests whether two arrays are equal in length and contents.
- /// </summary>
- /// <typeparam name="T">The type of elements in the arrays.</typeparam>
- /// <param name="first">The first array in the comparison. May not be null.</param>
- /// <param name="second">The second array in the comparison. May not be null.</param>
- /// <returns>True if the arrays equal; false otherwise.</returns>
- internal static bool AreEquivalent<T>(T[] first, T[] second) {
- if (first == null) {
- throw new ArgumentNullException("first");
- }
- if (second == null) {
- throw new ArgumentNullException("second");
- }
- if (first.Length != second.Length) {
- return false;
- }
- for (int i = 0; i < first.Length; i++) {
- if (!first[i].Equals(second[i])) {
- return false;
- }
- }
- return true;
- }
-
- /// <summary>
- /// Tests whether two dictionaries are equal in length and contents.
- /// </summary>
- /// <typeparam name="TKey">The type of keys in the dictionaries.</typeparam>
- /// <typeparam name="TValue">The type of values in the dictionaries.</typeparam>
- /// <param name="first">The first dictionary in the comparison. May not be null.</param>
- /// <param name="second">The second dictionary in the comparison. May not be null.</param>
- /// <returns>True if the arrays equal; false otherwise.</returns>
- internal static bool AreEquivalent<TKey, TValue>(IDictionary<TKey, TValue> first, IDictionary<TKey, TValue> second) {
- return AreEquivalent(first.ToArray(), second.ToArray());
- }
-
- /// <summary>
- /// Concatenates a list of name-value pairs as key=value&key=value,
- /// taking care to properly encode each key and value for URL
- /// transmission. No ? is prefixed to the string.
- /// </summary>
- /// <param name="args">The dictionary of key/values to read from.</param>
- /// <returns>The formulated querystring style string.</returns>
- internal static string CreateQueryString(IEnumerable<KeyValuePair<string, string>> args) {
- ErrorUtilities.VerifyArgumentNotNull(args, "args");
- if (args.Count() == 0) {
- return string.Empty;
- }
- StringBuilder sb = new StringBuilder(args.Count() * 10);
-
- foreach (var p in args) {
- ErrorUtilities.VerifyArgument(p.Key != null, MessagingStrings.UnexpectedNullValue);
- ErrorUtilities.VerifyArgument(p.Value != null, MessagingStrings.UnexpectedNullValue);
- sb.Append(HttpUtility.UrlEncode(p.Key));
- sb.Append('=');
- sb.Append(HttpUtility.UrlEncode(p.Value));
- sb.Append('&');
- }
- sb.Length--; // remove trailing &
-
- return sb.ToString();
- }
-
- /// <summary>
- /// Adds a set of name-value pairs to the end of a given URL
- /// as part of the querystring piece. Prefixes a ? or & before
- /// first element as necessary.
- /// </summary>
- /// <param name="builder">The UriBuilder to add arguments to.</param>
- /// <param name="args">
- /// The arguments to add to the query.
- /// If null, <paramref name="builder"/> is not changed.
- /// </param>
- internal static void AppendQueryArgs(this UriBuilder builder, IEnumerable<KeyValuePair<string, string>> args) {
- if (builder == null) {
- throw new ArgumentNullException("builder");
- }
-
- if (args != null && args.Count() > 0) {
- StringBuilder sb = new StringBuilder(50 + (args.Count() * 10));
- if (!string.IsNullOrEmpty(builder.Query)) {
- sb.Append(builder.Query.Substring(1));
- sb.Append('&');
- }
- sb.Append(CreateQueryString(args));
-
- builder.Query = sb.ToString();
- }
- }
-
- /// <summary>
- /// Extracts the recipient from an HttpRequestInfo.
- /// </summary>
- /// <param name="request">The request to get recipient information from.</param>
- /// <returns>The recipient.</returns>
- internal static MessageReceivingEndpoint GetRecipient(this HttpRequestInfo request) {
- return new MessageReceivingEndpoint(request.Url, request.HttpMethod == "GET" ? HttpDeliveryMethods.GetRequest : HttpDeliveryMethods.PostRequest);
- }
-
- /// <summary>
- /// Copies some extra parameters into a message.
- /// </summary>
- /// <param name="message">The message to copy the extra data into.</param>
- /// <param name="extraParameters">The extra data to copy into the message. May be null to do nothing.</param>
- internal static void AddExtraParameters(this IMessage message, IDictionary<string, string> extraParameters) {
- ErrorUtilities.VerifyArgumentNotNull(message, "message");
-
- if (extraParameters != null) {
- MessageDictionary messageDictionary = new MessageDictionary(message);
- foreach (var pair in extraParameters) {
- messageDictionary.Add(pair);
- }
- }
- }
-
- /// <summary>
- /// Converts a <see cref="NameValueCollection"/> to an IDictionary<string, string>.
- /// </summary>
- /// <param name="nvc">The NameValueCollection to convert. May be null.</param>
- /// <returns>The generated dictionary, or null if <paramref name="nvc"/> is null.</returns>
- internal static Dictionary<string, string> ToDictionary(this NameValueCollection nvc) {
- if (nvc == null) {
- return null;
- }
-
- var dictionary = new Dictionary<string, string>();
- foreach (string key in nvc) {
- dictionary.Add(key, nvc[key]);
- }
-
- return dictionary;
- }
-
- /// <summary>
- /// Sorts the elements of a sequence in ascending order by using a specified comparer.
- /// </summary>
- /// <typeparam name="TSource">The type of the elements of source.</typeparam>
- /// <typeparam name="TKey">The type of the key returned by keySelector.</typeparam>
- /// <param name="source">A sequence of values to order.</param>
- /// <param name="keySelector">A function to extract a key from an element.</param>
- /// <param name="comparer">A comparison function to compare keys.</param>
- /// <returns>An System.Linq.IOrderedEnumerable<TElement> whose elements are sorted according to a key.</returns>
- internal static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Comparison<TKey> comparer) {
- return System.Linq.Enumerable.OrderBy<TSource, TKey>(source, keySelector, new ComparisonHelper<TKey>(comparer));
- }
-
- /// <summary>
- /// Determines whether the specified message is a request (indirect message or direct request).
- /// </summary>
- /// <param name="message">The message in question.</param>
- /// <returns>
- /// <c>true</c> if the specified message is a request; otherwise, <c>false</c>.
- /// </returns>
- /// <remarks>
- /// Although an <see cref="IProtocolMessage"/> may implement the <see cref="IDirectedProtocolMessage"/>
- /// interface, it may only be doing that for its derived classes. These objects are only requests
- /// if their <see cref="IDirectedProtocolMessage.Recipient"/> property is non-null.
- /// </remarks>
- internal static bool IsRequest(this IDirectedProtocolMessage message) {
- ErrorUtilities.VerifyArgumentNotNull(message, "message");
- return message.Recipient != null;
- }
-
- /// <summary>
- /// Determines whether the specified message is a direct response.
- /// </summary>
- /// <param name="message">The message in question.</param>
- /// <returns>
- /// <c>true</c> if the specified message is a direct response; otherwise, <c>false</c>.
- /// </returns>
- /// <remarks>
- /// Although an <see cref="IProtocolMessage"/> may implement the
- /// <see cref="IDirectResponseProtocolMessage"/> interface, it may only be doing
- /// that for its derived classes. These objects are only requests if their
- /// <see cref="IDirectResponseProtocolMessage.OriginatingRequest"/> property is non-null.
- /// </remarks>
- internal static bool IsDirectResponse(this IDirectResponseProtocolMessage message) {
- ErrorUtilities.VerifyArgumentNotNull(message, "message");
- return message.OriginatingRequest != null;
- }
-
- /// <summary>
- /// A class to convert a <see cref="Comparison<T>"/> into an <see cref="IComparer<T>"/>.
- /// </summary>
- /// <typeparam name="T">The type of objects being compared.</typeparam>
- private class ComparisonHelper<T> : IComparer<T> {
- /// <summary>
- /// The comparison method to use.
- /// </summary>
- private Comparison<T> comparison;
-
- /// <summary>
- /// Initializes a new instance of the ComparisonHelper class.
- /// </summary>
- /// <param name="comparison">The comparison method to use.</param>
- internal ComparisonHelper(Comparison<T> comparison) {
- if (comparison == null) {
- throw new ArgumentNullException("comparison");
- }
-
- this.comparison = comparison;
- }
-
- #region IComparer<T> Members
-
- /// <summary>
- /// Compares two instances of <typeparamref name="T"/>.
- /// </summary>
- /// <param name="x">The first object to compare.</param>
- /// <param name="y">The second object to compare.</param>
- /// <returns>Any of -1, 0, or 1 according to standard comparison rules.</returns>
- public int Compare(T x, T y) {
- return this.comparison(x, y);
- }
-
- #endregion
- }
- }
-}
+//----------------------------------------------------------------------- +// <copyright file="MessagingUtilities.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Messaging { + using System; + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Diagnostics.CodeAnalysis; + using System.IO; + using System.Linq; + using System.Net; + using System.Security.Cryptography; + using System.Text; + using System.Web; + using DotNetOpenAuth.Messaging.Reflection; + + /// <summary> + /// A grab-bag of utility methods useful for the channel stack of the protocol. + /// </summary> + public static class MessagingUtilities { + /// <summary> + /// The cryptographically strong random data generator used for creating secrets. + /// </summary> + /// <remarks>The random number generator is thread-safe.</remarks> + internal static readonly RandomNumberGenerator CryptoRandomDataGenerator = new RNGCryptoServiceProvider(); + + /// <summary> + /// Gets the original request URL, as seen from the browser before any URL rewrites on the server if any. + /// Cookieless session directory (if applicable) is also included. + /// </summary> + /// <returns>The URL in the user agent's Location bar.</returns> + [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "The Uri merging requires use of a string value.")] + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Expensive call should not be a property.")] + public static Uri GetRequestUrlFromContext() { + HttpContext context = HttpContext.Current; + if (context == null) { + throw new InvalidOperationException(MessagingStrings.CurrentHttpContextRequired); + } + + // We use Request.Url for the full path to the server, and modify it + // with Request.RawUrl to capture both the cookieless session "directory" if it exists + // and the original path in case URL rewriting is going on. We don't want to be + // fooled by URL rewriting because we're comparing the actual URL with what's in + // the return_to parameter in some cases. + // Response.ApplyAppPathModifier(builder.Path) would have worked for the cookieless + // session, but not the URL rewriting problem. + return new Uri(context.Request.Url, context.Request.RawUrl); + } + + /// <summary> + /// Strips any and all URI query parameters that start with some prefix. + /// </summary> + /// <param name="uri">The URI that may have a query with parameters to remove.</param> + /// <param name="prefix">The prefix for parameters to remove.</param> + /// <returns>Either a new Uri with the parameters removed if there were any to remove, or the same Uri instance if no parameters needed to be removed.</returns> + public static Uri StripQueryArgumentsWithPrefix(this Uri uri, string prefix) { + NameValueCollection queryArgs = HttpUtility.ParseQueryString(uri.Query); + var matchingKeys = queryArgs.Keys.OfType<string>().Where(key => key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)).ToList(); + if (matchingKeys.Count > 0) { + UriBuilder builder = new UriBuilder(uri); + foreach (string key in matchingKeys) { + queryArgs.Remove(key); + } + builder.Query = CreateQueryString(queryArgs.ToDictionary()); + return builder.Uri; + } else { + return uri; + } + } + + /// <summary> + /// Gets a cryptographically strong random sequence of values. + /// </summary> + /// <param name="length">The length of the sequence to generate.</param> + /// <returns>The generated values, which may contain zeros.</returns> + internal static byte[] GetCryptoRandomData(int length) { + byte[] buffer = new byte[length]; + CryptoRandomDataGenerator.GetBytes(buffer); + return buffer; + } + + /// <summary> + /// Gets a cryptographically strong random sequence of values. + /// </summary> + /// <param name="binaryLength">The length of the byte sequence to generate.</param> + /// <returns>A base64 encoding of the generated random data, + /// whose length in characters will likely be greater than <paramref name="binaryLength"/>.</returns> + internal static string GetCryptoRandomDataAsBase64(int binaryLength) { + byte[] uniq_bytes = GetCryptoRandomData(binaryLength); + string uniq = Convert.ToBase64String(uniq_bytes); + return uniq; + } + + /// <summary> + /// Adds a set of HTTP headers to an <see cref="HttpResponse"/> instance, + /// taking care to set some headers to the appropriate properties of + /// <see cref="HttpResponse" /> + /// </summary> + /// <param name="headers">The headers to add.</param> + /// <param name="response">The <see cref="HttpResponse"/> instance to set the appropriate values to.</param> + internal static void ApplyHeadersToResponse(WebHeaderCollection headers, HttpResponse response) { + if (headers == null) { + throw new ArgumentNullException("headers"); + } + if (response == null) { + throw new ArgumentNullException("response"); + } + foreach (string headerName in headers) { + switch (headerName) { + case "Content-Type": + response.ContentType = headers[HttpResponseHeader.ContentType]; + break; + + // Add more special cases here as necessary. + default: + response.AddHeader(headerName, headers[headerName]); + break; + } + } + } + + /// <summary> + /// Copies the contents of one stream to another. + /// </summary> + /// <param name="copyFrom">The stream to copy from, at the position where copying should begin.</param> + /// <param name="copyTo">The stream to copy to, at the position where bytes should be written.</param> + /// <returns>The total number of bytes copied.</returns> + /// <remarks> + /// Copying begins at the streams' current positions. + /// The positions are NOT reset after copying is complete. + /// </remarks> + internal static int CopyTo(this Stream copyFrom, Stream copyTo) { + return CopyTo(copyFrom, copyTo, int.MaxValue); + } + + /// <summary> + /// Copies the contents of one stream to another. + /// </summary> + /// <param name="copyFrom">The stream to copy from, at the position where copying should begin.</param> + /// <param name="copyTo">The stream to copy to, at the position where bytes should be written.</param> + /// <param name="maximumBytesToCopy">The maximum bytes to copy.</param> + /// <returns>The total number of bytes copied.</returns> + /// <remarks> + /// Copying begins at the streams' current positions. + /// The positions are NOT reset after copying is complete. + /// </remarks> + internal static int CopyTo(this Stream copyFrom, Stream copyTo, int maximumBytesToCopy) { + ErrorUtilities.VerifyArgumentNotNull(copyFrom, "copyFrom"); + ErrorUtilities.VerifyArgumentNotNull(copyTo, "copyTo"); + ErrorUtilities.VerifyArgument(copyFrom.CanRead, MessagingStrings.StreamUnreadable); + ErrorUtilities.VerifyArgument(copyTo.CanWrite, MessagingStrings.StreamUnwritable, "copyTo"); + + byte[] buffer = new byte[1024]; + int readBytes; + int totalCopiedBytes = 0; + while ((readBytes = copyFrom.Read(buffer, 0, Math.Min(1024, maximumBytesToCopy))) > 0) { + int writeBytes = Math.Min(maximumBytesToCopy, readBytes); + copyTo.Write(buffer, 0, writeBytes); + totalCopiedBytes += writeBytes; + maximumBytesToCopy -= writeBytes; + } + + return totalCopiedBytes; + } + + /// <summary> + /// Creates a snapshot of some stream so it is seekable, and the original can be closed. + /// </summary> + /// <param name="copyFrom">The stream to copy bytes from.</param> + /// <returns>A seekable stream with the same contents as the original.</returns> + internal static Stream CreateSnapshot(this Stream copyFrom) { + ErrorUtilities.VerifyArgumentNotNull(copyFrom, "copyFrom"); + + MemoryStream copyTo = new MemoryStream(copyFrom.CanSeek ? (int)copyFrom.Length : 4 * 1024); + copyFrom.CopyTo(copyTo); + copyTo.Position = 0; + return copyTo; + } + + /// <summary> + /// Clones an <see cref="HttpWebRequest"/> in order to send it again. + /// </summary> + /// <param name="request">The request to clone.</param> + /// <returns>The newly created instance.</returns> + internal static HttpWebRequest Clone(this HttpWebRequest request) { + ErrorUtilities.VerifyArgumentNotNull(request, "request"); + return Clone(request, request.RequestUri); + } + + /// <summary> + /// Clones an <see cref="HttpWebRequest"/> in order to send it again. + /// </summary> + /// <param name="request">The request to clone.</param> + /// <param name="newRequestUri">The new recipient of the request.</param> + /// <returns>The newly created instance.</returns> + internal static HttpWebRequest Clone(this HttpWebRequest request, Uri newRequestUri) { + ErrorUtilities.VerifyArgumentNotNull(request, "request"); + ErrorUtilities.VerifyArgumentNotNull(newRequestUri, "newRequestUri"); + + var newRequest = (HttpWebRequest)WebRequest.Create(newRequestUri); + newRequest.Accept = request.Accept; + newRequest.AllowAutoRedirect = request.AllowAutoRedirect; + newRequest.AllowWriteStreamBuffering = request.AllowWriteStreamBuffering; + newRequest.AuthenticationLevel = request.AuthenticationLevel; + newRequest.AutomaticDecompression = request.AutomaticDecompression; + newRequest.CachePolicy = request.CachePolicy; + newRequest.ClientCertificates = request.ClientCertificates; + newRequest.ConnectionGroupName = request.ConnectionGroupName; + if (request.ContentLength >= 0) { + newRequest.ContentLength = request.ContentLength; + } + newRequest.ContentType = request.ContentType; + newRequest.ContinueDelegate = request.ContinueDelegate; + newRequest.CookieContainer = request.CookieContainer; + newRequest.Credentials = request.Credentials; + newRequest.Expect = request.Expect; + newRequest.IfModifiedSince = request.IfModifiedSince; + newRequest.ImpersonationLevel = request.ImpersonationLevel; + newRequest.KeepAlive = request.KeepAlive; + newRequest.MaximumAutomaticRedirections = request.MaximumAutomaticRedirections; + newRequest.MaximumResponseHeadersLength = request.MaximumResponseHeadersLength; + newRequest.MediaType = request.MediaType; + newRequest.Method = request.Method; + newRequest.Pipelined = request.Pipelined; + newRequest.PreAuthenticate = request.PreAuthenticate; + newRequest.ProtocolVersion = request.ProtocolVersion; + newRequest.Proxy = request.Proxy; + newRequest.ReadWriteTimeout = request.ReadWriteTimeout; + newRequest.Referer = request.Referer; + newRequest.SendChunked = request.SendChunked; + newRequest.Timeout = request.Timeout; + newRequest.TransferEncoding = request.TransferEncoding; + newRequest.UnsafeAuthenticatedConnectionSharing = request.UnsafeAuthenticatedConnectionSharing; + newRequest.UseDefaultCredentials = request.UseDefaultCredentials; + newRequest.UserAgent = request.UserAgent; + + // We copy headers last, and only those that do not yet exist as a result + // of setting these properties, so as to avoid exceptions thrown because + // there are properties .NET wants us to use rather than direct headers. + foreach (string header in request.Headers) { + if (string.IsNullOrEmpty(newRequest.Headers[header])) { + newRequest.Headers.Add(header, request.Headers[header]); + } + } + + return newRequest; + } + + /// <summary> + /// Tests whether two arrays are equal in length and contents. + /// </summary> + /// <typeparam name="T">The type of elements in the arrays.</typeparam> + /// <param name="first">The first array in the comparison. May not be null.</param> + /// <param name="second">The second array in the comparison. May not be null.</param> + /// <returns>True if the arrays equal; false otherwise.</returns> + internal static bool AreEquivalent<T>(T[] first, T[] second) { + if (first == null) { + throw new ArgumentNullException("first"); + } + if (second == null) { + throw new ArgumentNullException("second"); + } + if (first.Length != second.Length) { + return false; + } + for (int i = 0; i < first.Length; i++) { + if (!first[i].Equals(second[i])) { + return false; + } + } + return true; + } + + /// <summary> + /// Tests whether two dictionaries are equal in length and contents. + /// </summary> + /// <typeparam name="TKey">The type of keys in the dictionaries.</typeparam> + /// <typeparam name="TValue">The type of values in the dictionaries.</typeparam> + /// <param name="first">The first dictionary in the comparison. May not be null.</param> + /// <param name="second">The second dictionary in the comparison. May not be null.</param> + /// <returns>True if the arrays equal; false otherwise.</returns> + internal static bool AreEquivalent<TKey, TValue>(IDictionary<TKey, TValue> first, IDictionary<TKey, TValue> second) { + return AreEquivalent(first.ToArray(), second.ToArray()); + } + + /// <summary> + /// Concatenates a list of name-value pairs as key=value&key=value, + /// taking care to properly encode each key and value for URL + /// transmission. No ? is prefixed to the string. + /// </summary> + /// <param name="args">The dictionary of key/values to read from.</param> + /// <returns>The formulated querystring style string.</returns> + internal static string CreateQueryString(IEnumerable<KeyValuePair<string, string>> args) { + ErrorUtilities.VerifyArgumentNotNull(args, "args"); + if (args.Count() == 0) { + return string.Empty; + } + StringBuilder sb = new StringBuilder(args.Count() * 10); + + foreach (var p in args) { + ErrorUtilities.VerifyArgument(p.Key != null, MessagingStrings.UnexpectedNullValue); + ErrorUtilities.VerifyArgument(p.Value != null, MessagingStrings.UnexpectedNullValue); + sb.Append(HttpUtility.UrlEncode(p.Key)); + sb.Append('='); + sb.Append(HttpUtility.UrlEncode(p.Value)); + sb.Append('&'); + } + sb.Length--; // remove trailing & + + return sb.ToString(); + } + + /// <summary> + /// Adds a set of name-value pairs to the end of a given URL + /// as part of the querystring piece. Prefixes a ? or & before + /// first element as necessary. + /// </summary> + /// <param name="builder">The UriBuilder to add arguments to.</param> + /// <param name="args"> + /// The arguments to add to the query. + /// If null, <paramref name="builder"/> is not changed. + /// </param> + internal static void AppendQueryArgs(this UriBuilder builder, IEnumerable<KeyValuePair<string, string>> args) { + if (builder == null) { + throw new ArgumentNullException("builder"); + } + + if (args != null && args.Count() > 0) { + StringBuilder sb = new StringBuilder(50 + (args.Count() * 10)); + if (!string.IsNullOrEmpty(builder.Query)) { + sb.Append(builder.Query.Substring(1)); + sb.Append('&'); + } + sb.Append(CreateQueryString(args)); + + builder.Query = sb.ToString(); + } + } + + /// <summary> + /// Extracts the recipient from an HttpRequestInfo. + /// </summary> + /// <param name="request">The request to get recipient information from.</param> + /// <returns>The recipient.</returns> + internal static MessageReceivingEndpoint GetRecipient(this HttpRequestInfo request) { + return new MessageReceivingEndpoint(request.Url, request.HttpMethod == "GET" ? HttpDeliveryMethods.GetRequest : HttpDeliveryMethods.PostRequest); + } + + /// <summary> + /// Copies some extra parameters into a message. + /// </summary> + /// <param name="message">The message to copy the extra data into.</param> + /// <param name="extraParameters">The extra data to copy into the message. May be null to do nothing.</param> + internal static void AddExtraParameters(this IMessage message, IDictionary<string, string> extraParameters) { + ErrorUtilities.VerifyArgumentNotNull(message, "message"); + + if (extraParameters != null) { + MessageDictionary messageDictionary = new MessageDictionary(message); + foreach (var pair in extraParameters) { + messageDictionary.Add(pair); + } + } + } + + /// <summary> + /// Converts a <see cref="NameValueCollection"/> to an IDictionary<string, string>. + /// </summary> + /// <param name="nvc">The NameValueCollection to convert. May be null.</param> + /// <returns>The generated dictionary, or null if <paramref name="nvc"/> is null.</returns> + internal static Dictionary<string, string> ToDictionary(this NameValueCollection nvc) { + if (nvc == null) { + return null; + } + + var dictionary = new Dictionary<string, string>(); + foreach (string key in nvc) { + dictionary.Add(key, nvc[key]); + } + + return dictionary; + } + + /// <summary> + /// Sorts the elements of a sequence in ascending order by using a specified comparer. + /// </summary> + /// <typeparam name="TSource">The type of the elements of source.</typeparam> + /// <typeparam name="TKey">The type of the key returned by keySelector.</typeparam> + /// <param name="source">A sequence of values to order.</param> + /// <param name="keySelector">A function to extract a key from an element.</param> + /// <param name="comparer">A comparison function to compare keys.</param> + /// <returns>An System.Linq.IOrderedEnumerable<TElement> whose elements are sorted according to a key.</returns> + internal static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Comparison<TKey> comparer) { + return System.Linq.Enumerable.OrderBy<TSource, TKey>(source, keySelector, new ComparisonHelper<TKey>(comparer)); + } + + /// <summary> + /// Determines whether the specified message is a request (indirect message or direct request). + /// </summary> + /// <param name="message">The message in question.</param> + /// <returns> + /// <c>true</c> if the specified message is a request; otherwise, <c>false</c>. + /// </returns> + /// <remarks> + /// Although an <see cref="IProtocolMessage"/> may implement the <see cref="IDirectedProtocolMessage"/> + /// interface, it may only be doing that for its derived classes. These objects are only requests + /// if their <see cref="IDirectedProtocolMessage.Recipient"/> property is non-null. + /// </remarks> + internal static bool IsRequest(this IDirectedProtocolMessage message) { + ErrorUtilities.VerifyArgumentNotNull(message, "message"); + return message.Recipient != null; + } + + /// <summary> + /// Determines whether the specified message is a direct response. + /// </summary> + /// <param name="message">The message in question.</param> + /// <returns> + /// <c>true</c> if the specified message is a direct response; otherwise, <c>false</c>. + /// </returns> + /// <remarks> + /// Although an <see cref="IProtocolMessage"/> may implement the + /// <see cref="IDirectResponseProtocolMessage"/> interface, it may only be doing + /// that for its derived classes. These objects are only requests if their + /// <see cref="IDirectResponseProtocolMessage.OriginatingRequest"/> property is non-null. + /// </remarks> + internal static bool IsDirectResponse(this IDirectResponseProtocolMessage message) { + ErrorUtilities.VerifyArgumentNotNull(message, "message"); + return message.OriginatingRequest != null; + } + + /// <summary> + /// A class to convert a <see cref="Comparison<T>"/> into an <see cref="IComparer<T>"/>. + /// </summary> + /// <typeparam name="T">The type of objects being compared.</typeparam> + private class ComparisonHelper<T> : IComparer<T> { + /// <summary> + /// The comparison method to use. + /// </summary> + private Comparison<T> comparison; + + /// <summary> + /// Initializes a new instance of the ComparisonHelper class. + /// </summary> + /// <param name="comparison">The comparison method to use.</param> + internal ComparisonHelper(Comparison<T> comparison) { + if (comparison == null) { + throw new ArgumentNullException("comparison"); + } + + this.comparison = comparison; + } + + #region IComparer<T> Members + + /// <summary> + /// Compares two instances of <typeparamref name="T"/>. + /// </summary> + /// <param name="x">The first object to compare.</param> + /// <param name="y">The second object to compare.</param> + /// <returns>Any of -1, 0, or 1 according to standard comparison rules.</returns> + public int Compare(T x, T y) { + return this.comparison(x, y); + } + + #endregion + } + } +} diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdMessageFactory.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdMessageFactory.cs index 956aae0..73d8830 100644 --- a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdMessageFactory.cs +++ b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdMessageFactory.cs @@ -10,7 +10,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { using System.Linq; using System.Text; using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OpenId.Messages;
+ using DotNetOpenAuth.OpenId.Messages; using DotNetOpenAuth.OpenId.RelyingParty; /// <summary> @@ -54,9 +54,9 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { } else if (string.Equals(mode, protocol.Args.Mode.checkid_setup) || string.Equals(mode, protocol.Args.Mode.checkid_immediate)) { bool immediate = string.Equals(mode, protocol.Args.Mode.checkid_immediate); - if (fields.ContainsKey(protocol.openid.identity)) {
+ if (fields.ContainsKey(protocol.openid.identity)) { message = new CheckIdRequest(protocol.Version, recipient.Location, AuthenticationRequestMode.Immediate); - } else {
+ } else { message = new SignedResponseRequest(protocol.Version, recipient.Location, AuthenticationRequestMode.Immediate); } } else if (string.Equals(mode, protocol.Args.Mode.cancel) || diff --git a/src/DotNetOpenAuth/OpenId/Messages/CheckIdRequest.cs b/src/DotNetOpenAuth/OpenId/Messages/CheckIdRequest.cs index 038a12e..6d54504 100644 --- a/src/DotNetOpenAuth/OpenId/Messages/CheckIdRequest.cs +++ b/src/DotNetOpenAuth/OpenId/Messages/CheckIdRequest.cs @@ -1,66 +1,66 @@ -//-----------------------------------------------------------------------
-// <copyright file="CheckIdRequest.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OpenId.Messages {
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using System.Text;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OpenId.RelyingParty;
-
- /// <summary>
- /// An authentication request from a Relying Party to a Provider.
- /// </summary>
- /// <remarks>
- /// This message type satisfies OpenID 2.0 section 9.1.
- /// </remarks>
- [DebuggerDisplay("OpenID {Version} {Mode} {ClaimedIdentifier}")]
- internal class CheckIdRequest : SignedResponseRequest {
- /// <summary>
- /// Initializes a new instance of the <see cref="CheckIdRequest"/> class.
- /// </summary>
- /// <param name="version">The OpenID version to use.</param>
- /// <param name="providerEndpoint">The Provider endpoint that receives this message.</param>
- /// <param name="mode">
- /// <see cref="AuthenticationRequestMode.Immediate"/> for asynchronous javascript clients;
- /// <see cref="AuthenticationRequestMode.Setup"/> to allow the Provider to interact with the user in order to complete authentication.
- /// </param>
- internal CheckIdRequest(Version version, Uri providerEndpoint, AuthenticationRequestMode mode) :
- base(version, providerEndpoint, mode) {
- }
-
- /// <summary>
- /// Gets or sets the Claimed Identifier.
- /// </summary>
- /// <remarks>
- /// <para>"openid.claimed_id" and "openid.identity" SHALL be either both present or both absent.
- /// If neither value is present, the assertion is not about an identifier,
- /// and will contain other information in its payload, using extensions (Extensions). </para>
- /// <para>It is RECOMMENDED that OPs accept XRI identifiers with or without the "xri://" prefix, as specified in the Normalization (Normalization) section. </para>
- /// </remarks>
- [MessagePart("openid.claimed_id", IsRequired = true, AllowEmpty = false, MinVersion = "2.0")]
- internal Identifier ClaimedIdentifier { get; set; }
-
- /// <summary>
- /// Gets or sets the OP Local Identifier.
- /// </summary>
- /// <value>The OP-Local Identifier. </value>
- /// <remarks>
- /// <para>If a different OP-Local Identifier is not specified, the claimed
- /// identifier MUST be used as the value for openid.identity.</para>
- /// <para>Note: If this is set to the special value
- /// "http://specs.openid.net/auth/2.0/identifier_select" then the OP SHOULD
- /// choose an Identifier that belongs to the end user. This parameter MAY
- /// be omitted if the request is not about an identifier (for instance if
- /// an extension is in use that makes the request meaningful without it;
- /// see openid.claimed_id above). </para>
- /// </remarks>
- [MessagePart("openid.identity", IsRequired = true, AllowEmpty = false)]
- internal Identifier LocalIdentifier { get; set; }
- }
-}
+//----------------------------------------------------------------------- +// <copyright file="CheckIdRequest.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OpenId.Messages { + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using System.Text; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OpenId.RelyingParty; + + /// <summary> + /// An authentication request from a Relying Party to a Provider. + /// </summary> + /// <remarks> + /// This message type satisfies OpenID 2.0 section 9.1. + /// </remarks> + [DebuggerDisplay("OpenID {Version} {Mode} {ClaimedIdentifier}")] + internal class CheckIdRequest : SignedResponseRequest { + /// <summary> + /// Initializes a new instance of the <see cref="CheckIdRequest"/> class. + /// </summary> + /// <param name="version">The OpenID version to use.</param> + /// <param name="providerEndpoint">The Provider endpoint that receives this message.</param> + /// <param name="mode"> + /// <see cref="AuthenticationRequestMode.Immediate"/> for asynchronous javascript clients; + /// <see cref="AuthenticationRequestMode.Setup"/> to allow the Provider to interact with the user in order to complete authentication. + /// </param> + internal CheckIdRequest(Version version, Uri providerEndpoint, AuthenticationRequestMode mode) : + base(version, providerEndpoint, mode) { + } + + /// <summary> + /// Gets or sets the Claimed Identifier. + /// </summary> + /// <remarks> + /// <para>"openid.claimed_id" and "openid.identity" SHALL be either both present or both absent. + /// If neither value is present, the assertion is not about an identifier, + /// and will contain other information in its payload, using extensions (Extensions). </para> + /// <para>It is RECOMMENDED that OPs accept XRI identifiers with or without the "xri://" prefix, as specified in the Normalization (Normalization) section. </para> + /// </remarks> + [MessagePart("openid.claimed_id", IsRequired = true, AllowEmpty = false, MinVersion = "2.0")] + internal Identifier ClaimedIdentifier { get; set; } + + /// <summary> + /// Gets or sets the OP Local Identifier. + /// </summary> + /// <value>The OP-Local Identifier. </value> + /// <remarks> + /// <para>If a different OP-Local Identifier is not specified, the claimed + /// identifier MUST be used as the value for openid.identity.</para> + /// <para>Note: If this is set to the special value + /// "http://specs.openid.net/auth/2.0/identifier_select" then the OP SHOULD + /// choose an Identifier that belongs to the end user. This parameter MAY + /// be omitted if the request is not about an identifier (for instance if + /// an extension is in use that makes the request meaningful without it; + /// see openid.claimed_id above). </para> + /// </remarks> + [MessagePart("openid.identity", IsRequired = true, AllowEmpty = false)] + internal Identifier LocalIdentifier { get; set; } + } +} diff --git a/src/DotNetOpenAuth/OpenId/Messages/IOpenIdMessageExtension.cs b/src/DotNetOpenAuth/OpenId/Messages/IOpenIdMessageExtension.cs index 4fe066b..ef5b86a 100644 --- a/src/DotNetOpenAuth/OpenId/Messages/IOpenIdMessageExtension.cs +++ b/src/DotNetOpenAuth/OpenId/Messages/IOpenIdMessageExtension.cs @@ -1,40 +1,40 @@ -//-----------------------------------------------------------------------
-// <copyright file="IOpenIdMessageExtension.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OpenId.Messages {
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using DotNetOpenAuth.Messaging;
-
- /// <summary>
- /// The contract any OpenID extension for DotNetOpenId must implement.
- /// </summary>
- internal interface IOpenIdMessageExtension : IExtensionMessage {
- /// <summary>
- /// Gets the TypeURI the extension uses in the OpenID protocol and in XRDS advertisements.
- /// </summary>
- string TypeUri { get; }
-
- /// <summary>
- /// Gets the additional TypeURIs that are supported by this extension, in preferred order.
- /// May be empty if none other than <see cref="TypeUri"/> is supported, but
- /// should not be null.
- /// </summary>
- /// <remarks>
- /// Useful for reading in messages with an older version of an extension.
- /// The value in the <see cref="TypeUri"/> property is always checked before
- /// trying this list.
- /// If you do support multiple versions of an extension using this method,
- /// consider adding a CreateResponse method to your request extension class
- /// so that the response can have the context it needs to remain compatible
- /// given the version of the extension in the request message.
- /// The <see cref="Extensions.SimpleRegistration.ClaimsRequest.CreateResponse"/> for an example.
- /// </remarks>
- IEnumerable<string> AdditionalSupportedTypeUris { get; }
- }
-}
+//----------------------------------------------------------------------- +// <copyright file="IOpenIdMessageExtension.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OpenId.Messages { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using DotNetOpenAuth.Messaging; + + /// <summary> + /// The contract any OpenID extension for DotNetOpenId must implement. + /// </summary> + internal interface IOpenIdMessageExtension : IExtensionMessage { + /// <summary> + /// Gets the TypeURI the extension uses in the OpenID protocol and in XRDS advertisements. + /// </summary> + string TypeUri { get; } + + /// <summary> + /// Gets the additional TypeURIs that are supported by this extension, in preferred order. + /// May be empty if none other than <see cref="TypeUri"/> is supported, but + /// should not be null. + /// </summary> + /// <remarks> + /// Useful for reading in messages with an older version of an extension. + /// The value in the <see cref="TypeUri"/> property is always checked before + /// trying this list. + /// If you do support multiple versions of an extension using this method, + /// consider adding a CreateResponse method to your request extension class + /// so that the response can have the context it needs to remain compatible + /// given the version of the extension in the request message. + /// The <see cref="Extensions.SimpleRegistration.ClaimsRequest.CreateResponse"/> for an example. + /// </remarks> + IEnumerable<string> AdditionalSupportedTypeUris { get; } + } +} diff --git a/src/DotNetOpenAuth/OpenId/Messages/SignedResponseRequest.cs b/src/DotNetOpenAuth/OpenId/Messages/SignedResponseRequest.cs index f2eae6a..0e21807 100644 --- a/src/DotNetOpenAuth/OpenId/Messages/SignedResponseRequest.cs +++ b/src/DotNetOpenAuth/OpenId/Messages/SignedResponseRequest.cs @@ -1,177 +1,177 @@ -//-----------------------------------------------------------------------
-// <copyright file="SignedResponseRequest.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OpenId.Messages {
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using System.Text;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OpenId.RelyingParty;
-
- /// <summary>
- /// An indirect request from a Relying Party to a Provider where the response
- /// is expected to be signed.
- /// </summary>
- internal class SignedResponseRequest : RequestBase, IProtocolMessageWithExtensions {
- /// <summary>
- /// Backing store for the <see cref="Extensions"/> property.
- /// </summary>
- private IList<IExtensionMessage> extensions = new List<IExtensionMessage>();
-
- /// <summary>
- /// Initializes a new instance of the <see cref="SignedResponseRequest"/> class.
- /// </summary>
- /// <param name="version">The OpenID version to use.</param>
- /// <param name="providerEndpoint">The Provider endpoint that receives this message.</param>
- /// <param name="mode">
- /// <see cref="AuthenticationRequestMode.Immediate"/> for asynchronous javascript clients;
- /// <see cref="AuthenticationRequestMode.Setup"/> to allow the Provider to interact with the user in order to complete authentication.
- /// </param>
- internal SignedResponseRequest(Version version, Uri providerEndpoint, AuthenticationRequestMode mode) :
- base(version, providerEndpoint, GetMode(version, mode), DotNetOpenAuth.Messaging.MessageTransport.Indirect) {
- }
-
- #region IProtocolMessageWithExtensions Members
-
- /// <summary>
- /// Gets the list of extensions that are included with this message.
- /// </summary>
- /// <value></value>
- /// <remarks>
- /// Implementations of this interface should ensure that this property never returns null.
- /// </remarks>
- public IList<IExtensionMessage> Extensions {
- get { return this.extensions; }
- }
-
- #endregion
-
- /// <summary>
- /// Gets a value indicating whether the Provider is allowed to interact with the user
- /// as part of authentication.
- /// </summary>
- /// <value><c>true</c> if using OpenID immediate mode; otherwise, <c>false</c>.</value>
- internal bool Immediate {
- get { return String.Equals(this.Mode, Protocol.Args.Mode.checkid_immediate, StringComparison.Ordinal); }
- }
-
- /// <summary>
- /// Gets or sets the handle of the association the RP would like the Provider
- /// to use for signing a positive assertion in the response message.
- /// </summary>
- /// <value>A handle for an association between the Relying Party and the OP
- /// that SHOULD be used to sign the response. </value>
- /// <remarks>
- /// If no association handle is sent, the transaction will take place in Stateless Mode
- /// (Verifying Directly with the OpenID Provider).
- /// </remarks>
- [MessagePart("openid.assoc_handle", IsRequired = false, AllowEmpty = false)]
- internal string AssociationHandle { get; set; }
-
- /// <summary>
- /// Gets or sets the URL the Provider should redirect the user agent to following
- /// the authentication attempt.
- /// </summary>
- /// <value>URL to which the OP SHOULD return the User-Agent with the response
- /// indicating the status of the request.</value>
- /// <remarks>
- /// <para>If this value is not sent in the request it signifies that the Relying Party
- /// does not wish for the end user to be returned. </para>
- /// <para>The return_to URL MAY be used as a mechanism for the Relying Party to attach
- /// context about the authentication request to the authentication response.
- /// This document does not define a mechanism by which the RP can ensure that query
- /// parameters are not modified by outside parties; such a mechanism can be defined
- /// by the RP itself. </para>
- /// </remarks>
- [MessagePart("openid.return_to", IsRequired = true, AllowEmpty = false)]
- [MessagePart("openid.return_to", IsRequired = false, AllowEmpty = false, MinVersion = "2.0")]
- internal Uri ReturnTo { get; set; }
-
- /// <summary>
- /// Gets or sets the Relying Party discovery URL the Provider may use to verify the
- /// source of the authentication request.
- /// </summary>
- /// <value>
- /// URL pattern the OP SHOULD ask the end user to trust. See Section 9.2 (Realms).
- /// This value MUST be sent if openid.return_to is omitted.
- /// Default: The <see cref="ReturnTo"/> URL.
- /// </value>
- [MessagePart("openid.trust_root", IsRequired = false, AllowEmpty = false)]
- [MessagePart("openid.realm", IsRequired = false, AllowEmpty = false, MinVersion = "2.0")]
- internal Realm Realm { get; set; }
-
- /// <summary>
- /// Checks the message state for conformity to the protocol specification
- /// and throws an exception if the message is invalid.
- /// </summary>
- /// <remarks>
- /// <para>Some messages have required fields, or combinations of fields that must relate to each other
- /// in specialized ways. After deserializing a message, this method checks the state of the
- /// message to see if it conforms to the protocol.</para>
- /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
- /// outside this scope of this particular message.</para>
- /// </remarks>
- /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
- public override void EnsureValidMessage() {
- base.EnsureValidMessage();
-
- if (this.Realm == null) {
- // Set the default Realm per the spec if it is not explicitly given.
- this.Realm = this.ReturnTo;
- } else if (this.ReturnTo != null) {
- // Verify that the realm and return_to agree.
- ErrorUtilities.VerifyProtocol(this.Realm.Contains(this.ReturnTo), OpenIdStrings.ReturnToNotUnderRealm, this.ReturnTo, this.Realm);
- }
- }
-
- /// <summary>
- /// Adds parameters to the return_to querystring.
- /// </summary>
- /// <param name="keysValues">The keys=value pairs to add to the return_to query string.</param>
- /// <remarks>
- /// This method is useful if the Relying Party wants to recall some value
- /// when and if a positive assertion comes back from the Provider.
- /// </remarks>
- internal void AddReturnToArguments(IEnumerable<KeyValuePair<string, string>> keysValues) {
- ErrorUtilities.VerifyArgumentNotNull(keysValues, "keysValues");
- UriBuilder returnToBuilder = new UriBuilder(this.ReturnTo);
- returnToBuilder.AppendQueryArgs(keysValues);
- this.ReturnTo = returnToBuilder.Uri;
- }
-
- /// <summary>
- /// Adds a parameter to the return_to querystring.
- /// </summary>
- /// <param name="key">The name of the parameter.</param>
- /// <param name="value">The value of the argument.</param>
- /// <remarks>
- /// This method is useful if the Relying Party wants to recall some value
- /// when and if a positive assertion comes back from the Provider.
- /// </remarks>
- internal void AddReturnToArguments(string key, string value) {
- var pair = new KeyValuePair<string, string>(key, value);
- this.AddReturnToArguments(new[] { pair });
- }
-
- /// <summary>
- /// Gets the value of the openid.mode parameter based on the protocol version and immediate flag.
- /// </summary>
- /// <param name="version">The OpenID version to use.</param>
- /// <param name="mode">
- /// <see cref="AuthenticationRequestMode.Immediate"/> for asynchronous javascript clients;
- /// <see cref="AuthenticationRequestMode.Setup"/> to allow the Provider to interact with the user in order to complete authentication.
- /// </param>
- /// <returns>checkid_immediate or checkid_setup</returns>
- private static string GetMode(Version version, AuthenticationRequestMode mode) {
- ErrorUtilities.VerifyArgumentNotNull(version, "version");
-
- Protocol protocol = Protocol.Lookup(version);
- return mode == AuthenticationRequestMode.Immediate ? protocol.Args.Mode.checkid_immediate : protocol.Args.Mode.checkid_setup;
- }
- }
-}
+//----------------------------------------------------------------------- +// <copyright file="SignedResponseRequest.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OpenId.Messages { + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using System.Text; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OpenId.RelyingParty; + + /// <summary> + /// An indirect request from a Relying Party to a Provider where the response + /// is expected to be signed. + /// </summary> + internal class SignedResponseRequest : RequestBase, IProtocolMessageWithExtensions { + /// <summary> + /// Backing store for the <see cref="Extensions"/> property. + /// </summary> + private IList<IExtensionMessage> extensions = new List<IExtensionMessage>(); + + /// <summary> + /// Initializes a new instance of the <see cref="SignedResponseRequest"/> class. + /// </summary> + /// <param name="version">The OpenID version to use.</param> + /// <param name="providerEndpoint">The Provider endpoint that receives this message.</param> + /// <param name="mode"> + /// <see cref="AuthenticationRequestMode.Immediate"/> for asynchronous javascript clients; + /// <see cref="AuthenticationRequestMode.Setup"/> to allow the Provider to interact with the user in order to complete authentication. + /// </param> + internal SignedResponseRequest(Version version, Uri providerEndpoint, AuthenticationRequestMode mode) : + base(version, providerEndpoint, GetMode(version, mode), DotNetOpenAuth.Messaging.MessageTransport.Indirect) { + } + + #region IProtocolMessageWithExtensions Members + + /// <summary> + /// Gets the list of extensions that are included with this message. + /// </summary> + /// <value></value> + /// <remarks> + /// Implementations of this interface should ensure that this property never returns null. + /// </remarks> + public IList<IExtensionMessage> Extensions { + get { return this.extensions; } + } + + #endregion + + /// <summary> + /// Gets a value indicating whether the Provider is allowed to interact with the user + /// as part of authentication. + /// </summary> + /// <value><c>true</c> if using OpenID immediate mode; otherwise, <c>false</c>.</value> + internal bool Immediate { + get { return String.Equals(this.Mode, Protocol.Args.Mode.checkid_immediate, StringComparison.Ordinal); } + } + + /// <summary> + /// Gets or sets the handle of the association the RP would like the Provider + /// to use for signing a positive assertion in the response message. + /// </summary> + /// <value>A handle for an association between the Relying Party and the OP + /// that SHOULD be used to sign the response. </value> + /// <remarks> + /// If no association handle is sent, the transaction will take place in Stateless Mode + /// (Verifying Directly with the OpenID Provider). + /// </remarks> + [MessagePart("openid.assoc_handle", IsRequired = false, AllowEmpty = false)] + internal string AssociationHandle { get; set; } + + /// <summary> + /// Gets or sets the URL the Provider should redirect the user agent to following + /// the authentication attempt. + /// </summary> + /// <value>URL to which the OP SHOULD return the User-Agent with the response + /// indicating the status of the request.</value> + /// <remarks> + /// <para>If this value is not sent in the request it signifies that the Relying Party + /// does not wish for the end user to be returned. </para> + /// <para>The return_to URL MAY be used as a mechanism for the Relying Party to attach + /// context about the authentication request to the authentication response. + /// This document does not define a mechanism by which the RP can ensure that query + /// parameters are not modified by outside parties; such a mechanism can be defined + /// by the RP itself. </para> + /// </remarks> + [MessagePart("openid.return_to", IsRequired = true, AllowEmpty = false)] + [MessagePart("openid.return_to", IsRequired = false, AllowEmpty = false, MinVersion = "2.0")] + internal Uri ReturnTo { get; set; } + + /// <summary> + /// Gets or sets the Relying Party discovery URL the Provider may use to verify the + /// source of the authentication request. + /// </summary> + /// <value> + /// URL pattern the OP SHOULD ask the end user to trust. See Section 9.2 (Realms). + /// This value MUST be sent if openid.return_to is omitted. + /// Default: The <see cref="ReturnTo"/> URL. + /// </value> + [MessagePart("openid.trust_root", IsRequired = false, AllowEmpty = false)] + [MessagePart("openid.realm", IsRequired = false, AllowEmpty = false, MinVersion = "2.0")] + internal Realm Realm { get; set; } + + /// <summary> + /// Checks the message state for conformity to the protocol specification + /// and throws an exception if the message is invalid. + /// </summary> + /// <remarks> + /// <para>Some messages have required fields, or combinations of fields that must relate to each other + /// in specialized ways. After deserializing a message, this method checks the state of the + /// message to see if it conforms to the protocol.</para> + /// <para>Note that this property should <i>not</i> check signatures or perform any state checks + /// outside this scope of this particular message.</para> + /// </remarks> + /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception> + public override void EnsureValidMessage() { + base.EnsureValidMessage(); + + if (this.Realm == null) { + // Set the default Realm per the spec if it is not explicitly given. + this.Realm = this.ReturnTo; + } else if (this.ReturnTo != null) { + // Verify that the realm and return_to agree. + ErrorUtilities.VerifyProtocol(this.Realm.Contains(this.ReturnTo), OpenIdStrings.ReturnToNotUnderRealm, this.ReturnTo, this.Realm); + } + } + + /// <summary> + /// Adds parameters to the return_to querystring. + /// </summary> + /// <param name="keysValues">The keys=value pairs to add to the return_to query string.</param> + /// <remarks> + /// This method is useful if the Relying Party wants to recall some value + /// when and if a positive assertion comes back from the Provider. + /// </remarks> + internal void AddReturnToArguments(IEnumerable<KeyValuePair<string, string>> keysValues) { + ErrorUtilities.VerifyArgumentNotNull(keysValues, "keysValues"); + UriBuilder returnToBuilder = new UriBuilder(this.ReturnTo); + returnToBuilder.AppendQueryArgs(keysValues); + this.ReturnTo = returnToBuilder.Uri; + } + + /// <summary> + /// Adds a parameter to the return_to querystring. + /// </summary> + /// <param name="key">The name of the parameter.</param> + /// <param name="value">The value of the argument.</param> + /// <remarks> + /// This method is useful if the Relying Party wants to recall some value + /// when and if a positive assertion comes back from the Provider. + /// </remarks> + internal void AddReturnToArguments(string key, string value) { + var pair = new KeyValuePair<string, string>(key, value); + this.AddReturnToArguments(new[] { pair }); + } + + /// <summary> + /// Gets the value of the openid.mode parameter based on the protocol version and immediate flag. + /// </summary> + /// <param name="version">The OpenID version to use.</param> + /// <param name="mode"> + /// <see cref="AuthenticationRequestMode.Immediate"/> for asynchronous javascript clients; + /// <see cref="AuthenticationRequestMode.Setup"/> to allow the Provider to interact with the user in order to complete authentication. + /// </param> + /// <returns>checkid_immediate or checkid_setup</returns> + private static string GetMode(Version version, AuthenticationRequestMode mode) { + ErrorUtilities.VerifyArgumentNotNull(version, "version"); + + Protocol protocol = Protocol.Lookup(version); + return mode == AuthenticationRequestMode.Immediate ? protocol.Args.Mode.checkid_immediate : protocol.Args.Mode.checkid_setup; + } + } +} diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs b/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs index ad62c27..c8566f8 100644 --- a/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs +++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs @@ -1,333 +1,333 @@ -//------------------------------------------------------------------------------
-// <auto-generated>
-// This code was generated by a tool.
-// Runtime Version:2.0.50727.3521
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-// </auto-generated>
-//------------------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OpenId {
- using System;
-
-
- /// <summary>
- /// A strongly-typed resource class, for looking up localized strings, etc.
- /// </summary>
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class OpenIdStrings {
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal OpenIdStrings() {
- }
-
- /// <summary>
- /// Returns the cached ResourceManager instance used by this class.
- /// </summary>
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
- get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DotNetOpenAuth.OpenId.OpenIdStrings", typeof(OpenIdStrings).Assembly);
- resourceMan = temp;
- }
- return resourceMan;
- }
- }
-
- /// <summary>
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- /// </summary>
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
- get {
- return resourceCulture;
- }
- set {
- resourceCulture = value;
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The association and nonce stores must either be both null or both non-null..
- /// </summary>
- internal static string AssociationAndNonceStoresMustBeBothNullOrBothNonNull {
- get {
- return ResourceManager.GetString("AssociationAndNonceStoresMustBeBothNullOrBothNonNull", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The length of the shared secret ({0}) does not match the length required by the association type ('{1}')..
- /// </summary>
- internal static string AssociationSecretAndTypeLengthMismatch {
- get {
- return ResourceManager.GetString("AssociationSecretAndTypeLengthMismatch", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The length of the encrypted shared secret ({0}) does not match the length of the hashing algorithm ({1})..
- /// </summary>
- internal static string AssociationSecretHashLengthMismatch {
- get {
- return ResourceManager.GetString("AssociationSecretHashLengthMismatch", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The private data supplied does not meet the requirements of any known Association type. Its length may be too short, or it may have been corrupted..
- /// </summary>
- internal static string BadAssociationPrivateData {
- get {
- return ResourceManager.GetString("BadAssociationPrivateData", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to A Simple Registration request can only generate a response on the receiving end..
- /// </summary>
- internal static string CallDeserializeBeforeCreateResponse {
- get {
- return ResourceManager.GetString("CallDeserializeBeforeCreateResponse", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The openid.claimed_id and openid.identity parameters must both be present or both be absent..
- /// </summary>
- internal static string ClaimedIdAndLocalIdMustBothPresentOrAbsent {
- get {
- return ResourceManager.GetString("ClaimedIdAndLocalIdMustBothPresentOrAbsent", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The following properties must be set before the Diffie-Hellman algorithm can generate a public key: {0}.
- /// </summary>
- internal static string DiffieHellmanRequiredPropertiesNotSet {
- get {
- return ResourceManager.GetString("DiffieHellmanRequiredPropertiesNotSet", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to URI is not SSL yet requireSslDiscovery is set to true..
- /// </summary>
- internal static string ExplicitHttpUriSuppliedWithSslRequirement {
- get {
- return ResourceManager.GetString("ExplicitHttpUriSuppliedWithSslRequirement", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to An extension sharing namespace '{0}' has already been added. Only one extension per namespace is allowed in a given request..
- /// </summary>
- internal static string ExtensionAlreadyAddedWithSameTypeURI {
- get {
- return ResourceManager.GetString("ExtensionAlreadyAddedWithSameTypeURI", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Cannot encode '{0}' because it contains an illegal character for Key-Value Form encoding. (line {1}: '{2}').
- /// </summary>
- internal static string InvalidCharacterInKeyValueFormInput {
- get {
- return ResourceManager.GetString("InvalidCharacterInKeyValueFormInput", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Cannot decode Key-Value Form because a line was found without a '{0}' character. (line {1}: '{2}').
- /// </summary>
- internal static string InvalidKeyValueFormCharacterMissing {
- get {
- return ResourceManager.GetString("InvalidKeyValueFormCharacterMissing", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The scheme must be http or https but was '{0}'..
- /// </summary>
- internal static string InvalidScheme {
- get {
- return ResourceManager.GetString("InvalidScheme", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The value '{0}' is not a valid URI..
- /// </summary>
- internal static string InvalidUri {
- get {
- return ResourceManager.GetString("InvalidUri", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Not a recognized XRI format: '{0}'..
- /// </summary>
- internal static string InvalidXri {
- get {
- return ResourceManager.GetString("InvalidXri", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The list of keys do not match the provided dictionary..
- /// </summary>
- internal static string KeysListAndDictionaryDoNotMatch {
- get {
- return ResourceManager.GetString("KeysListAndDictionaryDoNotMatch", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to No recognized association type matches the requested length of {0}..
- /// </summary>
- internal static string NoAssociationTypeFoundByLength {
- get {
- return ResourceManager.GetString("NoAssociationTypeFoundByLength", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to No recognized association type matches the requested name of '{0}'..
- /// </summary>
- internal static string NoAssociationTypeFoundByName {
- get {
- return ResourceManager.GetString("NoAssociationTypeFoundByName", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Unless using transport layer encryption, "no-encryption" MUST NOT be used..
- /// </summary>
- internal static string NoEncryptionSessionRequiresHttps {
- get {
- return ResourceManager.GetString("NoEncryptionSessionRequiresHttps", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Diffie-Hellman session type '{0}' not found for OpenID {1}..
- /// </summary>
- internal static string NoSessionTypeFound {
- get {
- return ResourceManager.GetString("NoSessionTypeFound", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Unable to determine the version of the OpenID protocol implemented by the Provider at endpoint '{0}'..
- /// </summary>
- internal static string ProviderVersionUnrecognized {
- get {
- return ResourceManager.GetString("ProviderVersionUnrecognized", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to An HTTP request to the realm URL ({0}) resulted in a redirect, which is not allowed during relying party discovery..
- /// </summary>
- internal static string RealmCausedRedirectUponDiscovery {
- get {
- return ResourceManager.GetString("RealmCausedRedirectUponDiscovery", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to return_to '{0}' not under realm '{1}'..
- /// </summary>
- internal static string ReturnToNotUnderRealm {
- get {
- return ResourceManager.GetString("ReturnToNotUnderRealm", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The {0} parameter ({1}) does not match the actual URL ({2}) the request was made with..
- /// </summary>
- internal static string ReturnToParamDoesNotMatchRequestUrl {
- get {
- return ResourceManager.GetString("ReturnToParamDoesNotMatchRequestUrl", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The openid.return_to parameter is required in the request message in order to construct a response, but that parameter was missing..
- /// </summary>
- internal static string ReturnToRequiredForResponse {
- get {
- return ResourceManager.GetString("ReturnToRequiredForResponse", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The following parameter(s) are not included in the signature but must be: {0}.
- /// </summary>
- internal static string SignatureDoesNotIncludeMandatoryParts {
- get {
- return ResourceManager.GetString("SignatureDoesNotIncludeMandatoryParts", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Invalid birthdate value. Must be in the form yyyy-MM-dd..
- /// </summary>
- internal static string SregInvalidBirthdate {
- get {
- return ResourceManager.GetString("SregInvalidBirthdate", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The type must implement {0}..
- /// </summary>
- internal static string TypeMustImplementX {
- get {
- return ResourceManager.GetString("TypeMustImplementX", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Unsolicited assertions are not allowed from 1.0 OpenID Providers..
- /// </summary>
- internal static string UnsolicitedAssertionsNotAllowedFrom1xOPs {
- get {
- return ResourceManager.GetString("UnsolicitedAssertionsNotAllowedFrom1xOPs", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The openid.user_setup_url parameter is required when sending negative assertion messages in response to immediate mode requests..
- /// </summary>
- internal static string UserSetupUrlRequiredInImmediateNegativeResponse {
- get {
- return ResourceManager.GetString("UserSetupUrlRequiredInImmediateNegativeResponse", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to XRI resolution failed..
- /// </summary>
- internal static string XriResolutionFailed {
- get {
- return ResourceManager.GetString("XriResolutionFailed", resourceCulture);
- }
- }
- }
-}
+//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:2.0.50727.3521 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace DotNetOpenAuth.OpenId { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class OpenIdStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal OpenIdStrings() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DotNetOpenAuth.OpenId.OpenIdStrings", typeof(OpenIdStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// Looks up a localized string similar to The association and nonce stores must either be both null or both non-null.. + /// </summary> + internal static string AssociationAndNonceStoresMustBeBothNullOrBothNonNull { + get { + return ResourceManager.GetString("AssociationAndNonceStoresMustBeBothNullOrBothNonNull", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The length of the shared secret ({0}) does not match the length required by the association type ('{1}').. + /// </summary> + internal static string AssociationSecretAndTypeLengthMismatch { + get { + return ResourceManager.GetString("AssociationSecretAndTypeLengthMismatch", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The length of the encrypted shared secret ({0}) does not match the length of the hashing algorithm ({1}).. + /// </summary> + internal static string AssociationSecretHashLengthMismatch { + get { + return ResourceManager.GetString("AssociationSecretHashLengthMismatch", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The private data supplied does not meet the requirements of any known Association type. Its length may be too short, or it may have been corrupted.. + /// </summary> + internal static string BadAssociationPrivateData { + get { + return ResourceManager.GetString("BadAssociationPrivateData", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to A Simple Registration request can only generate a response on the receiving end.. + /// </summary> + internal static string CallDeserializeBeforeCreateResponse { + get { + return ResourceManager.GetString("CallDeserializeBeforeCreateResponse", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The openid.claimed_id and openid.identity parameters must both be present or both be absent.. + /// </summary> + internal static string ClaimedIdAndLocalIdMustBothPresentOrAbsent { + get { + return ResourceManager.GetString("ClaimedIdAndLocalIdMustBothPresentOrAbsent", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The following properties must be set before the Diffie-Hellman algorithm can generate a public key: {0}. + /// </summary> + internal static string DiffieHellmanRequiredPropertiesNotSet { + get { + return ResourceManager.GetString("DiffieHellmanRequiredPropertiesNotSet", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to URI is not SSL yet requireSslDiscovery is set to true.. + /// </summary> + internal static string ExplicitHttpUriSuppliedWithSslRequirement { + get { + return ResourceManager.GetString("ExplicitHttpUriSuppliedWithSslRequirement", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to An extension sharing namespace '{0}' has already been added. Only one extension per namespace is allowed in a given request.. + /// </summary> + internal static string ExtensionAlreadyAddedWithSameTypeURI { + get { + return ResourceManager.GetString("ExtensionAlreadyAddedWithSameTypeURI", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Cannot encode '{0}' because it contains an illegal character for Key-Value Form encoding. (line {1}: '{2}'). + /// </summary> + internal static string InvalidCharacterInKeyValueFormInput { + get { + return ResourceManager.GetString("InvalidCharacterInKeyValueFormInput", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Cannot decode Key-Value Form because a line was found without a '{0}' character. (line {1}: '{2}'). + /// </summary> + internal static string InvalidKeyValueFormCharacterMissing { + get { + return ResourceManager.GetString("InvalidKeyValueFormCharacterMissing", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The scheme must be http or https but was '{0}'.. + /// </summary> + internal static string InvalidScheme { + get { + return ResourceManager.GetString("InvalidScheme", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The value '{0}' is not a valid URI.. + /// </summary> + internal static string InvalidUri { + get { + return ResourceManager.GetString("InvalidUri", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Not a recognized XRI format: '{0}'.. + /// </summary> + internal static string InvalidXri { + get { + return ResourceManager.GetString("InvalidXri", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The list of keys do not match the provided dictionary.. + /// </summary> + internal static string KeysListAndDictionaryDoNotMatch { + get { + return ResourceManager.GetString("KeysListAndDictionaryDoNotMatch", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to No recognized association type matches the requested length of {0}.. + /// </summary> + internal static string NoAssociationTypeFoundByLength { + get { + return ResourceManager.GetString("NoAssociationTypeFoundByLength", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to No recognized association type matches the requested name of '{0}'.. + /// </summary> + internal static string NoAssociationTypeFoundByName { + get { + return ResourceManager.GetString("NoAssociationTypeFoundByName", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Unless using transport layer encryption, "no-encryption" MUST NOT be used.. + /// </summary> + internal static string NoEncryptionSessionRequiresHttps { + get { + return ResourceManager.GetString("NoEncryptionSessionRequiresHttps", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Diffie-Hellman session type '{0}' not found for OpenID {1}.. + /// </summary> + internal static string NoSessionTypeFound { + get { + return ResourceManager.GetString("NoSessionTypeFound", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Unable to determine the version of the OpenID protocol implemented by the Provider at endpoint '{0}'.. + /// </summary> + internal static string ProviderVersionUnrecognized { + get { + return ResourceManager.GetString("ProviderVersionUnrecognized", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to An HTTP request to the realm URL ({0}) resulted in a redirect, which is not allowed during relying party discovery.. + /// </summary> + internal static string RealmCausedRedirectUponDiscovery { + get { + return ResourceManager.GetString("RealmCausedRedirectUponDiscovery", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to return_to '{0}' not under realm '{1}'.. + /// </summary> + internal static string ReturnToNotUnderRealm { + get { + return ResourceManager.GetString("ReturnToNotUnderRealm", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The {0} parameter ({1}) does not match the actual URL ({2}) the request was made with.. + /// </summary> + internal static string ReturnToParamDoesNotMatchRequestUrl { + get { + return ResourceManager.GetString("ReturnToParamDoesNotMatchRequestUrl", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The openid.return_to parameter is required in the request message in order to construct a response, but that parameter was missing.. + /// </summary> + internal static string ReturnToRequiredForResponse { + get { + return ResourceManager.GetString("ReturnToRequiredForResponse", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The following parameter(s) are not included in the signature but must be: {0}. + /// </summary> + internal static string SignatureDoesNotIncludeMandatoryParts { + get { + return ResourceManager.GetString("SignatureDoesNotIncludeMandatoryParts", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Invalid birthdate value. Must be in the form yyyy-MM-dd.. + /// </summary> + internal static string SregInvalidBirthdate { + get { + return ResourceManager.GetString("SregInvalidBirthdate", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The type must implement {0}.. + /// </summary> + internal static string TypeMustImplementX { + get { + return ResourceManager.GetString("TypeMustImplementX", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Unsolicited assertions are not allowed from 1.0 OpenID Providers.. + /// </summary> + internal static string UnsolicitedAssertionsNotAllowedFrom1xOPs { + get { + return ResourceManager.GetString("UnsolicitedAssertionsNotAllowedFrom1xOPs", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The openid.user_setup_url parameter is required when sending negative assertion messages in response to immediate mode requests.. + /// </summary> + internal static string UserSetupUrlRequiredInImmediateNegativeResponse { + get { + return ResourceManager.GetString("UserSetupUrlRequiredInImmediateNegativeResponse", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to XRI resolution failed.. + /// </summary> + internal static string XriResolutionFailed { + get { + return ResourceManager.GetString("XriResolutionFailed", resourceCulture); + } + } + } +} diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx index c1d755b..8b5e09f 100644 --- a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx +++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx @@ -1,210 +1,210 @@ -<?xml version="1.0" encoding="utf-8"?>
-<root>
- <!--
- Microsoft ResX Schema
-
- Version 2.0
-
- The primary goals of this format is to allow a simple XML format
- that is mostly human readable. The generation and parsing of the
- various data types are done through the TypeConverter classes
- associated with the data types.
-
- Example:
-
- ... ado.net/XML headers & schema ...
- <resheader name="resmimetype">text/microsoft-resx</resheader>
- <resheader name="version">2.0</resheader>
- <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
- <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
- <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
- <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
- <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
- <value>[base64 mime encoded serialized .NET Framework object]</value>
- </data>
- <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
- <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
- <comment>This is a comment</comment>
- </data>
-
- There are any number of "resheader" rows that contain simple
- name/value pairs.
-
- Each data row contains a name, and value. The row also contains a
- type or mimetype. Type corresponds to a .NET class that support
- text/value conversion through the TypeConverter architecture.
- Classes that don't support this are serialized and stored with the
- mimetype set.
-
- The mimetype is used for serialized objects, and tells the
- ResXResourceReader how to depersist the object. This is currently not
- extensible. For a given mimetype the value must be set accordingly:
-
- Note - application/x-microsoft.net.object.binary.base64 is the format
- that the ResXResourceWriter will generate, however the reader can
- read any of the formats listed below.
-
- mimetype: application/x-microsoft.net.object.binary.base64
- value : The object must be serialized with
- : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.soap.base64
- value : The object must be serialized with
- : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
- : and then encoded with base64 encoding.
-
- mimetype: application/x-microsoft.net.object.bytearray.base64
- value : The object must be serialized into a byte array
- : using a System.ComponentModel.TypeConverter
- : and then encoded with base64 encoding.
- -->
- <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
- <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
- <xsd:element name="root" msdata:IsDataSet="true">
- <xsd:complexType>
- <xsd:choice maxOccurs="unbounded">
- <xsd:element name="metadata">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" />
- </xsd:sequence>
- <xsd:attribute name="name" use="required" type="xsd:string" />
- <xsd:attribute name="type" type="xsd:string" />
- <xsd:attribute name="mimetype" type="xsd:string" />
- <xsd:attribute ref="xml:space" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="assembly">
- <xsd:complexType>
- <xsd:attribute name="alias" type="xsd:string" />
- <xsd:attribute name="name" type="xsd:string" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="data">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
- <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
- <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
- <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
- <xsd:attribute ref="xml:space" />
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="resheader">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required" />
- </xsd:complexType>
- </xsd:element>
- </xsd:choice>
- </xsd:complexType>
- </xsd:element>
- </xsd:schema>
- <resheader name="resmimetype">
- <value>text/microsoft-resx</value>
- </resheader>
- <resheader name="version">
- <value>2.0</value>
- </resheader>
- <resheader name="reader">
- <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
- </resheader>
- <resheader name="writer">
- <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
- </resheader>
- <data name="AssociationAndNonceStoresMustBeBothNullOrBothNonNull" xml:space="preserve">
- <value>The association and nonce stores must either be both null or both non-null.</value>
- </data>
- <data name="AssociationSecretAndTypeLengthMismatch" xml:space="preserve">
- <value>The length of the shared secret ({0}) does not match the length required by the association type ('{1}').</value>
- </data>
- <data name="AssociationSecretHashLengthMismatch" xml:space="preserve">
- <value>The length of the encrypted shared secret ({0}) does not match the length of the hashing algorithm ({1}).</value>
- </data>
- <data name="BadAssociationPrivateData" xml:space="preserve">
- <value>The private data supplied does not meet the requirements of any known Association type. Its length may be too short, or it may have been corrupted.</value>
- </data>
- <data name="CallDeserializeBeforeCreateResponse" xml:space="preserve">
- <value>A Simple Registration request can only generate a response on the receiving end.</value>
- </data>
- <data name="ClaimedIdAndLocalIdMustBothPresentOrAbsent" xml:space="preserve">
- <value>The openid.claimed_id and openid.identity parameters must both be present or both be absent.</value>
- </data>
- <data name="DiffieHellmanRequiredPropertiesNotSet" xml:space="preserve">
- <value>The following properties must be set before the Diffie-Hellman algorithm can generate a public key: {0}</value>
- </data>
- <data name="ExplicitHttpUriSuppliedWithSslRequirement" xml:space="preserve">
- <value>URI is not SSL yet requireSslDiscovery is set to true.</value>
- </data>
- <data name="ExtensionAlreadyAddedWithSameTypeURI" xml:space="preserve">
- <value>An extension sharing namespace '{0}' has already been added. Only one extension per namespace is allowed in a given request.</value>
- </data>
- <data name="InvalidCharacterInKeyValueFormInput" xml:space="preserve">
- <value>Cannot encode '{0}' because it contains an illegal character for Key-Value Form encoding. (line {1}: '{2}')</value>
- </data>
- <data name="InvalidKeyValueFormCharacterMissing" xml:space="preserve">
- <value>Cannot decode Key-Value Form because a line was found without a '{0}' character. (line {1}: '{2}')</value>
- </data>
- <data name="InvalidScheme" xml:space="preserve">
- <value>The scheme must be http or https but was '{0}'.</value>
- </data>
- <data name="InvalidUri" xml:space="preserve">
- <value>The value '{0}' is not a valid URI.</value>
- </data>
- <data name="InvalidXri" xml:space="preserve">
- <value>Not a recognized XRI format: '{0}'.</value>
- </data>
- <data name="KeysListAndDictionaryDoNotMatch" xml:space="preserve">
- <value>The list of keys do not match the provided dictionary.</value>
- </data>
- <data name="NoAssociationTypeFoundByLength" xml:space="preserve">
- <value>No recognized association type matches the requested length of {0}.</value>
- </data>
- <data name="NoAssociationTypeFoundByName" xml:space="preserve">
- <value>No recognized association type matches the requested name of '{0}'.</value>
- </data>
- <data name="NoEncryptionSessionRequiresHttps" xml:space="preserve">
- <value>Unless using transport layer encryption, "no-encryption" MUST NOT be used.</value>
- </data>
- <data name="NoSessionTypeFound" xml:space="preserve">
- <value>Diffie-Hellman session type '{0}' not found for OpenID {1}.</value>
- </data>
- <data name="ProviderVersionUnrecognized" xml:space="preserve">
- <value>Unable to determine the version of the OpenID protocol implemented by the Provider at endpoint '{0}'.</value>
- </data>
- <data name="RealmCausedRedirectUponDiscovery" xml:space="preserve">
- <value>An HTTP request to the realm URL ({0}) resulted in a redirect, which is not allowed during relying party discovery.</value>
- </data>
- <data name="ReturnToNotUnderRealm" xml:space="preserve">
- <value>return_to '{0}' not under realm '{1}'.</value>
- </data>
- <data name="ReturnToParamDoesNotMatchRequestUrl" xml:space="preserve">
- <value>The {0} parameter ({1}) does not match the actual URL ({2}) the request was made with.</value>
- </data>
- <data name="ReturnToRequiredForResponse" xml:space="preserve">
- <value>The openid.return_to parameter is required in the request message in order to construct a response, but that parameter was missing.</value>
- </data>
- <data name="SignatureDoesNotIncludeMandatoryParts" xml:space="preserve">
- <value>The following parameter(s) are not included in the signature but must be: {0}</value>
- </data>
- <data name="SregInvalidBirthdate" xml:space="preserve">
- <value>Invalid birthdate value. Must be in the form yyyy-MM-dd.</value>
- </data>
- <data name="TypeMustImplementX" xml:space="preserve">
- <value>The type must implement {0}.</value>
- </data>
- <data name="UnsolicitedAssertionsNotAllowedFrom1xOPs" xml:space="preserve">
- <value>Unsolicited assertions are not allowed from 1.0 OpenID Providers.</value>
- </data>
- <data name="UserSetupUrlRequiredInImmediateNegativeResponse" xml:space="preserve">
- <value>The openid.user_setup_url parameter is required when sending negative assertion messages in response to immediate mode requests.</value>
- </data>
- <data name="XriResolutionFailed" xml:space="preserve">
- <value>XRI resolution failed.</value>
- </data>
+<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="AssociationAndNonceStoresMustBeBothNullOrBothNonNull" xml:space="preserve"> + <value>The association and nonce stores must either be both null or both non-null.</value> + </data> + <data name="AssociationSecretAndTypeLengthMismatch" xml:space="preserve"> + <value>The length of the shared secret ({0}) does not match the length required by the association type ('{1}').</value> + </data> + <data name="AssociationSecretHashLengthMismatch" xml:space="preserve"> + <value>The length of the encrypted shared secret ({0}) does not match the length of the hashing algorithm ({1}).</value> + </data> + <data name="BadAssociationPrivateData" xml:space="preserve"> + <value>The private data supplied does not meet the requirements of any known Association type. Its length may be too short, or it may have been corrupted.</value> + </data> + <data name="CallDeserializeBeforeCreateResponse" xml:space="preserve"> + <value>A Simple Registration request can only generate a response on the receiving end.</value> + </data> + <data name="ClaimedIdAndLocalIdMustBothPresentOrAbsent" xml:space="preserve"> + <value>The openid.claimed_id and openid.identity parameters must both be present or both be absent.</value> + </data> + <data name="DiffieHellmanRequiredPropertiesNotSet" xml:space="preserve"> + <value>The following properties must be set before the Diffie-Hellman algorithm can generate a public key: {0}</value> + </data> + <data name="ExplicitHttpUriSuppliedWithSslRequirement" xml:space="preserve"> + <value>URI is not SSL yet requireSslDiscovery is set to true.</value> + </data> + <data name="ExtensionAlreadyAddedWithSameTypeURI" xml:space="preserve"> + <value>An extension sharing namespace '{0}' has already been added. Only one extension per namespace is allowed in a given request.</value> + </data> + <data name="InvalidCharacterInKeyValueFormInput" xml:space="preserve"> + <value>Cannot encode '{0}' because it contains an illegal character for Key-Value Form encoding. (line {1}: '{2}')</value> + </data> + <data name="InvalidKeyValueFormCharacterMissing" xml:space="preserve"> + <value>Cannot decode Key-Value Form because a line was found without a '{0}' character. (line {1}: '{2}')</value> + </data> + <data name="InvalidScheme" xml:space="preserve"> + <value>The scheme must be http or https but was '{0}'.</value> + </data> + <data name="InvalidUri" xml:space="preserve"> + <value>The value '{0}' is not a valid URI.</value> + </data> + <data name="InvalidXri" xml:space="preserve"> + <value>Not a recognized XRI format: '{0}'.</value> + </data> + <data name="KeysListAndDictionaryDoNotMatch" xml:space="preserve"> + <value>The list of keys do not match the provided dictionary.</value> + </data> + <data name="NoAssociationTypeFoundByLength" xml:space="preserve"> + <value>No recognized association type matches the requested length of {0}.</value> + </data> + <data name="NoAssociationTypeFoundByName" xml:space="preserve"> + <value>No recognized association type matches the requested name of '{0}'.</value> + </data> + <data name="NoEncryptionSessionRequiresHttps" xml:space="preserve"> + <value>Unless using transport layer encryption, "no-encryption" MUST NOT be used.</value> + </data> + <data name="NoSessionTypeFound" xml:space="preserve"> + <value>Diffie-Hellman session type '{0}' not found for OpenID {1}.</value> + </data> + <data name="ProviderVersionUnrecognized" xml:space="preserve"> + <value>Unable to determine the version of the OpenID protocol implemented by the Provider at endpoint '{0}'.</value> + </data> + <data name="RealmCausedRedirectUponDiscovery" xml:space="preserve"> + <value>An HTTP request to the realm URL ({0}) resulted in a redirect, which is not allowed during relying party discovery.</value> + </data> + <data name="ReturnToNotUnderRealm" xml:space="preserve"> + <value>return_to '{0}' not under realm '{1}'.</value> + </data> + <data name="ReturnToParamDoesNotMatchRequestUrl" xml:space="preserve"> + <value>The {0} parameter ({1}) does not match the actual URL ({2}) the request was made with.</value> + </data> + <data name="ReturnToRequiredForResponse" xml:space="preserve"> + <value>The openid.return_to parameter is required in the request message in order to construct a response, but that parameter was missing.</value> + </data> + <data name="SignatureDoesNotIncludeMandatoryParts" xml:space="preserve"> + <value>The following parameter(s) are not included in the signature but must be: {0}</value> + </data> + <data name="SregInvalidBirthdate" xml:space="preserve"> + <value>Invalid birthdate value. Must be in the form yyyy-MM-dd.</value> + </data> + <data name="TypeMustImplementX" xml:space="preserve"> + <value>The type must implement {0}.</value> + </data> + <data name="UnsolicitedAssertionsNotAllowedFrom1xOPs" xml:space="preserve"> + <value>Unsolicited assertions are not allowed from 1.0 OpenID Providers.</value> + </data> + <data name="UserSetupUrlRequiredInImmediateNegativeResponse" xml:space="preserve"> + <value>The openid.user_setup_url parameter is required when sending negative assertion messages in response to immediate mode requests.</value> + </data> + <data name="XriResolutionFailed" xml:space="preserve"> + <value>XRI resolution failed.</value> + </data> </root>
\ No newline at end of file diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequestMode.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequestMode.cs index 15e0ad8..40ea66a 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequestMode.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequestMode.cs @@ -1,26 +1,26 @@ -//-----------------------------------------------------------------------
-// <copyright file="AuthenticationRequestMode.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OpenId.RelyingParty {
- /// <summary>
- /// Indicates the mode the Provider should use while authenticating the end user.
- /// </summary>
- public enum AuthenticationRequestMode {
- /// <summary>
- /// The Provider should use whatever credentials are immediately available
- /// to determine whether the end user owns the Identifier. If sufficient
- /// credentials (i.e. cookies) are not immediately available, the Provider
- /// should fail rather than prompt the user.
- /// </summary>
- Immediate,
-
- /// <summary>
- /// The Provider should determine whether the end user owns the Identifier,
- /// displaying a web page to the user to login etc., if necessary.
- /// </summary>
- Setup,
- }
+//----------------------------------------------------------------------- +// <copyright file="AuthenticationRequestMode.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OpenId.RelyingParty { + /// <summary> + /// Indicates the mode the Provider should use while authenticating the end user. + /// </summary> + public enum AuthenticationRequestMode { + /// <summary> + /// The Provider should use whatever credentials are immediately available + /// to determine whether the end user owns the Identifier. If sufficient + /// credentials (i.e. cookies) are not immediately available, the Provider + /// should fail rather than prompt the user. + /// </summary> + Immediate, + + /// <summary> + /// The Provider should determine whether the end user owns the Identifier, + /// displaying a web page to the user to login etc., if necessary. + /// </summary> + Setup, + } }
\ No newline at end of file diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs index f4e03a5..ed9a7ca 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs @@ -1,110 +1,110 @@ -//-----------------------------------------------------------------------
-// <copyright file="OpenIdRelyingParty.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OpenId.RelyingParty {
- using System;
- using DotNetOpenAuth.Configuration;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.Messaging.Bindings;
- using DotNetOpenAuth.OpenId.ChannelElements;
- using DotNetOpenAuth.OpenId.Messages;
-
- /// <summary>
- /// Provides the programmatic facilities to act as an OpenId consumer.
- /// </summary>
- public sealed class OpenIdRelyingParty {
- /// <summary>
- /// The untrusted web request handler we use (and share) by default across all RP instances.
- /// </summary>
- private static IDirectSslWebRequestHandler defaultUntrustedWebRequestHandler = new UntrustedWebRequestHandler();
-
- /// <summary>
- /// Backing field for the <see cref="SecuritySettings"/> property.
- /// </summary>
- private RelyingPartySecuritySettings securitySettings;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="OpenIdRelyingParty"/> class.
- /// </summary>
- /// <param name="associationStore">The association store. If null, the relying party will always operate in "dumb mode".</param>
- /// <param name="nonceStore">The nonce store to use. If null, the relying party will always operate in "dumb mode".</param>
- /// <param name="secretStore">The secret store to use. If null, the relying party will always operate in "dumb mode".</param>
- public OpenIdRelyingParty(IAssociationStore<Uri> associationStore, INonceStore nonceStore, IPrivateSecretStore secretStore) {
- // TODO: fix this so that a null association store is supported as 'dumb mode only'.
- ErrorUtilities.VerifyArgumentNotNull(associationStore, "associationStore");
- ErrorUtilities.VerifyArgumentNotNull(nonceStore, "nonceStore");
- ErrorUtilities.VerifyArgumentNotNull(secretStore, "secretStore");
- ErrorUtilities.VerifyArgument((associationStore == null) == (nonceStore == null), OpenIdStrings.AssociationAndNonceStoresMustBeBothNullOrBothNonNull);
-
- this.Channel = new OpenIdChannel(associationStore, nonceStore, secretStore);
- this.AssociationStore = associationStore;
- this.SecuritySettings = RelyingPartySection.Configuration.SecuritySettings.CreateSecuritySettings();
- this.WebRequestHandler = defaultUntrustedWebRequestHandler;
- }
-
- /// <summary>
- /// Gets the channel to use for sending/receiving messages.
- /// </summary>
- public Channel Channel { get; internal set; }
-
- /// <summary>
- /// Gets the security settings used by this Relying Party.
- /// </summary>
- public RelyingPartySecuritySettings SecuritySettings {
- get {
- return this.securitySettings;
- }
-
- internal set {
- if (value == null) {
- throw new ArgumentNullException("value");
- }
-
- this.securitySettings = value;
- }
- }
-
- /// <summary>
- /// Gets the association store.
- /// </summary>
- internal IAssociationStore<Uri> AssociationStore { get; private set; }
-
- /// <summary>
- /// Gets the web request handler to use for discovery and the part of
- /// authentication where direct messages are sent to an untrusted remote party.
- /// </summary>
- internal IDirectSslWebRequestHandler WebRequestHandler { get; private set; }
-
- /// <summary>
- /// Gets an association between this Relying Party and a given Provider.
- /// A new association is created if necessary and possible.
- /// </summary>
- /// <param name="provider">The provider to create an association with.</param>
- /// <returns>The association if one exists and/or could be created. Null otherwise.</returns>
- internal Association GetAssociation(ProviderEndpointDescription provider) {
- ErrorUtilities.VerifyArgumentNotNull(provider, "provider");
-
- var associateRequest = AssociateRequest.Create(this.SecuritySettings, provider);
- if (associateRequest == null) {
- return null;
- }
-
- var associateResponse = this.Channel.Request(associateRequest);
- var associateSuccessfulResponse = associateResponse as AssociateSuccessfulResponse;
- var associateUnsuccessfulResponse = associateResponse as AssociateUnsuccessfulResponse;
- if (associateSuccessfulResponse != null) {
- Association association = associateSuccessfulResponse.CreateAssociation(associateRequest);
- this.AssociationStore.StoreAssociation(provider.Endpoint, association);
- return association;
- } else if (associateUnsuccessfulResponse != null) {
- // TODO: code here
- throw new NotImplementedException();
- } else {
- throw new ProtocolException(MessagingStrings.UnexpectedMessageReceivedOfMany);
- }
- }
- }
-}
+//----------------------------------------------------------------------- +// <copyright file="OpenIdRelyingParty.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OpenId.RelyingParty { + using System; + using DotNetOpenAuth.Configuration; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.Messaging.Bindings; + using DotNetOpenAuth.OpenId.ChannelElements; + using DotNetOpenAuth.OpenId.Messages; + + /// <summary> + /// Provides the programmatic facilities to act as an OpenId consumer. + /// </summary> + public sealed class OpenIdRelyingParty { + /// <summary> + /// The untrusted web request handler we use (and share) by default across all RP instances. + /// </summary> + private static IDirectSslWebRequestHandler defaultUntrustedWebRequestHandler = new UntrustedWebRequestHandler(); + + /// <summary> + /// Backing field for the <see cref="SecuritySettings"/> property. + /// </summary> + private RelyingPartySecuritySettings securitySettings; + + /// <summary> + /// Initializes a new instance of the <see cref="OpenIdRelyingParty"/> class. + /// </summary> + /// <param name="associationStore">The association store. If null, the relying party will always operate in "dumb mode".</param> + /// <param name="nonceStore">The nonce store to use. If null, the relying party will always operate in "dumb mode".</param> + /// <param name="secretStore">The secret store to use. If null, the relying party will always operate in "dumb mode".</param> + public OpenIdRelyingParty(IAssociationStore<Uri> associationStore, INonceStore nonceStore, IPrivateSecretStore secretStore) { + // TODO: fix this so that a null association store is supported as 'dumb mode only'. + ErrorUtilities.VerifyArgumentNotNull(associationStore, "associationStore"); + ErrorUtilities.VerifyArgumentNotNull(nonceStore, "nonceStore"); + ErrorUtilities.VerifyArgumentNotNull(secretStore, "secretStore"); + ErrorUtilities.VerifyArgument((associationStore == null) == (nonceStore == null), OpenIdStrings.AssociationAndNonceStoresMustBeBothNullOrBothNonNull); + + this.Channel = new OpenIdChannel(associationStore, nonceStore, secretStore); + this.AssociationStore = associationStore; + this.SecuritySettings = RelyingPartySection.Configuration.SecuritySettings.CreateSecuritySettings(); + this.WebRequestHandler = defaultUntrustedWebRequestHandler; + } + + /// <summary> + /// Gets the channel to use for sending/receiving messages. + /// </summary> + public Channel Channel { get; internal set; } + + /// <summary> + /// Gets the security settings used by this Relying Party. + /// </summary> + public RelyingPartySecuritySettings SecuritySettings { + get { + return this.securitySettings; + } + + internal set { + if (value == null) { + throw new ArgumentNullException("value"); + } + + this.securitySettings = value; + } + } + + /// <summary> + /// Gets the association store. + /// </summary> + internal IAssociationStore<Uri> AssociationStore { get; private set; } + + /// <summary> + /// Gets the web request handler to use for discovery and the part of + /// authentication where direct messages are sent to an untrusted remote party. + /// </summary> + internal IDirectSslWebRequestHandler WebRequestHandler { get; private set; } + + /// <summary> + /// Gets an association between this Relying Party and a given Provider. + /// A new association is created if necessary and possible. + /// </summary> + /// <param name="provider">The provider to create an association with.</param> + /// <returns>The association if one exists and/or could be created. Null otherwise.</returns> + internal Association GetAssociation(ProviderEndpointDescription provider) { + ErrorUtilities.VerifyArgumentNotNull(provider, "provider"); + + var associateRequest = AssociateRequest.Create(this.SecuritySettings, provider); + if (associateRequest == null) { + return null; + } + + var associateResponse = this.Channel.Request(associateRequest); + var associateSuccessfulResponse = associateResponse as AssociateSuccessfulResponse; + var associateUnsuccessfulResponse = associateResponse as AssociateUnsuccessfulResponse; + if (associateSuccessfulResponse != null) { + Association association = associateSuccessfulResponse.CreateAssociation(associateRequest); + this.AssociationStore.StoreAssociation(provider.Endpoint, association); + return association; + } else if (associateUnsuccessfulResponse != null) { + // TODO: code here + throw new NotImplementedException(); + } else { + throw new ProtocolException(MessagingStrings.UnexpectedMessageReceivedOfMany); + } + } + } +} |