Ejemplo n.º 1
0
        /// <summary>
        /// Creates a new association with a given Provider.
        /// </summary>
        /// <param name="provider">The provider to create an association with.</param>
        /// <param name="cancellationToken">The cancellation token.</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 async Task <Association> CreateNewAssociationAsync(IProviderEndpoint provider, CancellationToken cancellationToken)
        {
            Requires.NotNull(provider, "provider");

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

            try {
                var associateRequest = AssociateRequestRelyingParty.Create(this.securitySettings, provider);

                const int RenegotiateRetries = 1;
                return(await this.CreateNewAssociationAsync(provider, associateRequest, RenegotiateRetries, cancellationToken));
            } catch (VerificationException ex) {
                // See Trac ticket #163.  In partial trust host environments, the
                // Diffie-Hellman implementation we're using for HTTP OP endpoints
                // sometimes causes the CLR to throw:
                // "VerificationException: Operation could destabilize the runtime."
                // Just give up and use dumb mode in this case.
                Logger.OpenId.ErrorFormat("VerificationException occurred while trying to create an association with {0}.  {1}", provider.Uri, ex);
                return(null);
            }
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        private HttpRequestInfo CreateAssociateRequest(Uri opEndpoint)
        {
            var rp = CreateRelyingParty(true);
            AssociateRequest associateMessage = AssociateRequestRelyingParty.Create(rp.SecuritySettings, new ProviderEndpointDescription(opEndpoint, Protocol.Default.Version));
            Channel          rpChannel        = rp.Channel;
            MemoryStream     ms       = new MemoryStream();
            StreamWriter     mswriter = new StreamWriter(ms);

            mswriter.Write(MessagingUtilities.CreateQueryString(rpChannel.MessageDescriptions.GetAccessor(associateMessage)));
            mswriter.Flush();
            ms.Position = 0;
            var headers = new WebHeaderCollection();

            headers.Add(HttpRequestHeader.ContentType, Channel.HttpFormUrlEncoded);
            var httpRequest = new HttpRequestInfo("POST", opEndpoint, headers, ms);

            return(httpRequest);
        }
Ejemplo n.º 5
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();
        }
Ejemplo n.º 6
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>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// The newly created association, or null if no association can be created with
        /// the given Provider given the current security settings.
        /// </returns>
        /// <exception cref="ProtocolException">Create if an error occurs while creating the new association.</exception>
        private async Task <Association> CreateNewAssociationAsync(IProviderEndpoint provider, AssociateRequest associateRequest, int retriesRemaining, CancellationToken cancellationToken)
        {
            Requires.NotNull(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);
            }

            Exception exception = null;

            try {
                var associateResponse = await this.channel.RequestAsync(associateRequest, cancellationToken);

                var associateSuccessfulResponse   = associateResponse as IAssociateSuccessfulResponseRelyingParty;
                var associateUnsuccessfulResponse = associateResponse as AssociateUnsuccessfulResponse;
                if (associateSuccessfulResponse != null)
                {
                    Association association = associateSuccessfulResponse.CreateAssociationAtRelyingParty(associateRequest);
                    this.associationStore.StoreAssociation(provider.Uri, 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.Version), 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.Version);
                    ErrorUtilities.VerifyProtocol(
                        HmacShaAssociation.IsDHSessionCompatible(protocol, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType),
                        OpenIdStrings.IncompatibleAssociationAndSessionTypes,
                        associateUnsuccessfulResponse.AssociationType,
                        associateUnsuccessfulResponse.SessionType);

                    associateRequest = AssociateRequestRelyingParty.Create(this.securitySettings, provider, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType);
                    return(await this.CreateNewAssociationAsync(provider, associateRequest, retriesRemaining - 1, cancellationToken));
                }
                else
                {
                    throw new ProtocolException(MessagingStrings.UnexpectedMessageReceivedOfMany);
                }
            } catch (ProtocolException ex) {
                exception = ex;
            }

            Assumes.NotNull(exception);

            // 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 (UntrustedWebRequestHandler.IsExceptionFrom417ExpectationFailed(exception))
            {
                return(await this.CreateNewAssociationAsync(provider, associateRequest, retriesRemaining - 1, cancellationToken));
            }

            // 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.Uri, exception);
            return(null);
        }