/// <summary>
        /// Gets an association between this Relying Party and a given Provider
        /// if it already exists in the association store.
        /// </summary>
        /// <param name="provider">The provider to create an association with.</param>
        /// <returns>The association if one exists and has useful life remaining.  Otherwise <c>null</c>.</returns>
        internal Association GetExistingAssociation(ProviderEndpointDescription provider)
        {
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");

            // If the RP has no application store for associations, there's no point in creating one.
            if (this.associationStore == null)
            {
                return(null);
            }

            Association association = this.associationStore.GetAssociation(provider.Endpoint, this.SecuritySettings);

            // If the returned association does not fulfill security requirements, ignore it.
            if (association != null && !this.SecuritySettings.IsAssociationInPermittedRange(association))
            {
                association = null;
            }

            if (association != null && !association.HasUsefulLifeRemaining)
            {
                association = null;
            }

            return(association);
        }
Example #2
0
        private AuthenticationRequest CreateAuthenticationRequest(Identifier claimedIdentifier, Identifier providerLocalIdentifier)
        {
            ProviderEndpointDescription providerEndpoint = new ProviderEndpointDescription(OPUri, this.protocol.Version);
            IdentifierDiscoveryResult   endpoint         = IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimedIdentifier, providerLocalIdentifier, providerEndpoint, 10, 5);
            OpenIdRelyingParty          rp = this.CreateRelyingParty();

            return(AuthenticationRequest.CreateForTest(endpoint, this.realm, this.returnTo, rp));
        }
Example #3
0
 /// <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);
     }
 }
Example #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ServiceEndpoint"/> class.
 /// </summary>
 /// <param name="providerEndpoint">The provider endpoint.</param>
 /// <param name="claimedIdentifier">The Claimed Identifier.</param>
 /// <param name="userSuppliedIdentifier">The User-supplied Identifier.</param>
 /// <param name="providerLocalIdentifier">The Provider Local Identifier.</param>
 /// <param name="servicePriority">The service priority.</param>
 /// <param name="uriPriority">The URI priority.</param>
 private ServiceEndpoint(ProviderEndpointDescription providerEndpoint, Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, int?servicePriority, int?uriPriority)
 {
     ErrorUtilities.VerifyArgumentNotNull(claimedIdentifier, "claimedIdentifier");
     ErrorUtilities.VerifyArgumentNotNull(providerEndpoint, "providerEndpoint");
     this.ProviderDescription     = providerEndpoint;
     this.ClaimedIdentifier       = claimedIdentifier;
     this.UserSuppliedIdentifier  = userSuppliedIdentifier;
     this.ProviderLocalIdentifier = providerLocalIdentifier ?? claimedIdentifier;
     this.servicePriority         = servicePriority;
     this.uriPriority             = uriPriority;
 }
Example #5
0
        protected Identifier GetMockDualIdentifier()
        {
            Protocol protocol    = Protocol.Default;
            var      opDesc      = new ProviderEndpointDescription(OPUri, protocol.Version);
            var      dualResults = new IdentifierDiscoveryResult[] {
                IdentifierDiscoveryResult.CreateForClaimedIdentifier(VanityUri.AbsoluteUri, OPLocalIdentifiers[0], opDesc, 10, 10),
                IdentifierDiscoveryResult.CreateForProviderIdentifier(protocol.ClaimedIdentifierForOPIdentifier, opDesc, 20, 20),
            };

            this.RegisterMockXrdsResponse(VanityUri, dualResults);
            return(VanityUri);
        }
Example #6
0
        public async Task 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.
            int providerAttemptCount = 0;

            HandleProvider(
                async(op, request) => {
                op.SecuritySettings.MaximumHashBitLength = 160;                         // Force OP to reject HMAC-SHA256

                switch (++providerAttemptCount)
                {
                case 1:
                    // Receive initial request for an HMAC-SHA256 association.
                    var req = (AutoResponsiveRequest)await op.GetRequestAsync(request);
                    var associateRequest = (AssociateRequest)req.RequestMessage;
                    Assert.That(associateRequest, Is.Not.Null);
                    Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA256, associateRequest.AssociationType);

                    // Ensure that the response is a suggestion that the RP try again with HMAC-SHA1
                    var renegotiateResponse =
                        (AssociateUnsuccessfulResponse)await req.GetResponseMessageAsyncTestHook(CancellationToken.None);
                    Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, renegotiateResponse.AssociationType);
                    return(await op.PrepareResponseAsync(req));

                case 2:
                    // Receive second attempt request for an HMAC-SHA1 association.
                    req = (AutoResponsiveRequest)await op.GetRequestAsync(request);
                    associateRequest = (AssociateRequest)req.RequestMessage;
                    Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, associateRequest.AssociationType);

                    // Ensure that the response is a success response.
                    var successResponse =
                        (AssociateSuccessfulResponse)await req.GetResponseMessageAsyncTestHook(CancellationToken.None);
                    Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, successResponse.AssociationType);
                    return(await op.PrepareResponseAsync(req));

                default:
                    throw Assumes.NotReachable();
                }
            });
            var         rp            = this.CreateRelyingParty();
            var         opDescription = new ProviderEndpointDescription(OPUri, protocol.Version);
            Association association   = await rp.AssociationManager.GetOrCreateAssociationAsync(opDescription, CancellationToken.None);

            Assert.IsNotNull(association, "Association failed to be created.");
            Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, association.GetAssociationType(protocol));
        }
Example #7
0
        public void AssociateRequestDeterminedBySecuritySettings()
        {
            Protocol         protocol         = Protocol.V20;
            SecuritySettings securitySettings = new RelyingPartySecuritySettings();

            securitySettings.MinimumHashBitLength = 160;
            securitySettings.MaximumHashBitLength = 160;
            ProviderEndpointDescription provider = new ProviderEndpointDescription(OPUri, protocol.Version);

            Assert.AreEqual(AssociateRequestRelyingParty.Create(securitySettings, provider).AssociationType, protocol.Args.SignatureAlgorithm.HMAC_SHA1);

            securitySettings.MinimumHashBitLength = 384;
            securitySettings.MaximumHashBitLength = 384;
            Assert.AreEqual(AssociateRequestRelyingParty.Create(securitySettings, provider).AssociationType, protocol.Args.SignatureAlgorithm.HMAC_SHA384);
        }
Example #8
0
        internal static IdentifierDiscoveryResult GetServiceEndpoint(int user, ProtocolVersion providerVersion, int servicePriority, bool useSsl, bool delegating)
        {
            var providerEndpoint = new ProviderEndpointDescription(
                useSsl ? OpenIdTestBase.OPUriSsl : OpenIdTestBase.OPUri,
                new string[] { Protocol.Lookup(providerVersion).ClaimedIdentifierServiceTypeURI });
            var local_id   = useSsl ? OPLocalIdentifiersSsl[user] : OPLocalIdentifiers[user];
            var claimed_id = delegating ? (useSsl ? VanityUriSsl : VanityUri) : local_id;

            return(IdentifierDiscoveryResult.CreateForClaimedIdentifier(
                       claimed_id,
                       claimed_id,
                       local_id,
                       providerEndpoint,
                       servicePriority,
                       10));
        }
        /// <summary>
        /// Creates a new association with a given Provider.
        /// </summary>
        /// <param name="provider">The provider to create an association with.</param>
        /// <returns>
        /// The newly created association, or null if no association can be created with
        /// the given Provider given the current security settings.
        /// </returns>
        /// <remarks>
        /// A new association is created and returned even if one already exists in the
        /// association store.
        /// Any new association is automatically added to the <see cref="associationStore"/>.
        /// </remarks>
        private Association CreateNewAssociation(ProviderEndpointDescription provider)
        {
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");

            // If there is no association store, there is no point in creating an association.
            if (this.associationStore == null)
            {
                return(null);
            }

            var associateRequest = AssociateRequest.Create(this.securitySettings, provider);

            const int RenegotiateRetries = 1;

            return(this.CreateNewAssociation(provider, associateRequest, RenegotiateRetries));
        }
        public async Task GetRequest()
        {
            var httpInfo = new HttpRequestMessage(HttpMethod.Get, "http://someUri");

            Assert.IsNull(await this.provider.GetRequestAsync(httpInfo), "An irrelevant request should return null.");
            var providerDescription = new ProviderEndpointDescription(OPUri, Protocol.Default.Version);

            // Test some non-empty request scenario.
            HandleProvider(
                async(op, req) => {
                IRequest request = await op.GetRequestAsync(req);
                Assert.IsInstanceOf <AutoResponsiveRequest>(request);
                return(await op.PrepareResponseAsync(request));
            });
            var rp = this.CreateRelyingParty();
            await rp.Channel.RequestAsync(AssociateRequestRelyingParty.Create(rp.SecuritySettings, providerDescription), CancellationToken.None);
        }
Example #11
0
        public void ProblematicClaimedId()
        {
            var           providerEndpoint = new ProviderEndpointDescription(OpenIdTestBase.OPUri, Protocol.Default.Version);
            string        claimed_id       = BaseMockUri + "a./b.";
            var           se          = IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimed_id, claimed_id, providerEndpoint, null, null);
            UriIdentifier identityUri = (UriIdentifier)se.ClaimedIdentifier;
            var           mockId      = new MockIdentifier(identityUri, this.MockResponder, new IdentifierDiscoveryResult[] { se });

            var positiveAssertion = this.GetPositiveAssertion();

            positiveAssertion.ClaimedIdentifier = mockId;
            positiveAssertion.LocalIdentifier   = mockId;
            var rp           = CreateRelyingParty();
            var authResponse = new PositiveAuthenticationResponse(positiveAssertion, rp);

            Assert.AreEqual(AuthenticationStatus.Authenticated, authResponse.Status);
            Assert.AreEqual(claimed_id, authResponse.ClaimedIdentifier.ToString());
        }
        public async Task ProblematicClaimedId()
        {
            var    providerEndpoint = new ProviderEndpointDescription(OpenIdTestBase.OPUri, Protocol.Default.Version);
            string claimed_id       = BaseMockUri + "a./b.";
            var    se          = IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimed_id, claimed_id, providerEndpoint, null, null);
            var    identityUri = (UriIdentifier)se.ClaimedIdentifier;

            this.RegisterMockXrdsResponse(se);

            var rp = this.CreateRelyingParty();
            var positiveAssertion = this.GetPositiveAssertion();

            positiveAssertion.ClaimedIdentifier = claimed_id;
            positiveAssertion.LocalIdentifier   = claimed_id;
            var authResponse = await PositiveAuthenticationResponse.CreateAsync(positiveAssertion, rp, CancellationToken.None);

            Assert.AreEqual(AuthenticationStatus.Authenticated, authResponse.Status);
            Assert.AreEqual(claimed_id, authResponse.ClaimedIdentifier.ToString());
        }
Example #13
0
        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();
                AutoResponsiveRequest_Accessor reqAccessor = AutoResponsiveRequest_Accessor.AttachShadow(req);
                AssociateRequest associateRequest          = (AssociateRequest)reqAccessor.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)reqAccessor.ResponseMessage;
                Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, renegotiateResponse.AssociationType);
                op.SendResponse(req);

                // Receive second attempt request for an HMAC-SHA1 association.
                req              = (AutoResponsiveRequest)op.GetRequest();
                reqAccessor      = AutoResponsiveRequest_Accessor.AttachShadow(req);
                associateRequest = (AssociateRequest)reqAccessor.RequestMessage;
                Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, associateRequest.AssociationType);

                // Ensure that the response is a success response.
                AssociateSuccessfulResponse successResponse = (AssociateSuccessfulResponse)reqAccessor.ResponseMessage;
                Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, successResponse.AssociationType);
                op.SendResponse(req);
            });

            coordinator.Run();
        }
Example #14
0
        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();
        }
Example #15
0
        /// <summary>
        /// Gets an association between this Relying Party and a given Provider
        /// if it already exists in the association store.
        /// </summary>
        /// <param name="provider">The provider to create an association with.</param>
        /// <returns>The association if one exists and has useful life remaining.  Otherwise <c>null</c>.</returns>
        internal Association GetExistingAssociation(ProviderEndpointDescription provider)
        {
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");

            // If the RP has no application store for associations, there's no point in creating one.
            if (this.associationStore == null) {
                return null;
            }

            Association association = this.associationStore.GetAssociation(provider.Endpoint, this.SecuritySettings);

            // If the returned association does not fulfill security requirements, ignore it.
            if (association != null && !this.SecuritySettings.IsAssociationInPermittedRange(association)) {
                association = null;
            }

            if (association != null && !association.HasUsefulLifeRemaining) {
                association = null;
            }

            return association;
        }
Example #16
0
        /// <summary>
        /// Creates an association request message that is appropriate for a given Provider.
        /// </summary>
        /// <param name="securityRequirements">The set of requirements the selected association type must comply to.</param>
        /// <param name="provider">The provider to create an association with.</param>
        /// <returns>
        /// The message to send to the Provider to request an association.
        /// Null if no association could be created that meet the security requirements
        /// and the provider OpenID version.
        /// </returns>
        internal static AssociateRequest Create(SecuritySettings securityRequirements, ProviderEndpointDescription provider)
        {
            ErrorUtilities.VerifyArgumentNotNull(securityRequirements, "securityRequirements");
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");

            // Apply our knowledge of the endpoint's transport, OpenID version, and
            // security requirements to decide the best association.
            bool unencryptedAllowed = provider.Endpoint.IsTransportSecure();
            bool useDiffieHellman = !unencryptedAllowed;
            string associationType, sessionType;
            if (!HmacShaAssociation.TryFindBestAssociation(Protocol.Lookup(provider.ProtocolVersion), true, securityRequirements, useDiffieHellman, out associationType, out sessionType)) {
                // There are no associations that meet all requirements.
                Logger.OpenId.Warn("Security requirements and protocol combination knock out all possible association types.  Dumb mode forced.");
                return null;
            }

            return Create(securityRequirements, provider, associationType, sessionType);
        }
Example #17
0
        /// <summary>
        /// Creates an association request message that is appropriate for a given Provider.
        /// </summary>
        /// <param name="securityRequirements">The set of requirements the selected association type must comply to.</param>
        /// <param name="provider">The provider to create an association with.</param>
        /// <param name="associationType">Type of the association.</param>
        /// <param name="sessionType">Type of the session.</param>
        /// <returns>
        /// The message to send to the Provider to request an association.
        /// Null if no association could be created that meet the security requirements
        /// and the provider OpenID version.
        /// </returns>
        internal static AssociateRequest Create(SecuritySettings securityRequirements, ProviderEndpointDescription provider, string associationType, string sessionType)
        {
            ErrorUtilities.VerifyArgumentNotNull(securityRequirements, "securityRequirements");
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");
            ErrorUtilities.VerifyNonZeroLength(associationType, "associationType");
            ErrorUtilities.VerifyArgumentNotNull(sessionType, "sessionType");

            bool unencryptedAllowed = provider.Endpoint.IsTransportSecure();
            if (unencryptedAllowed) {
                var associateRequest = new AssociateUnencryptedRequest(provider.ProtocolVersion, provider.Endpoint);
                associateRequest.AssociationType = associationType;
                return associateRequest;
            } else {
                var associateRequest = new AssociateDiffieHellmanRequest(provider.ProtocolVersion, provider.Endpoint);
                associateRequest.AssociationType = associationType;
                associateRequest.SessionType = sessionType;
                associateRequest.InitializeRequest();
                return associateRequest;
            }
        }
Example #18
0
        /// <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()));
            }
        }
Example #19
0
        /// <summary>
        /// Creates a new association with a given Provider.
        /// </summary>
        /// <param name="provider">The provider to create an association with.</param>
        /// <param name="associateRequest">The associate request.  May be <c>null</c>, which will always result in a <c>null</c> return value..</param>
        /// <param name="retriesRemaining">The number of times to try the associate request again if the Provider suggests it.</param>
        /// <returns>
        /// The newly created association, or null if no association can be created with
        /// the given Provider given the current security settings.
        /// </returns>
        private Association CreateNewAssociation(ProviderEndpointDescription provider, AssociateRequest associateRequest, int retriesRemaining)
        {
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");

            if (associateRequest == null || retriesRemaining < 0) {
                // this can happen if security requirements and protocol conflict
                // to where there are no association types to choose from.
                return null;
            }

            try {
                var associateResponse = this.channel.Request(associateRequest);
                var associateSuccessfulResponse = associateResponse as AssociateSuccessfulResponse;
                var associateUnsuccessfulResponse = associateResponse as AssociateUnsuccessfulResponse;
                if (associateSuccessfulResponse != null) {
                    Association association = associateSuccessfulResponse.CreateAssociation(associateRequest, null);
                    this.associationStore.StoreAssociation(provider.Endpoint, association);
                    return association;
                } else if (associateUnsuccessfulResponse != null) {
                    if (string.IsNullOrEmpty(associateUnsuccessfulResponse.AssociationType)) {
                        Logger.OpenId.Debug("Provider rejected an association request and gave no suggestion as to an alternative association type.  Giving up.");
                        return null;
                    }

                    if (!this.securitySettings.IsAssociationInPermittedRange(Protocol.Lookup(provider.ProtocolVersion), associateUnsuccessfulResponse.AssociationType)) {
                        Logger.OpenId.DebugFormat("Provider rejected an association request and suggested '{0}' as an association to try, which this Relying Party does not support.  Giving up.", associateUnsuccessfulResponse.AssociationType);
                        return null;
                    }

                    if (retriesRemaining <= 0) {
                        Logger.OpenId.Debug("Unable to agree on an association type with the Provider in the allowed number of retries.  Giving up.");
                        return null;
                    }

                    // Make sure the Provider isn't suggesting an incompatible pair of association/session types.
                    Protocol protocol = Protocol.Lookup(provider.ProtocolVersion);
                    ErrorUtilities.VerifyProtocol(
                        HmacShaAssociation.IsDHSessionCompatible(protocol, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType),
                        OpenIdStrings.IncompatibleAssociationAndSessionTypes,
                        associateUnsuccessfulResponse.AssociationType,
                        associateUnsuccessfulResponse.SessionType);

                    associateRequest = AssociateRequest.Create(this.securitySettings, provider, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType);
                    return this.CreateNewAssociation(provider, associateRequest, retriesRemaining - 1);
                } else {
                    throw new ProtocolException(MessagingStrings.UnexpectedMessageReceivedOfMany);
                }
            } catch (ProtocolException ex) {
                // If the association failed because the remote server can't handle Expect: 100 Continue headers,
                // then our web request handler should have already accomodated for future calls.  Go ahead and
                // immediately make one of those future calls now to try to get the association to succeed.
                if (StandardWebRequestHandler.IsExceptionFrom417ExpectationFailed(ex)) {
                    return this.CreateNewAssociation(provider, associateRequest, retriesRemaining - 1);
                }

                // Since having associations with OPs is not totally critical, we'll log and eat
                // the exception so that auth may continue in dumb mode.
                Logger.OpenId.ErrorFormat("An error occurred while trying to create an association with {0}.  {1}", provider.Endpoint, ex);
                return null;
            }
        }
Example #20
0
        /// <summary>
        /// Creates an association request message that is appropriate for a given Provider.
        /// </summary>
        /// <param name="securityRequirements">The set of requirements the selected association type must comply to.</param>
        /// <param name="provider">The provider to create an association with.</param>
        /// <param name="associationType">Type of the association.</param>
        /// <param name="sessionType">Type of the session.</param>
        /// <returns>
        /// The message to send to the Provider to request an association.
        /// Null if no association could be created that meet the security requirements
        /// and the provider OpenID version.
        /// </returns>
        internal static AssociateRequest Create(SecuritySettings securityRequirements, ProviderEndpointDescription provider, string associationType, string sessionType)
        {
            ErrorUtilities.VerifyArgumentNotNull(securityRequirements, "securityRequirements");
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");
            ErrorUtilities.VerifyNonZeroLength(associationType, "associationType");
            ErrorUtilities.VerifyArgumentNotNull(sessionType, "sessionType");

            bool unencryptedAllowed = provider.Endpoint.IsTransportSecure();

            if (unencryptedAllowed)
            {
                var associateRequest = new AssociateUnencryptedRequest(provider.ProtocolVersion, provider.Endpoint);
                associateRequest.AssociationType = associationType;
                return(associateRequest);
            }
            else
            {
                var associateRequest = new AssociateDiffieHellmanRequest(provider.ProtocolVersion, provider.Endpoint);
                associateRequest.AssociationType = associationType;
                associateRequest.SessionType     = sessionType;
                associateRequest.InitializeRequest();
                return(associateRequest);
            }
        }
        /// <summary>
        /// Creates a new association with a given Provider.
        /// </summary>
        /// <param name="provider">The provider to create an association with.</param>
        /// <param name="associateRequest">The associate request.  May be <c>null</c>, which will always result in a <c>null</c> return value..</param>
        /// <param name="retriesRemaining">The number of times to try the associate request again if the Provider suggests it.</param>
        /// <returns>
        /// The newly created association, or null if no association can be created with
        /// the given Provider given the current security settings.
        /// </returns>
        private Association CreateNewAssociation(ProviderEndpointDescription provider, AssociateRequest associateRequest, int retriesRemaining)
        {
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");

            if (associateRequest == null || retriesRemaining < 0)
            {
                // this can happen if security requirements and protocol conflict
                // to where there are no association types to choose from.
                return(null);
            }

            try {
                var associateResponse             = this.channel.Request(associateRequest);
                var associateSuccessfulResponse   = associateResponse as AssociateSuccessfulResponse;
                var associateUnsuccessfulResponse = associateResponse as AssociateUnsuccessfulResponse;
                if (associateSuccessfulResponse != null)
                {
                    Association association = associateSuccessfulResponse.CreateAssociation(associateRequest, null);
                    this.associationStore.StoreAssociation(provider.Endpoint, association);
                    return(association);
                }
                else if (associateUnsuccessfulResponse != null)
                {
                    if (string.IsNullOrEmpty(associateUnsuccessfulResponse.AssociationType))
                    {
                        Logger.Debug("Provider rejected an association request and gave no suggestion as to an alternative association type.  Giving up.");
                        return(null);
                    }

                    if (!this.securitySettings.IsAssociationInPermittedRange(Protocol.Lookup(provider.ProtocolVersion), associateUnsuccessfulResponse.AssociationType))
                    {
                        Logger.DebugFormat("Provider rejected an association request and suggested '{0}' as an association to try, which this Relying Party does not support.  Giving up.", associateUnsuccessfulResponse.AssociationType);
                        return(null);
                    }

                    if (retriesRemaining <= 0)
                    {
                        Logger.Debug("Unable to agree on an association type with the Provider in the allowed number of retries.  Giving up.");
                        return(null);
                    }

                    // Make sure the Provider isn't suggesting an incompatible pair of association/session types.
                    Protocol protocol = Protocol.Lookup(provider.ProtocolVersion);
                    ErrorUtilities.VerifyProtocol(
                        HmacShaAssociation.IsDHSessionCompatible(protocol, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType),
                        OpenIdStrings.IncompatibleAssociationAndSessionTypes,
                        associateUnsuccessfulResponse.AssociationType,
                        associateUnsuccessfulResponse.SessionType);

                    associateRequest = AssociateRequest.Create(this.securitySettings, provider, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType);
                    return(this.CreateNewAssociation(provider, associateRequest, retriesRemaining - 1));
                }
                else
                {
                    throw new ProtocolException(MessagingStrings.UnexpectedMessageReceivedOfMany);
                }
            } catch (ProtocolException ex) {
                // Since having associations with OPs is not totally critical, we'll log and eat
                // the exception so that auth may continue in dumb mode.
                Logger.ErrorFormat("An error occurred while trying to create an association with {0}.  {1}", provider.Endpoint, ex);
                return(null);
            }
        }
Example #22
0
        /// <summary>
        /// Creates a <see cref="ServiceEndpoint"/> instance to represent some OP Identifier.
        /// </summary>
        /// <param name="providerIdentifier">The provider identifier.</param>
        /// <param name="providerEndpoint">The provider endpoint.</param>
        /// <param name="servicePriority">The service priority.</param>
        /// <param name="uriPriority">The URI priority.</param>
        /// <returns>The created <see cref="ServiceEndpoint"/> instance</returns>
        internal static ServiceEndpoint CreateForProviderIdentifier(Identifier providerIdentifier, ProviderEndpointDescription providerEndpoint, int?servicePriority, int?uriPriority)
        {
            ErrorUtilities.VerifyArgumentNotNull(providerEndpoint, "providerEndpoint");

            Protocol protocol = Protocol.Detect(providerEndpoint.Capabilities);

            return(new ServiceEndpoint(
                       providerEndpoint,
                       protocol.ClaimedIdentifierForOPIdentifier,
                       providerIdentifier,
                       protocol.ClaimedIdentifierForOPIdentifier,
                       servicePriority,
                       uriPriority));
        }
 /// <summary>
 /// Gets an existing association with the specified Provider, or attempts to create
 /// a new association of one does not already exist.
 /// </summary>
 /// <param name="provider">The provider to get an association for.</param>
 /// <returns>The existing or new association; <c>null</c> if none existed and one could not be created.</returns>
 internal Association GetOrCreateAssociation(ProviderEndpointDescription provider)
 {
     return(this.GetExistingAssociation(provider) ?? this.CreateNewAssociation(provider));
 }
Example #24
0
 /// <summary>
 /// Creates a <see cref="ServiceEndpoint"/> instance to represent some Claimed Identifier.
 /// </summary>
 /// <param name="claimedIdentifier">The claimed identifier.</param>
 /// <param name="providerLocalIdentifier">The provider local identifier.</param>
 /// <param name="providerEndpoint">The provider endpoint.</param>
 /// <param name="servicePriority">The service priority.</param>
 /// <param name="uriPriority">The URI priority.</param>
 /// <returns>The created <see cref="ServiceEndpoint"/> instance</returns>
 internal static ServiceEndpoint CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier providerLocalIdentifier, ProviderEndpointDescription providerEndpoint, int?servicePriority, int?uriPriority)
 {
     return(CreateForClaimedIdentifier(claimedIdentifier, null, providerLocalIdentifier, providerEndpoint, servicePriority, uriPriority));
 }
Example #25
0
 /// <summary>
 /// Gets an existing association with the specified Provider, or attempts to create
 /// a new association of one does not already exist.
 /// </summary>
 /// <param name="provider">The provider to get an association for.</param>
 /// <returns>The existing or new association; <c>null</c> if none existed and one could not be created.</returns>
 internal Association GetOrCreateAssociation(ProviderEndpointDescription provider)
 {
     return this.GetExistingAssociation(provider) ?? this.CreateNewAssociation(provider);
 }
Example #26
0
        /// <summary>
        /// Creates an association request message that is appropriate for a given Provider.
        /// </summary>
        /// <param name="securityRequirements">The set of requirements the selected association type must comply to.</param>
        /// <param name="provider">The provider to create an association with.</param>
        /// <returns>
        /// The message to send to the Provider to request an association.
        /// Null if no association could be created that meet the security requirements
        /// and the provider OpenID version.
        /// </returns>
        internal static AssociateRequest Create(SecuritySettings securityRequirements, ProviderEndpointDescription provider)
        {
            ErrorUtilities.VerifyArgumentNotNull(securityRequirements, "securityRequirements");
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");

            // Apply our knowledge of the endpoint's transport, OpenID version, and
            // security requirements to decide the best association.
            bool   unencryptedAllowed = provider.Endpoint.IsTransportSecure();
            bool   useDiffieHellman = !unencryptedAllowed;
            string associationType, sessionType;

            if (!HmacShaAssociation.TryFindBestAssociation(Protocol.Lookup(provider.ProtocolVersion), true, securityRequirements, useDiffieHellman, out associationType, out sessionType))
            {
                // There are no associations that meet all requirements.
                Logger.Warn("Security requirements and protocol combination knock out all possible association types.  Dumb mode forced.");
                return(null);
            }

            return(Create(securityRequirements, provider, associationType, sessionType));
        }
Example #27
0
        /// <summary>
        /// Creates a new association with a given Provider.
        /// </summary>
        /// <param name="provider">The provider to create an association with.</param>
        /// <returns>
        /// The newly created association, or null if no association can be created with
        /// the given Provider given the current security settings.
        /// </returns>
        /// <remarks>
        /// A new association is created and returned even if one already exists in the
        /// association store.
        /// Any new association is automatically added to the <see cref="associationStore"/>.
        /// </remarks>
        private Association CreateNewAssociation(ProviderEndpointDescription provider)
        {
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");

            // If there is no association store, there is no point in creating an association.
            if (this.associationStore == null) {
                return null;
            }

            var associateRequest = AssociateRequest.Create(this.securitySettings, provider);

            const int RenegotiateRetries = 1;
            return this.CreateNewAssociation(provider, associateRequest, RenegotiateRetries);
        }
        public void NonNullCapabilities()
        {
            var epd = new ProviderEndpointDescription(OPUri, Protocol.Default.Version);

            Assert.IsNotNull(epd.Capabilities);
        }
Example #29
0
        /// <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 async Task ParameterizedAssociationTestAsync(
            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;
            var relyingParty = new OpenIdRelyingParty(new MemoryCryptoKeyAndNonceStore(), this.HostFactories);
            var provider = new OpenIdProvider(new MemoryCryptoKeyAndNonceStore(), this.HostFactories)
            {
                SecuritySettings = this.ProviderSecuritySettings
            };

            Handle(opDescription.Uri).By(
                async(request, ct) => {
                IRequest req = await provider.GetRequestAsync(request, ct);
                Assert.IsNotNull(req, "Expected incoming request but did not receive it.");
                Assert.IsTrue(req.IsResponseReady);
                return(await provider.PrepareResponseAsync(req, ct));
            });
            relyingParty.Channel.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;
                }
            };
            relyingParty.Channel.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);
            };

            relyingParty.SecuritySettings = this.RelyingPartySecuritySettings;
            rpAssociation = await relyingParty.AssociationManager.GetOrCreateAssociationAsync(opDescription, CancellationToken.None);

            if (expectSuccess)
            {
                Assert.IsNotNull(rpAssociation);
                Association actual = relyingParty.AssociationManager.AssociationStoreTestHook.GetAssociation(opDescription.Uri, rpAssociation.Handle);
                Assert.AreEqual(rpAssociation, actual);
                opAssociation = 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(relyingParty.AssociationManager.AssociationStoreTestHook.GetAssociation(opDescription.Uri, new RelyingPartySecuritySettings()));
            }
        }
Example #30
0
 /// <summary>
 /// Creates a <see cref="ServiceEndpoint"/> instance to represent some Claimed Identifier.
 /// </summary>
 /// <param name="claimedIdentifier">The claimed identifier.</param>
 /// <param name="userSuppliedIdentifier">The user supplied identifier.</param>
 /// <param name="providerLocalIdentifier">The provider local identifier.</param>
 /// <param name="providerEndpoint">The provider endpoint.</param>
 /// <param name="servicePriority">The service priority.</param>
 /// <param name="uriPriority">The URI priority.</param>
 /// <returns>The created <see cref="ServiceEndpoint"/> instance</returns>
 internal static ServiceEndpoint CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, ProviderEndpointDescription providerEndpoint, int?servicePriority, int?uriPriority)
 {
     return(new ServiceEndpoint(providerEndpoint, claimedIdentifier, userSuppliedIdentifier, providerLocalIdentifier, servicePriority, uriPriority));
 }