/// <summary> /// Simulates an extension request and response. /// </summary> /// <param name="protocol">The protocol to use in the roundtripping.</param> /// <param name="requests">The extensions to add to the request message.</param> /// <param name="responses">The extensions to add to the response message.</param> /// <remarks> /// This method relies on the extension objects' Equals methods to verify /// accurate transport. The Equals methods should be verified by separate tests. /// </remarks> internal static void Roundtrip( Protocol protocol, IEnumerable <IOpenIdMessageExtension> requests, IEnumerable <IOpenIdMessageExtension> responses) { var securitySettings = new ProviderSecuritySettings(); var cryptoKeyStore = new MemoryCryptoKeyStore(); var associationStore = new ProviderAssociationHandleEncoder(cryptoKeyStore); Association association = HmacShaAssociationProvider.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart, associationStore, securitySettings); var coordinator = new OpenIdCoordinator( rp => { RegisterExtension(rp.Channel, Mocks.MockOpenIdExtension.Factory); var requestBase = new CheckIdRequest(protocol.Version, OpenIdTestBase.OPUri, AuthenticationRequestMode.Immediate); OpenIdTestBase.StoreAssociation(rp, OpenIdTestBase.OPUri, 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.Respond(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); var key = cryptoKeyStore.GetCurrentKey(ProviderAssociationHandleEncoder.AssociationHandleEncodingSecretBucket, TimeSpan.FromSeconds(1)); op.CryptoKeyStore.StoreKey(ProviderAssociationHandleEncoder.AssociationHandleEncodingSecretBucket, key.Key, key.Value); 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.Respond(response); }); coordinator.Run(); }
public void ExtensionOnlyChannelLevel() { Protocol protocol = Protocol.V20; AuthenticationRequestMode mode = AuthenticationRequestMode.Setup; var coordinator = new OpenIdCoordinator( rp => { var request = new SignedResponseRequest(protocol.Version, OPUri, mode); rp.Channel.Respond(request); }, op => { var request = op.Channel.ReadFromRequest<SignedResponseRequest>(); Assert.IsNotInstanceOf<CheckIdRequest>(request); }); coordinator.Run(); }
public void BadRequestsGenerateValidErrorResponses() { var coordinator = new OpenIdCoordinator( rp => { var nonOpenIdMessage = new Mocks.TestDirectedMessage(); nonOpenIdMessage.Recipient = OPUri; nonOpenIdMessage.HttpMethods = HttpDeliveryMethods.PostRequest; MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired, nonOpenIdMessage); var response = rp.Channel.Request <DirectErrorResponse>(nonOpenIdMessage); Assert.IsNotNull(response.ErrorMessage); Assert.AreEqual(Protocol.Default.Version, response.Version); }, AutoProvider); coordinator.Run(); }
public void BadRequestsGenerateValidErrorResponses() { var coordinator = new OpenIdCoordinator( rp => { var nonOpenIdMessage = new Mocks.TestDirectedMessage(); nonOpenIdMessage.Recipient = OPUri; nonOpenIdMessage.HttpMethods = HttpDeliveryMethods.PostRequest; MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired, nonOpenIdMessage); var response = rp.Channel.Request<DirectErrorResponse>(nonOpenIdMessage); Assert.IsNotNull(response.ErrorMessage); Assert.AreEqual(Protocol.Default.Version, response.Version); }, AutoProvider); coordinator.Run(); }
public void UnsolicitedAssertion() { this.MockResponder.RegisterMockRPDiscovery(); OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { rp.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler; IAuthenticationResponse response = rp.GetResponse(); Assert.AreEqual(AuthenticationStatus.Authenticated, response.Status); }, op => { op.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler; Identifier id = GetMockIdentifier(ProtocolVersion.V20); op.SendUnsolicitedAssertion(OPUri, RPRealmUri, id, OPLocalIdentifiers[0]); AutoProvider(op); // handle check_auth }); coordinator.Run(); }
/// <summary> /// Simulates an extension request and response. /// </summary> /// <param name="protocol">The protocol to use in the roundtripping.</param> /// <param name="requests">The extensions to add to the request message.</param> /// <param name="responses">The extensions to add to the response message.</param> /// <remarks> /// This method relies on the extension objects' Equals methods to verify /// accurate transport. The Equals methods should be verified by separate tests. /// </remarks> internal static void Roundtrip( Protocol protocol, IEnumerable<IOpenIdMessageExtension> requests, IEnumerable<IOpenIdMessageExtension> responses) { var securitySettings = new ProviderSecuritySettings(); var cryptoKeyStore = new MemoryCryptoKeyStore(); var associationStore = new ProviderAssociationHandleEncoder(cryptoKeyStore); Association association = HmacShaAssociationProvider.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart, associationStore, securitySettings); var coordinator = new OpenIdCoordinator( rp => { RegisterExtension(rp.Channel, Mocks.MockOpenIdExtension.Factory); var requestBase = new CheckIdRequest(protocol.Version, OpenIdTestBase.OPUri, AuthenticationRequestMode.Immediate); OpenIdTestBase.StoreAssociation(rp, OpenIdTestBase.OPUri, 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.Respond(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); var key = cryptoKeyStore.GetCurrentKey(ProviderAssociationHandleEncoder.AssociationHandleEncodingSecretBucket, TimeSpan.FromSeconds(1)); op.CryptoKeyStore.StoreKey(ProviderAssociationHandleEncoder.AssociationHandleEncodingSecretBucket, key.Key, key.Value); 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.Respond(response); }); coordinator.Run(); }
public void AssociateDiffieHellmanOverHttps() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { // We have to formulate the associate request manually, // since the DNOI RP won't voluntarily use DH on HTTPS. AssociateDiffieHellmanRequest request = new AssociateDiffieHellmanRequest(protocol.Version, new Uri("https://Provider")); request.AssociationType = protocol.Args.SignatureAlgorithm.HMAC_SHA256; request.SessionType = protocol.Args.SessionType.DH_SHA256; request.InitializeRequest(); var response = rp.Channel.Request<AssociateSuccessfulResponse>(request); Assert.IsNotNull(response); Assert.AreEqual(request.AssociationType, response.AssociationType); Assert.AreEqual(request.SessionType, response.SessionType); }, AutoProvider); coordinator.Run(); }
public void GetRequest() { var httpInfo = new HttpRequestInfo("GET", new Uri("http://someUri")); Assert.IsNull(this.provider.GetRequest(httpInfo), "An irrelevant request should return null."); var providerDescription = new ProviderEndpointDescription(OPUri, Protocol.Default.Version); // Test some non-empty request scenario. OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { rp.Channel.Request(AssociateRequestRelyingParty.Create(rp.SecuritySettings, providerDescription)); }, op => { IRequest request = op.GetRequest(); Assert.IsInstanceOf <AutoResponsiveRequest>(request); op.Respond(request); }); coordinator.Run(); }
public void AssertionWithEndpointFilter() { var coordinator = new OpenIdCoordinator( rp => { // register with RP so that id discovery passes rp.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler; // Rig it to always deny the incoming OP rp.EndpointFilter = op => false; // Receive the unsolicited assertion var response = rp.GetResponse(); Assert.AreEqual(AuthenticationStatus.Failed, response.Status); }, op => { Identifier id = GetMockIdentifier(ProtocolVersion.V20); op.SendUnsolicitedAssertion(OPUri, GetMockRealm(false), id, id); AutoProvider(op); }); coordinator.Run(); }
public void ExtensionOnlyFacadeLevel() { Protocol protocol = Protocol.V20; var coordinator = new OpenIdCoordinator( rp => { var request = rp.CreateRequest(GetMockIdentifier(protocol.ProtocolVersion), RPRealmUri, RPUri); request.IsExtensionOnly = true; rp.Channel.Respond(request.RedirectingResponse.OriginalMessage); IAuthenticationResponse response = rp.GetResponse(); Assert.AreEqual(AuthenticationStatus.ExtensionsOnly, response.Status); }, op => { var assocRequest = op.GetRequest(); op.Respond(assocRequest); var request = (IAnonymousRequest)op.GetRequest(); request.IsApproved = true; Assert.IsNotInstanceOf<CheckIdRequest>(request); op.Respond(request); }); coordinator.Run(); }
public void CreateRequestMessage() { OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { Identifier id = this.GetMockIdentifier(ProtocolVersion.V20); IAuthenticationRequest authRequest = rp.CreateRequest(id, this.realm, this.returnTo); // Add some callback arguments authRequest.AddCallbackArguments("a", "b"); authRequest.AddCallbackArguments(new Dictionary <string, string> { { "c", "d" }, { "e", "f" } }); // Assembly an extension request. ClaimsRequest sregRequest = new ClaimsRequest(); sregRequest.Nickname = DemandLevel.Request; authRequest.AddExtension(sregRequest); // Construct the actual authentication request message. var authRequestAccessor = AuthenticationRequest_Accessor.AttachShadow(authRequest); var req = authRequestAccessor.CreateRequestMessage(); Assert.IsNotNull(req); // Verify that callback arguments were included. NameValueCollection callbackArguments = HttpUtility.ParseQueryString(req.ReturnTo.Query); Assert.AreEqual("b", callbackArguments["a"]); Assert.AreEqual("d", callbackArguments["c"]); Assert.AreEqual("f", callbackArguments["e"]); // Verify that extensions were included. Assert.AreEqual(1, req.Extensions.Count); Assert.IsTrue(req.Extensions.Contains(sregRequest)); }, AutoProvider); coordinator.Run(); }
public void ExtensionsAreIdentifiedAsSignedOrUnsigned() { Protocol protocol = Protocol.Default; OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { RegisterMockExtension(rp.Channel); var response = rp.Channel.ReadFromRequest <IndirectSignedResponse>(); Assert.AreEqual(1, response.SignedExtensions.Count(), "Signed extension should have been received."); Assert.AreEqual(0, response.UnsignedExtensions.Count(), "No unsigned extension should be present."); response = rp.Channel.ReadFromRequest <IndirectSignedResponse>(); Assert.AreEqual(0, response.SignedExtensions.Count(), "No signed extension should have been received."); Assert.AreEqual(1, response.UnsignedExtensions.Count(), "Unsigned extension should have been received."); }, op => { RegisterMockExtension(op.Channel); op.Channel.Respond(CreateResponseWithExtensions(protocol)); op.Respond(op.GetRequest()); // check_auth op.SecuritySettings.SignOutgoingExtensions = false; op.Channel.Respond(CreateResponseWithExtensions(protocol)); op.Respond(op.GetRequest()); // check_auth }); coordinator.Run(); }
public void AssociateRenegotiateBitLength() { Protocol protocol = Protocol.V20; // The strategy is to make a simple request of the RP to establish an association, // and to more carefully observe the Provider-side of things to make sure that both // the OP and RP are behaving as expected. OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { var opDescription = new ProviderEndpointDescription(OPUri, protocol.Version); Association association = rp.AssociationManager.GetOrCreateAssociation(opDescription); Assert.IsNotNull(association, "Association failed to be created."); Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, association.GetAssociationType(protocol)); }, op => { op.SecuritySettings.MaximumHashBitLength = 160; // Force OP to reject HMAC-SHA256 // Receive initial request for an HMAC-SHA256 association. AutoResponsiveRequest req = (AutoResponsiveRequest)op.GetRequest(); AssociateRequest associateRequest = (AssociateRequest)req.RequestMessage; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA256, associateRequest.AssociationType); // Ensure that the response is a suggestion that the RP try again with HMAC-SHA1 AssociateUnsuccessfulResponse renegotiateResponse = (AssociateUnsuccessfulResponse)req.ResponseMessageTestHook; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, renegotiateResponse.AssociationType); op.Respond(req); // Receive second attempt request for an HMAC-SHA1 association. req = (AutoResponsiveRequest)op.GetRequest(); associateRequest = (AssociateRequest)req.RequestMessage; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, associateRequest.AssociationType); // Ensure that the response is a success response. AssociateSuccessfulResponse successResponse = (AssociateSuccessfulResponse)req.ResponseMessageTestHook; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, successResponse.AssociationType); op.Respond(req); }); coordinator.Run(); }
/// <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(Protocol.Lookup(opDescription.Version).ProtocolVersion); bool expectSuccess = expectedAssociationType != null; bool expectDiffieHellman = !opDescription.Uri.IsTransportSecure(); Association rpAssociation = null, opAssociation; AssociateSuccessfulResponse associateSuccessfulResponse = null; AssociateUnsuccessfulResponse associateUnsuccessfulResponse = null; OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { rp.SecuritySettings = this.RelyingPartySecuritySettings; rpAssociation = rp.AssociationManager.GetOrCreateAssociation(opDescription); }, op => { op.SecuritySettings = this.ProviderSecuritySettings; IRequest req = op.GetRequest(); Assert.IsNotNull(req, "Expected incoming request but did not receive it."); Assert.IsTrue(req.IsResponseReady); op.Respond(req); }); coordinator.IncomingMessageFilter = message => { Assert.AreSame(opDescription.Version, message.Version, "The message was recognized as version {0} but was expected to be {1}.", message.Version, Protocol.Lookup(opDescription.Version).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.AreEqual(opDescription.Version, message.Version, "The message was for version {0} but was expected to be for {1}.", message.Version, opDescription.Version); }; coordinator.Run(); if (expectSuccess) { Assert.IsNotNull(rpAssociation); Association actual = coordinator.RelyingParty.AssociationManager.AssociationStoreTestHook.GetAssociation(opDescription.Uri, rpAssociation.Handle); Assert.AreEqual(rpAssociation, actual); opAssociation = coordinator.Provider.AssociationStore.Deserialize(new TestSignedDirectedMessage(), false, rpAssociation.Handle); Assert.IsNotNull(opAssociation, "The Provider could not decode the association handle."); 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.IsInstanceOf<AssociateDiffieHellmanResponse>(associateSuccessfulResponse); var diffieHellmanResponse = (AssociateDiffieHellmanResponse)associateSuccessfulResponse; Assert.IsFalse(MessagingUtilities.AreEquivalent(diffieHellmanResponse.EncodedMacKey, rpAssociation.SecretKey), "Key should have been encrypted."); } else { Assert.IsInstanceOf<AssociateUnencryptedResponse>(associateSuccessfulResponse); var unencryptedResponse = (AssociateUnencryptedResponse)associateSuccessfulResponse; } } else { Assert.IsNull(coordinator.RelyingParty.AssociationManager.AssociationStoreTestHook.GetAssociation(opDescription.Uri, new RelyingPartySecuritySettings())); } }
public void AssociateRenegotiateLimitedByRPSecuritySettings() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { rp.SecuritySettings.MinimumHashBitLength = 256; var association = rp.AssociationManager.GetOrCreateAssociation(new ProviderEndpointDescription(OPUri, protocol.Version)); Assert.IsNull(association, "No association should have been created when RP and OP could not agree on association strength."); }, op => { op.SecuritySettings.MaximumHashBitLength = 160; AutoProvider(op); }); coordinator.Run(); }
public void RPOnlyRenegotiatesOnce() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { var association = rp.AssociationManager.GetOrCreateAssociation(new ProviderEndpointDescription(OPUri, protocol.Version)); Assert.IsNull(association, "The RP should quietly give up when the OP misbehaves."); }, op => { // Receive initial request. var request = op.Channel.ReadFromRequest<AssociateRequest>(); // Send a renegotiate response AssociateUnsuccessfulResponse renegotiateResponse = new AssociateUnsuccessfulResponse(request.Version, request); renegotiateResponse.AssociationType = protocol.Args.SignatureAlgorithm.HMAC_SHA1; renegotiateResponse.SessionType = protocol.Args.SessionType.DH_SHA1; op.Channel.Respond(renegotiateResponse); // Receive second-try request = op.Channel.ReadFromRequest<AssociateRequest>(); // Send ANOTHER renegotiate response, at which point the DNOI RP should give up. renegotiateResponse = new AssociateUnsuccessfulResponse(request.Version, request); renegotiateResponse.AssociationType = protocol.Args.SignatureAlgorithm.HMAC_SHA256; renegotiateResponse.SessionType = protocol.Args.SessionType.DH_SHA256; op.Channel.Respond(renegotiateResponse); }); coordinator.Run(); }
public void RPRejectsMismatchingAssociationAndSessionBitLengths() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { var association = rp.AssociationManager.GetOrCreateAssociation(new ProviderEndpointDescription(OPUri, protocol.Version)); Assert.IsNull(association, "The RP should quietly give up when the OP misbehaves."); }, op => { // Receive initial request. var request = op.Channel.ReadFromRequest<AssociateRequest>(); // Send a mismatched response AssociateUnsuccessfulResponse renegotiateResponse = new AssociateUnsuccessfulResponse(request.Version, request); renegotiateResponse.AssociationType = protocol.Args.SignatureAlgorithm.HMAC_SHA1; renegotiateResponse.SessionType = protocol.Args.SessionType.DH_SHA256; op.Channel.Respond(renegotiateResponse); }); coordinator.Run(); }
public void RPRejectsUnrecognizedAssociationType() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { var association = rp.AssociationManager.GetOrCreateAssociation(new ProviderEndpointDescription(OPUri, protocol.Version)); Assert.IsNull(association, "The RP should quietly give up when the OP misbehaves."); }, op => { // Receive initial request. var request = op.Channel.ReadFromRequest<AssociateRequest>(); // Send a response that suggests a foreign association type. AssociateUnsuccessfulResponse renegotiateResponse = new AssociateUnsuccessfulResponse(request.Version, request); renegotiateResponse.AssociationType = "HMAC-UNKNOWN"; renegotiateResponse.SessionType = "DH-UNKNOWN"; op.Channel.Respond(renegotiateResponse); }); coordinator.Run(); }
public void OPRejectsHttpNoEncryptionAssociateRequests() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { // We have to formulate the associate request manually, // since the DNOI RP won't voluntarily suggest no encryption at all. var request = new AssociateUnencryptedRequestNoSslCheck(protocol.Version, OPUri); request.AssociationType = protocol.Args.SignatureAlgorithm.HMAC_SHA256; request.SessionType = protocol.Args.SessionType.NoEncryption; var response = rp.Channel.Request<DirectErrorResponse>(request); Assert.IsNotNull(response); }, AutoProvider); coordinator.Run(); }
public void CreateRequestMessage() { OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { Identifier id = this.GetMockIdentifier(ProtocolVersion.V20); IAuthenticationRequest authRequest = rp.CreateRequest(id, this.realm, this.returnTo); // Add some callback arguments authRequest.AddCallbackArguments("a", "b"); authRequest.AddCallbackArguments(new Dictionary<string, string> { { "c", "d" }, { "e", "f" } }); // Assembly an extension request. ClaimsRequest sregRequest = new ClaimsRequest(); sregRequest.Nickname = DemandLevel.Request; authRequest.AddExtension(sregRequest); // Construct the actual authentication request message. var authRequestAccessor = AuthenticationRequest_Accessor.AttachShadow(authRequest); var req = authRequestAccessor.CreateRequestMessage(); Assert.IsNotNull(req); // Verify that callback arguments were included. NameValueCollection callbackArguments = HttpUtility.ParseQueryString(req.ReturnTo.Query); Assert.AreEqual("b", callbackArguments["a"]); Assert.AreEqual("d", callbackArguments["c"]); Assert.AreEqual("f", callbackArguments["e"]); // Verify that extensions were included. Assert.AreEqual(1, req.Extensions.Count); Assert.IsTrue(req.Extensions.Contains(sregRequest)); }, AutoProvider); coordinator.Run(); }
public void ExtensionsAreIdentifiedAsSignedOrUnsigned() { Protocol protocol = Protocol.Default; OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { RegisterMockExtension(rp.Channel); var response = rp.Channel.ReadFromRequest<IndirectSignedResponse>(); Assert.AreEqual(1, response.SignedExtensions.Count(), "Signed extension should have been received."); Assert.AreEqual(0, response.UnsignedExtensions.Count(), "No unsigned extension should be present."); response = rp.Channel.ReadFromRequest<IndirectSignedResponse>(); Assert.AreEqual(0, response.SignedExtensions.Count(), "No signed extension should have been received."); Assert.AreEqual(1, response.UnsignedExtensions.Count(), "Unsigned extension should have been received."); }, op => { RegisterMockExtension(op.Channel); op.Channel.Send(CreateResponseWithExtensions(protocol)); op.SendResponse(op.GetRequest()); // check_auth op.SecuritySettings.SignOutgoingExtensions = false; op.Channel.Send(CreateResponseWithExtensions(protocol)); op.SendResponse(op.GetRequest()); // check_auth }); coordinator.Run(); }
public void GetRequest() { HttpRequestInfo httpInfo = new HttpRequestInfo(); httpInfo.UrlBeforeRewriting = new Uri("http://someUri"); Assert.IsNull(this.provider.GetRequest(httpInfo), "An irrelevant request should return null."); var providerDescription = new ProviderEndpointDescription(OpenIdTestBase.OPUri, Protocol.Default.Version); // Test some non-empty request scenario. OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { rp.Channel.Request(AssociateRequestRelyingParty.Create(rp.SecuritySettings, providerDescription)); }, op => { IRequest request = op.GetRequest(); Assert.IsInstanceOf<AutoResponsiveRequest>(request); op.Respond(request); }); coordinator.Run(); }
private void ParameterizedAuthenticationTest(Protocol protocol, bool statelessRP, bool sharedAssociation, bool positive, bool immediate, bool tamper) { Contract.Requires<ArgumentException>(!statelessRP || !sharedAssociation, "The RP cannot be stateless while sharing an association with the OP."); Contract.Requires<ArgumentException>(positive || !tamper, "Cannot tamper with a negative response."); var securitySettings = new ProviderSecuritySettings(); var cryptoKeyStore = new MemoryCryptoKeyStore(); var associationStore = new ProviderAssociationHandleEncoder(cryptoKeyStore); Association association = sharedAssociation ? HmacShaAssociation.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart, associationStore, securitySettings) : null; var coordinator = new OpenIdCoordinator( rp => { var request = new CheckIdRequest(protocol.Version, OPUri, immediate ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup); if (association != null) { StoreAssociation(rp, OPUri, association); request.AssociationHandle = association.Handle; } request.ClaimedIdentifier = "http://claimedid"; request.LocalIdentifier = "http://localid"; request.ReturnTo = RPUri; request.Realm = RPUri; rp.Channel.Respond(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. try { CoordinatingChannel channel = (CoordinatingChannel)rp.Channel; channel.Replay(response); Assert.Fail("Expected ProtocolException was not thrown."); } catch (ProtocolException ex) { Assert.IsTrue(ex is ReplayedMessageException || ex is InvalidSignatureException, "A {0} exception was thrown instead of the expected {1} or {2}.", ex.GetType(), typeof(ReplayedMessageException).Name, typeof(InvalidSignatureException).Name); } } } else { var response = rp.Channel.ReadFromRequest<NegativeAssertionResponse>(); Assert.IsNotNull(response); if (immediate) { // Only 1.1 was required to include user_setup_url if (protocol.Version.Major < 2) { Assert.IsNotNull(response.UserSetupUrl); } } else { Assert.IsNull(response.UserSetupUrl); } } }, op => { if (association != null) { var key = cryptoKeyStore.GetCurrentKey(ProviderAssociationHandleEncoder.AssociationHandleEncodingSecretBucket, TimeSpan.FromSeconds(1)); op.CryptoKeyStore.StoreKey(ProviderAssociationHandleEncoder.AssociationHandleEncodingSecretBucket, key.Key, key.Value); } var request = op.Channel.ReadFromRequest<CheckIdRequest>(); Assert.IsNotNull(request); IProtocolMessage response; if (positive) { response = new PositiveAssertionResponse(request); } else { response = new NegativeAssertionResponse(request, op.Channel); } op.Channel.Respond(response); if (positive && (statelessRP || !sharedAssociation)) { var checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>(); var checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest); checkauthResponse.IsValid = checkauthRequest.IsValid; op.Channel.Respond(checkauthResponse); if (!tamper) { // Respond to the replay attack. checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>(); checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest); checkauthResponse.IsValid = checkauthRequest.IsValid; op.Channel.Respond(checkauthResponse); } } }); if (tamper) { coordinator.IncomingMessageFilter = message => { var assertion = message as PositiveAssertionResponse; if (assertion != null) { // Alter the Local Identifier between the Provider and the Relying Party. // If the signature binding element does its job, this should cause the RP // to throw. assertion.LocalIdentifier = "http://victim"; } }; } if (statelessRP) { coordinator.RelyingParty = new OpenIdRelyingParty(null); } coordinator.Run(); }