コード例 #1
0
        /// <summary>
        /// Performs any transformation on an incoming message that may be necessary and/or
        /// validates an incoming message based on the rules of this channel binding element.
        /// </summary>
        /// <param name="message">The incoming message to process.</param>
        /// <returns>
        /// The protections (if any) that this binding element applied to the message.
        /// Null if this binding element did not even apply to this binding element.
        /// </returns>
        /// <exception cref="ProtocolException">
        /// Thrown when the binding element rules indicate that this message is invalid and should
        /// NOT be processed.
        /// </exception>
        /// <remarks>
        /// Implementations that provide message protection must honor the
        /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
        /// </remarks>
        public MessageProtections?ProcessIncomingMessage(IProtocolMessage message)
        {
            IndirectSignedResponse response = message as IndirectSignedResponse;

            if (this.UseRequestNonce(response))
            {
                if (!response.ReturnToParametersSignatureValidated)
                {
                    Logger.OpenId.Error("Incoming message is expected to have a nonce, but the return_to parameter is not signed.");
                }

                string nonceValue = response.GetReturnToArgument(NonceParameter);
                ErrorUtilities.VerifyProtocol(
                    nonceValue != null && response.ReturnToParametersSignatureValidated,
                    this.securitySettings.RejectUnsolicitedAssertions ? OpenIdStrings.UnsolicitedAssertionsNotAllowed : OpenIdStrings.UnsolicitedAssertionsNotAllowedFrom1xOPs);

                CustomNonce nonce          = CustomNonce.Deserialize(nonceValue);
                DateTime    expirationDate = nonce.CreationDateUtc + MaximumMessageAge;
                if (expirationDate < DateTime.UtcNow)
                {
                    throw new ExpiredMessageException(expirationDate, message);
                }

                IReplayProtectedProtocolMessage replayResponse = response;
                if (!this.nonceStore.StoreNonce(replayResponse.NonceContext, nonce.RandomPartAsString, nonce.CreationDateUtc))
                {
                    Logger.OpenId.ErrorFormat("Replayed nonce detected ({0} {1}).  Rejecting message.", replayResponse.Nonce, replayResponse.UtcCreationDate);
                    throw new ReplayedMessageException(message);
                }

                return(MessageProtections.ReplayProtection);
            }

            return(null);
        }
コード例 #2
0
        /// <summary>
        /// Performs any transformation on an incoming message that may be necessary and/or
        /// validates an incoming message based on the rules of this channel binding element.
        /// </summary>
        /// <param name="message">The incoming message to process.</param>
        /// <returns>
        /// True if the <paramref name="message"/> applied to this binding element
        /// and the operation was successful.  False if the operation did not apply to this message.
        /// </returns>
        /// <exception cref="ProtocolException">
        /// Thrown when the binding element rules indicate that this message is invalid and should
        /// NOT be processed.
        /// </exception>
        /// <remarks>
        /// Implementations that provide message protection must honor the
        /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
        /// </remarks>
        public bool PrepareMessageForReceiving(IProtocolMessage message)
        {
            IndirectSignedResponse response = message as IndirectSignedResponse;

            if (response != null && response.Version.Major < 2)
            {
                string nonceValue = response.GetReturnToArgument(NonceParameter);
                ErrorUtilities.VerifyProtocol(nonceValue != null, OpenIdStrings.UnsolicitedAssertionsNotAllowedFrom1xOPs);

                CustomNonce nonce          = CustomNonce.Deserialize(nonceValue);
                DateTime    expirationDate = nonce.CreationDateUtc + MaximumMessageAge;
                if (expirationDate < DateTime.UtcNow)
                {
                    throw new ExpiredMessageException(expirationDate, message);
                }

                if (!this.nonceStore.StoreNonce(nonce.RandomPartAsString, nonce.CreationDateUtc))
                {
                    throw new ReplayedMessageException(message);
                }

                return(true);
            }

            return(false);
        }
コード例 #3
0
        /// <summary>
        /// Gets a specific association referenced in a given message's association handle.
        /// </summary>
        /// <param name="signedMessage">The signed message whose association handle should be used to lookup the association to return.</param>
        /// <returns>The referenced association; or <c>null</c> if such an association cannot be found.</returns>
        /// <remarks>
        /// If the association handle set in the message does not match any valid association,
        /// the association handle property is cleared, and the
        /// <see cref="ITamperResistantOpenIdMessage.InvalidateHandle"/> property is set to the
        /// handle that could not be found.
        /// </remarks>
        private Association GetSpecificAssociation(ITamperResistantOpenIdMessage signedMessage)
        {
            Association association = null;

            if (!string.IsNullOrEmpty(signedMessage.AssociationHandle))
            {
                IndirectSignedResponse indirectSignedMessage = signedMessage as IndirectSignedResponse;
                if (this.IsOnProvider)
                {
                    // Since we have an association handle, we're either signing with a smart association,
                    // or verifying a dumb one.
                    bool signing = string.IsNullOrEmpty(signedMessage.Signature);
                    AssociationRelyingPartyType type = signing ? AssociationRelyingPartyType.Smart : AssociationRelyingPartyType.Dumb;
                    association = this.opAssociations.GetAssociation(type, signedMessage.AssociationHandle);
                    if (association == null)
                    {
                        // There was no valid association with the requested handle.
                        // Let's tell the RP to forget about that association.
                        signedMessage.InvalidateHandle  = signedMessage.AssociationHandle;
                        signedMessage.AssociationHandle = null;
                    }
                }
                else if (this.rpAssociations != null)                     // if on a smart RP
                {
                    Uri providerEndpoint = indirectSignedMessage.ProviderEndpoint;
                    association = this.rpAssociations.GetAssociation(providerEndpoint, signedMessage.AssociationHandle);
                }
            }

            return(association);
        }
コード例 #4
0
        public void SignedResponsesIncludeExtraDataInSignature()
        {
            Protocol protocol         = Protocol.Default;
            SigningBindingElement sbe = new SigningBindingElement(new AssociationMemoryStore <AssociationRelyingPartyType>(), new ProviderSecuritySettings());

            sbe.Channel = new TestChannel(this.MessageDescriptions);
            IndirectSignedResponse response = new IndirectSignedResponse(protocol.Version, RPUri);

            response.ReturnTo         = RPUri;
            response.ProviderEndpoint = OPUri;

            response.ExtraData["someunsigned"]      = "value";
            response.ExtraData["openid.somesigned"] = "value";

            Assert.IsNotNull(sbe.ProcessOutgoingMessage(response));
            ITamperResistantOpenIdMessage signedResponse = (ITamperResistantOpenIdMessage)response;

            // Make sure that the extra parameters are signed.
            // Since the signing algorithm only allows for signing parameters that start with
            // 'openid.', other parameters should not be signed.
            Assert.IsNotNull(signedResponse.SignedParameterOrder);
            string[] signedParameters = signedResponse.SignedParameterOrder.Split(',');
            Assert.IsTrue(signedParameters.Contains("somesigned"));
            Assert.IsFalse(signedParameters.Contains("someunsigned"));
        }
コード例 #5
0
        public void SignaturesMatchKnownGood()
        {
            Protocol protocol    = Protocol.V20;
            var      settings    = new ProviderSecuritySettings();
            var      cryptoStore = new MemoryCryptoKeyStore();

            byte[] associationSecret = Convert.FromBase64String("rsSwv1zPWfjPRQU80hciu8FPDC+GONAMJQ/AvSo1a2M=");
            string handle            = "mock";

            cryptoStore.StoreKey(ProviderAssociationKeyStorage.SharedAssociationBucket, handle, new CryptoKey(associationSecret, DateTime.UtcNow.AddDays(1)));

            var store = new ProviderAssociationKeyStorage(cryptoStore);
            SigningBindingElement signer = new ProviderSigningBindingElement(store, settings);

            signer.Channel = new TestChannel(this.MessageDescriptions);

            IndirectSignedResponse        message       = new IndirectSignedResponse(protocol.Version, new Uri("http://rp"));
            ITamperResistantOpenIdMessage signedMessage = message;

            message.ProviderEndpoint        = new Uri("http://provider");
            signedMessage.UtcCreationDate   = DateTime.Parse("1/1/2009");
            signedMessage.AssociationHandle = handle;
            Assert.IsNotNull(signer.ProcessOutgoingMessage(message));
            Assert.AreEqual("o9+uN7qTaUS9v0otbHTuNAtbkpBm14+es9QnNo6IHD4=", signedMessage.Signature);
        }
コード例 #6
0
        public void MissingSignedParameter()
        {
            var cryptoStore = new MemoryCryptoKeyStore();

            byte[] associationSecret = Convert.FromBase64String("rsSwv1zPWfjPRQU80hciu8FPDC+GONAMJQ/AvSo1a2M=");
            string handle            = "{634477555066085461}{TTYcIg==}{32}";

            cryptoStore.StoreKey(ProviderAssociationKeyStorage.PrivateAssociationBucket, handle, new CryptoKey(associationSecret, DateTime.UtcNow.AddDays(1)));

            var signer      = new ProviderSigningBindingElement(new ProviderAssociationKeyStorage(cryptoStore), new ProviderSecuritySettings());
            var testChannel = new TestChannel(new OpenIdProviderMessageFactory());

            signer.Channel = testChannel;

            var buggyRPMessage = new Dictionary <string, string>()
            {
                { "openid.assoc_handle", "{634477555066085461}{TTYcIg==}{32}" },
                { "openid.claimed_id", "https://openid.stackexchange.com/user/f5e91123-e5b4-43c5-871f-5f276c75d31a" },
                { "openid.identity", "https://openid.stackexchange.com/user/f5e91123-e5b4-43c5-871f-5f276c75d31a" },
                { "openid.mode", "check_authentication" },
                { "openid.op_endpoint", "https://openid.stackexchange.com/openid/provider" },
                { "openid.response_nonce", "2011-08-01T00:32:10Zvdyt3efw" },
                { "openid.return_to", "http://openid-consumer.appspot.com/finish?session_id=1543025&janrain_nonce=2011-08-01T00%3A32%3A09ZIPGz7D" },
                { "openid.sig", "b0Rll6Kt1KKBWWBEg/qBvW3sQYtmhOUmpI0/UREBVZ0=" },
                { "openid.signed", "claimed_id,identity,assoc_handle,op_endpoint,return_to,response_nonce,ns.sreg,sreg.email,sreg.fullname" },
                { "openid.sreg.email", "*****@*****.**" },
                { "openid.sreg.fullname", "Kevin K Montrose" },
            };
            var message          = (CheckAuthenticationRequest)testChannel.Receive(buggyRPMessage, new MessageReceivingEndpoint(OPUri, HttpDeliveryMethods.PostRequest));
            var originalResponse = new IndirectSignedResponse(message, signer.Channel);

            signer.ProcessIncomingMessage(originalResponse);
        }
コード例 #7
0
        /// <summary>
        /// Performs any transformation on an incoming message that may be necessary and/or
        /// validates an incoming message based on the rules of this channel binding element.
        /// </summary>
        /// <param name="message">The incoming message to process.</param>
        /// <returns>
        /// True if the <paramref name="message"/> applied to this binding element
        /// and the operation was successful.  False if the operation did not apply to this message.
        /// </returns>
        /// <exception cref="ProtocolException">
        /// Thrown when the binding element rules indicate that this message is invalid and should
        /// NOT be processed.
        /// </exception>
        /// <remarks>
        /// Implementations that provide message protection must honor the
        /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
        /// </remarks>
        public bool PrepareMessageForReceiving(IProtocolMessage message)
        {
            IndirectSignedResponse response = message as IndirectSignedResponse;

            if (response != null && response.Version.Major < 2)
            {
                // Although GetReturnToArgument may return null if the parameters are not signed,
                // the ReturnToSignatureBindingElement should have thrown an exception already
                // if this is a 1.0 OP signed response without a valid signature since 1.0 OPs
                // are not supposed to be able to send unsolicited assertions.
                // Any safe solicited assertion would include our signature, allowing us to find
                // these values.
                if (response.ProviderEndpoint == null)
                {
                    string op_endpoint = response.GetReturnToArgument(ProviderEndpointParameterName);
                    response.ProviderEndpoint = new Uri(op_endpoint);
                }

                PositiveAssertionResponse authResponse = response as PositiveAssertionResponse;
                if (authResponse != null)
                {
                    if (authResponse.ClaimedIdentifier == null)
                    {
                        authResponse.ClaimedIdentifier = response.GetReturnToArgument(ClaimedIdentifierParameterName);
                    }
                }

                return(true);
            }

            return(false);
        }
コード例 #8
0
        /// <summary>
        /// Performs any transformation on an incoming message that may be necessary and/or
        /// validates an incoming message based on the rules of this channel binding element.
        /// </summary>
        /// <param name="message">The incoming message to process.</param>
        /// <returns>
        /// The protections (if any) that this binding element applied to the message.
        /// Null if this binding element did not even apply to this binding element.
        /// </returns>
        /// <exception cref="ProtocolException">
        /// Thrown when the binding element rules indicate that this message is invalid and should
        /// NOT be processed.
        /// </exception>
        /// <remarks>
        /// Implementations that provide message protection must honor the
        /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
        /// </remarks>
        public MessageProtections?ProcessIncomingMessage(IProtocolMessage message)
        {
            IndirectSignedResponse response = message as IndirectSignedResponse;

            if (response != null)
            {
                // We can't use response.GetReturnToArgument(string) because that relies
                // on us already having validated this signature.
                NameValueCollection returnToParameters = HttpUtility.ParseQueryString(response.ReturnTo.Query);

                // Only check the return_to signature if one is present.
                if (returnToParameters[ReturnToSignatureHandleParameterName] != null)
                {
                    // Set the safety flag showing whether the return_to url had a valid signature.
                    byte[] expectedBytes = this.GetReturnToSignature(response.ReturnTo);
                    string actual        = returnToParameters[ReturnToSignatureParameterName];
                    actual = OpenIdUtilities.FixDoublyUriDecodedBase64String(actual);
                    byte[] actualBytes = Convert.FromBase64String(actual);
                    response.ReturnToParametersSignatureValidated = MessagingUtilities.AreEquivalentConstantTime(actualBytes, expectedBytes);
                    if (!response.ReturnToParametersSignatureValidated)
                    {
                        Logger.Bindings.WarnFormat("The return_to signature failed verification.");
                    }

                    return(MessageProtections.None);
                }
            }

            return(null);
        }
コード例 #9
0
        /// <summary>
        /// Performs any transformation on an incoming message that may be necessary and/or
        /// validates an incoming message based on the rules of this channel binding element.
        /// </summary>
        /// <param name="message">The incoming message to process.</param>
        /// <returns>
        /// True if the <paramref name="message"/> applied to this binding element
        /// and the operation was successful.  False if the operation did not apply to this message.
        /// </returns>
        /// <exception cref="ProtocolException">
        /// Thrown when the binding element rules indicate that this message is invalid and should
        /// NOT be processed.
        /// </exception>
        /// <remarks>
        /// Implementations that provide message protection must honor the
        /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
        /// </remarks>
        public bool PrepareMessageForReceiving(IProtocolMessage message)
        {
            IndirectSignedResponse response = message as IndirectSignedResponse;

            if (response != null)
            {
                // We can't use response.GetReturnToArgument(string) because that relies
                // on us already having validated this signature.
                NameValueCollection returnToParameters = HttpUtility.ParseQueryString(response.ReturnTo.Query);

                // Only check the return_to signature if one is present.
                if (returnToParameters[ReturnToSignatureHandleParameterName] != null)
                {
                    // Set the safety flag showing whether the return_to url had a valid signature.
                    string expected = this.GetReturnToSignature(response.ReturnTo);
                    string actual   = returnToParameters[ReturnToSignatureParameterName];
                    actual = OpenIdUtilities.FixDoublyUriDecodedBase64String(actual);
                    response.ReturnToParametersSignatureValidated = actual == expected;
                    if (!response.ReturnToParametersSignatureValidated)
                    {
                        Logger.WarnFormat("The return_to signature failed verification.");
                    }

                    return(true);
                }
            }

            return(false);
        }
コード例 #10
0
        internal AnonymousRequest(OpenIdProvider provider, SignedResponseRequest request)
            : base(provider, request)
        {
            Requires.NotNull(provider, "provider");
            Requires.That(!(request is CheckIdRequest), "request", "request cannot be CheckIdRequest");

            this.positiveResponse = new IndirectSignedResponse(request);
        }
コード例 #11
0
        internal AnonymousRequest(OpenIdProvider provider, SignedResponseRequest request)
            : base(provider, request)
        {
            Contract.Requires <ArgumentNullException>(provider != null);
            Contract.Requires <ArgumentException>(!(request is CheckIdRequest), "Instantiate " + typeof(AuthenticationRequest).Name + " to handle this kind of message.");

            this.positiveResponse = new IndirectSignedResponse(request);
        }
コード例 #12
0
        public override void SetUp()
        {
            base.SetUp();

            IndirectSignedResponse responseMessage = new IndirectSignedResponse(Protocol.Default.Version, RPUri);

            this.extensions = responseMessage.Extensions;
            this.response   = new DotNetOpenAuth.OpenId.RelyingParty.PositiveAnonymousResponse(responseMessage);
        }
コード例 #13
0
        /// <summary>
        /// Creates a response message with one extensions.
        /// </summary>
        /// <param name="protocol">The protocol to construct the message with.</param>
        /// <returns>The message ready to send from OP to RP.</returns>
        private IndirectSignedResponse CreateResponseWithExtensions(Protocol protocol)
        {
            Requires.NotNull(protocol, "protocol");

            IndirectSignedResponse response = new IndirectSignedResponse(protocol.Version, RPUri);

            response.ProviderEndpoint = OPUri;
            response.Extensions.Add(new MockOpenIdExtension("pv", "ev"));
            return(response);
        }
コード例 #14
0
        /// <summary>
        /// Creates a response message with one extensions.
        /// </summary>
        /// <param name="protocol">The protocol to construct the message with.</param>
        /// <returns>The message ready to send from OP to RP.</returns>
        private IndirectSignedResponse CreateResponseWithExtensions(Protocol protocol)
        {
            Contract.Requires <ArgumentNullException>(protocol != null);

            IndirectSignedResponse response = new IndirectSignedResponse(protocol.Version, RPUri);

            response.ProviderEndpoint = OPUri;
            response.Extensions.Add(new MockOpenIdExtension("pv", "ev"));
            return(response);
        }
コード例 #15
0
        public void ProviderTest()
        {
            var responseMessage = new IndirectSignedResponse(Protocol.V20.Version, this.returnTo);

            responseMessage.ProviderEndpoint = OPUri;
            var response = new PositiveAnonymousResponse(responseMessage);

            Assert.IsNotNull(response.Provider);
            Assert.AreEqual(OPUri, response.Provider.Uri);
            Assert.AreEqual(responseMessage.Version, response.Provider.Version);
        }
コード例 #16
0
        public override void SetUp()
        {
            base.SetUp();

            this.protocol         = Protocol.V20;
            this.request          = new CheckIdRequest(this.protocol.Version, OPUri, AuthenticationRequestMode.Setup);
            this.request.ReturnTo = RPUri;
            this.response         = new IndirectSignedResponse(this.request);

            this.unsolicited = new IndirectSignedResponse(this.protocol.Version, RPUri);
        }
コード例 #17
0
        /// <summary>
        /// Analyzes an incoming request message payload to discover what kind of
        /// message is embedded in it and returns the type, or null if no match is found.
        /// </summary>
        /// <param name="recipient">The intended or actual recipient of the request message.</param>
        /// <param name="fields">The name/value pairs that make up the message payload.</param>
        /// <returns>
        /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can
        /// deserialize to.  Null if the request isn't recognized as a valid protocol message.
        /// </returns>
        public IDirectedProtocolMessage GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary <string, string> fields)
        {
            RequestBase message = null;

            // Discern the OpenID version of the message.
            Protocol protocol = Protocol.V11;
            string   ns;

            if (fields.TryGetValue(Protocol.V20.openid.ns, out ns))
            {
                ErrorUtilities.VerifyProtocol(string.Equals(ns, Protocol.OpenId2Namespace, StringComparison.Ordinal), MessagingStrings.UnexpectedMessagePartValue, Protocol.V20.openid.ns, ns);
                protocol = Protocol.V20;
            }

            string mode;

            if (fields.TryGetValue(protocol.openid.mode, out mode))
            {
                if (string.Equals(mode, protocol.Args.Mode.cancel) ||
                    (string.Equals(mode, protocol.Args.Mode.setup_needed) && (protocol.Version.Major >= 2 || fields.ContainsKey(protocol.openid.user_setup_url))))
                {
                    message = new NegativeAssertionResponse(protocol.Version, recipient.Location, mode);
                }
                else if (string.Equals(mode, protocol.Args.Mode.id_res))
                {
                    if (fields.ContainsKey(protocol.openid.identity))
                    {
                        message = new PositiveAssertionResponse(protocol.Version, recipient.Location);
                    }
                    else
                    {
                        ErrorUtilities.VerifyProtocol(!fields.ContainsKey(protocol.openid.claimed_id), OpenIdStrings.IdentityAndClaimedIdentifierMustBeBothPresentOrAbsent);
                        message = new IndirectSignedResponse(protocol.Version, recipient.Location);
                    }
                }
                else if (string.Equals(mode, protocol.Args.Mode.error))
                {
                    message = new IndirectErrorResponse(protocol.Version, recipient.Location);
                }
                else
                {
                    ErrorUtilities.ThrowProtocol(MessagingStrings.UnexpectedMessagePartValue, protocol.openid.mode, mode);
                }
            }

            if (message != null)
            {
                message.SetAsIncoming();
            }

            return(message);
        }
コード例 #18
0
        /// <summary>
        /// Gets the dictionary of message parts that should be deserialized into extensions.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="ignoreUnsigned">If set to <c>true</c> only signed extensions will be available.</param>
        /// <returns>
        /// A dictionary of message parts, including only signed parts when appropriate.
        /// </returns>
        private IDictionary <string, string> GetExtensionsDictionary(IProtocolMessage message, bool ignoreUnsigned)
        {
            RequiresEx.ValidState(this.Channel != null);

            IndirectSignedResponse signedResponse = message as IndirectSignedResponse;

            if (signedResponse != null && ignoreUnsigned)
            {
                return(signedResponse.GetSignedMessageParts(this.Channel));
            }
            else
            {
                return(this.Channel.MessageDescriptions.GetAccessor(message));
            }
        }
コード例 #19
0
        /// <summary>
        /// Gets a specific association referenced in a given message's association handle.
        /// </summary>
        /// <param name="signedMessage">The signed message whose association handle should be used to lookup the association to return.</param>
        /// <returns>
        /// The referenced association; or <c>null</c> if such an association cannot be found.
        /// </returns>
        protected override Association GetSpecificAssociation(ITamperResistantOpenIdMessage signedMessage)
        {
            Association association = null;

            if (!string.IsNullOrEmpty(signedMessage.AssociationHandle))
            {
                IndirectSignedResponse indirectSignedMessage = signedMessage as IndirectSignedResponse;
                if (this.rpAssociations != null)                   // if on a smart RP
                {
                    Uri providerEndpoint = indirectSignedMessage.ProviderEndpoint;
                    association = this.rpAssociations.GetAssociation(providerEndpoint, signedMessage.AssociationHandle);
                }
            }

            return(association);
        }
コード例 #20
0
        public void CtorAndProperties()
        {
            var responseMessage = new IndirectSignedResponse(Protocol.V20.Version, this.returnTo);
            var ext             = new ClaimsResponse();

            responseMessage.Extensions.Add(ext);
            var response = new PositiveAnonymousResponse(responseMessage);

            Assert.AreEqual(AuthenticationStatus.ExtensionsOnly, response.Status);
            Assert.AreSame(responseMessage, response.Response);
            Assert.IsNull(response.ClaimedIdentifier);
            Assert.IsNull(response.FriendlyIdentifierForDisplay);
            Assert.IsNull(response.Exception);
            Assert.IsNull(response.Provider);
            Assert.AreSame(ext, response.GetUntrustedExtension <ClaimsResponse>());
        }
コード例 #21
0
        /// <summary>
        /// Gets the dictionary of message parts that should be deserialized into extensions.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <returns>A dictionary of message parts, including only signed parts when appropriate.</returns>
        private IDictionary <string, string> GetExtensionsDictionary(IProtocolMessage message)
        {
            // An IndirectSignedResponse message (the only one we care to filter parts for)
            // can be received both by RPs and OPs (during check_auth).
            // Whichever party is reading the extensions, apply their security policy regarding
            // signing.  (Although OPs have no reason to deserialize extensions during check_auth)
            // so that scenario might be optimized away eventually.
            bool extensionsShouldBeSigned = this.rpSecuritySettings != null ? !this.rpSecuritySettings.AllowUnsignedIncomingExtensions : this.opSecuritySettings.SignOutgoingExtensions;

            IndirectSignedResponse signedResponse = message as IndirectSignedResponse;

            if (signedResponse != null && extensionsShouldBeSigned)
            {
                return(signedResponse.GetSignedMessageParts());
            }
            else
            {
                return(new MessageDictionary(message));
            }
        }
コード例 #22
0
        public void ExtensionResponsesAreSigned()
        {
            Protocol protocol = Protocol.Default;
            var      op       = this.CreateProvider();
            IndirectSignedResponse response = this.CreateResponseWithExtensions(protocol);

            op.Channel.PrepareResponse(response);
            ITamperResistantOpenIdMessage signedResponse = (ITamperResistantOpenIdMessage)response;
            string extensionAliasKey = signedResponse.ExtraData.Single(kv => kv.Value == MockOpenIdExtension.MockTypeUri).Key;

            Assert.IsTrue(extensionAliasKey.StartsWith("openid.ns."));
            string extensionAlias = extensionAliasKey.Substring("openid.ns.".Length);

            // Make sure that the extension members and the alias=namespace declaration are all signed.
            Assert.IsNotNull(signedResponse.SignedParameterOrder);
            string[] signedParameters = signedResponse.SignedParameterOrder.Split(',');
            Assert.IsTrue(signedParameters.Contains(extensionAlias + ".Part"));
            Assert.IsTrue(signedParameters.Contains(extensionAlias + ".data"));
            Assert.IsTrue(signedParameters.Contains("ns." + extensionAlias));
        }
コード例 #23
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PositiveAnonymousResponse"/> class.
        /// </summary>
        /// <param name="response">The response message.</param>
        protected internal PositiveAnonymousResponse(IndirectSignedResponse response)
        {
            Requires.NotNull(response, "response");

            this.response = response;
            if (response.ProviderEndpoint != null && response.Version != null)
            {
                this.provider = new ProviderEndpointDescription(response.ProviderEndpoint, response.Version);
            }

            // Derived types of this are responsible to log an appropriate message for themselves.
            if (Logger.OpenId.IsInfoEnabled && this.GetType() == typeof(PositiveAnonymousResponse))
            {
                Logger.OpenId.Info("Received anonymous (identity-less) positive assertion.");
            }

            if (response.ProviderEndpoint != null)
            {
                Reporting.RecordEventOccurrence(this, response.ProviderEndpoint.AbsoluteUri);
            }
        }
コード例 #24
0
        public void GetReturnToArgumentAndNames()
        {
            UriBuilder returnToBuilder = new UriBuilder(this.response.ReturnTo);

            returnToBuilder.AppendQueryArgs(new Dictionary <string, string> {
                { "a", "b" }
            });
            this.request.ReturnTo = returnToBuilder.Uri;

            // First pretend that the return_to args were signed.
            this.response = new IndirectSignedResponse(this.request);
            this.response.ReturnToParametersSignatureValidated = true;
            Assert.AreEqual(1, this.response.GetReturnToParameterNames().Count());
            Assert.IsTrue(this.response.GetReturnToParameterNames().Contains("a"));
            Assert.AreEqual("b", this.response.GetReturnToArgument("a"));

            // Now simulate them NOT being signed.  They should still be visible at this level.
            this.response = new IndirectSignedResponse(this.request);
            this.response.ReturnToParametersSignatureValidated = false;
            Assert.AreEqual(1, this.response.GetReturnToParameterNames().Count());
            Assert.IsTrue(this.response.GetReturnToParameterNames().Contains("a"));
            Assert.AreEqual("b", this.response.GetReturnToArgument("a"));
        }
コード例 #25
0
        public void SignaturesMatchKnownGood()
        {
            Protocol protocol = Protocol.V20;
            var      settings = new ProviderSecuritySettings();
            var      store    = new AssociationMemoryStore <AssociationRelyingPartyType>();

            byte[]      associationSecret = Convert.FromBase64String("rsSwv1zPWfjPRQU80hciu8FPDC+GONAMJQ/AvSo1a2M=");
            Association association       = HmacShaAssociation.Create("mock", associationSecret, TimeSpan.FromDays(1));

            store.StoreAssociation(AssociationRelyingPartyType.Smart, association);
            SigningBindingElement signer = new SigningBindingElement(store, settings);

            signer.Channel = new TestChannel(this.MessageDescriptions);

            IndirectSignedResponse        message       = new IndirectSignedResponse(protocol.Version, new Uri("http://rp"));
            ITamperResistantOpenIdMessage signedMessage = message;

            message.ProviderEndpoint        = new Uri("http://provider");
            signedMessage.UtcCreationDate   = DateTime.Parse("1/1/2009");
            signedMessage.AssociationHandle = association.Handle;
            Assert.IsNotNull(signer.ProcessOutgoingMessage(message));
            Assert.AreEqual("o9+uN7qTaUS9v0otbHTuNAtbkpBm14+es9QnNo6IHD4=", signedMessage.Signature);
        }
コード例 #26
0
        public Task <MessageProtections?> ProcessIncomingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken)
        {
            IndirectSignedResponse response = message as IndirectSignedResponse;

            if (response != null && response.Version.Major < 2)
            {
                // GetReturnToArgument may return parameters that are not signed,
                // but we must allow for that since in OpenID 1.x, a stateless RP has
                // no way to preserve the provider endpoint and claimed identifier otherwise.
                // We'll verify the positive assertion later in the
                // RelyingParty.PositiveAuthenticationResponse constructor anyway.
                // If this is a 1.0 OP signed response without these parameters then we didn't initiate
                // the request ,and since 1.0 OPs are not supposed to be able to send unsolicited
                // assertions it's an invalid case that we throw an exception for.
                if (response.ProviderEndpoint == null)
                {
                    string op_endpoint = response.GetReturnToArgument(ProviderEndpointParameterName);
                    ErrorUtilities.VerifyProtocol(op_endpoint != null, MessagingStrings.RequiredParametersMissing, message.GetType().Name, ProviderEndpointParameterName);
                    response.ProviderEndpoint = new Uri(op_endpoint);
                }

                PositiveAssertionResponse authResponse = response as PositiveAssertionResponse;
                if (authResponse != null)
                {
                    if (authResponse.ClaimedIdentifier == null)
                    {
                        string claimedId = response.GetReturnToArgument(ClaimedIdentifierParameterName);
                        ErrorUtilities.VerifyProtocol(claimedId != null, MessagingStrings.RequiredParametersMissing, message.GetType().Name, ClaimedIdentifierParameterName);
                        authResponse.ClaimedIdentifier = claimedId;
                    }
                }

                return(NoneTask);
            }

            return(NullTask);
        }
コード例 #27
0
ファイル: OpenIdChannel.cs プロジェクト: terry2012/DSV
        /// <summary>
        /// Verifies the integrity and applicability of an incoming message.
        /// </summary>
        /// <param name="message">The message just received.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// A task that completes with the asynchronous operation.
        /// </returns>
        /// <exception cref="ProtocolException">Thrown when the message is somehow invalid, except for check_authentication messages.
        /// This can be due to tampering, replay attack or expiration, among other things.</exception>
        protected override async Task ProcessIncomingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken)
        {
            var checkAuthRequest = message as CheckAuthenticationRequest;

            if (checkAuthRequest != null)
            {
                IndirectSignedResponse originalResponse = new IndirectSignedResponse(checkAuthRequest, this);
                try {
                    await base.ProcessIncomingMessageAsync(originalResponse, cancellationToken);

                    checkAuthRequest.IsValid = true;
                } catch (ProtocolException) {
                    checkAuthRequest.IsValid = false;
                }
            }
            else
            {
                await base.ProcessIncomingMessageAsync(message, cancellationToken);
            }

            // Convert an OpenID indirect error message, which we never expect
            // between two good OpenID implementations, into an exception.
            // We don't process DirectErrorResponse because associate negotiations
            // commonly get a derivative of that message type and handle it.
            var errorMessage = message as IndirectErrorResponse;

            if (errorMessage != null)
            {
                string exceptionMessage = string.Format(
                    CultureInfo.CurrentCulture,
                    OpenIdStrings.IndirectErrorFormattedMessage,
                    errorMessage.ErrorMessage,
                    errorMessage.Contact,
                    errorMessage.Reference);
                throw new ProtocolException(exceptionMessage, message);
            }
        }
コード例 #28
0
        /// <summary>
        /// Gets a specific association referenced in a given message's association handle.
        /// </summary>
        /// <param name="signedMessage">The signed message whose association handle should be used to lookup the association to return.</param>
        /// <returns>
        /// The referenced association; or <c>null</c> if such an association cannot be found.
        /// </returns>
        protected override Association GetSpecificAssociation(ITamperResistantOpenIdMessage signedMessage)
        {
            Association association = null;

            if (!string.IsNullOrEmpty(signedMessage.AssociationHandle))
            {
                IndirectSignedResponse indirectSignedMessage = signedMessage as IndirectSignedResponse;

                // Since we have an association handle, we're either signing with a smart association,
                // or verifying a dumb one.
                bool signing = string.IsNullOrEmpty(signedMessage.Signature);
                bool isPrivateAssociation = !signing;
                association = this.opAssociations.Deserialize(signedMessage, isPrivateAssociation, signedMessage.AssociationHandle);
                if (association == null)
                {
                    // There was no valid association with the requested handle.
                    // Let's tell the RP to forget about that association.
                    signedMessage.InvalidateHandle  = signedMessage.AssociationHandle;
                    signedMessage.AssociationHandle = null;
                }
            }

            return(association);
        }
コード例 #29
0
        /// <summary>
        /// Determines whether the relying party sending an authentication request is
        /// vulnerable to replay attacks.
        /// </summary>
        /// <param name="request">The request message from the Relying Party.  Useful, but may be null for conservative estimate results.</param>
        /// <param name="response">The response message to be signed.</param>
        /// <returns>
        ///     <c>true</c> if the relying party is vulnerable; otherwise, <c>false</c>.
        /// </returns>
        private static bool IsRelyingPartyVulnerableToReplays(SignedResponseRequest request, IndirectSignedResponse response)
        {
            Requires.NotNull(response, "response");

            // OpenID 2.0 includes replay protection as part of the protocol.
            if (response.Version.Major >= 2)
            {
                return(false);
            }

            // This library's RP may be on the remote end, and may be using 1.x merely because
            // discovery on the Claimed Identifier suggested this was a 1.x OP.
            // Since this library's RP has a built-in request_nonce parameter for replay
            // protection, we'll allow for that.
            var returnToArgs = HttpUtility.ParseQueryString(response.ReturnTo.Query);

            if (!string.IsNullOrEmpty(returnToArgs[Protocol.ReturnToNonceParameter]))
            {
                return(false);
            }

            // If the OP endpoint _AND_ RP return_to URL uses HTTPS then no one
            // can steal and replay the positive assertion.
            // We can only ascertain this if the request message was handed to us
            // so we know what our own OP endpoint is.  If we don't have a request
            // message, then we'll default to assuming it's insecure.
            if (request != null)
            {
                if (request.Recipient.IsTransportSecure() && response.Recipient.IsTransportSecure())
                {
                    return(false);
                }
            }

            // Nothing left to protect against replays.  RP is vulnerable.
            return(true);
        }
コード例 #30
0
        /// <summary>
        /// Analyzes an incoming request message payload to discover what kind of
        /// message is embedded in it and returns the type, or null if no match is found.
        /// </summary>
        /// <param name="recipient">The intended or actual recipient of the request message.</param>
        /// <param name="fields">The name/value pairs that make up the message payload.</param>
        /// <returns>
        /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can
        /// deserialize to.  Null if the request isn't recognized as a valid protocol message.
        /// </returns>
        public IDirectedProtocolMessage GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary <string, string> fields)
        {
            ErrorUtilities.VerifyArgumentNotNull(recipient, "recipient");
            ErrorUtilities.VerifyArgumentNotNull(fields, "fields");

            RequestBase message = null;

            // Discern the OpenID version of the message.
            Protocol protocol = Protocol.V11;
            string   ns;

            if (fields.TryGetValue(Protocol.V20.openid.ns, out ns))
            {
                ErrorUtilities.VerifyProtocol(string.Equals(ns, Protocol.OpenId2Namespace, StringComparison.Ordinal), MessagingStrings.UnexpectedMessagePartValue, Protocol.V20.openid.ns, ns);
                protocol = Protocol.V20;
            }

            string mode;

            if (fields.TryGetValue(protocol.openid.mode, out mode))
            {
                if (string.Equals(mode, protocol.Args.Mode.associate))
                {
                    if (fields.ContainsKey(protocol.openid.dh_consumer_public))
                    {
                        message = new AssociateDiffieHellmanRequest(protocol.Version, recipient.Location);
                    }
                    else
                    {
                        message = new AssociateUnencryptedRequest(protocol.Version, recipient.Location);
                    }
                }
                else if (string.Equals(mode, protocol.Args.Mode.checkid_setup) ||
                         string.Equals(mode, protocol.Args.Mode.checkid_immediate))
                {
                    AuthenticationRequestMode authMode = string.Equals(mode, protocol.Args.Mode.checkid_immediate) ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup;
                    if (fields.ContainsKey(protocol.openid.identity))
                    {
                        message = new CheckIdRequest(protocol.Version, recipient.Location, authMode);
                    }
                    else
                    {
                        message = new SignedResponseRequest(protocol.Version, recipient.Location, authMode);
                    }
                }
                else if (string.Equals(mode, protocol.Args.Mode.cancel) ||
                         (string.Equals(mode, protocol.Args.Mode.setup_needed) && (protocol.Version.Major >= 2 || fields.ContainsKey(protocol.openid.user_setup_url))))
                {
                    message = new NegativeAssertionResponse(protocol.Version, recipient.Location, mode);
                }
                else if (string.Equals(mode, protocol.Args.Mode.id_res))
                {
                    if (fields.ContainsKey(protocol.openid.identity))
                    {
                        message = new PositiveAssertionResponse(protocol.Version, recipient.Location);
                    }
                    else
                    {
                        message = new IndirectSignedResponse(protocol.Version, recipient.Location);
                    }
                }
                else if (string.Equals(mode, protocol.Args.Mode.check_authentication))
                {
                    message = new CheckAuthenticationRequest(protocol.Version, recipient.Location);
                }
                else if (string.Equals(mode, protocol.Args.Mode.error))
                {
                    message = new IndirectErrorResponse(protocol.Version, recipient.Location);
                }
                else
                {
                    ErrorUtilities.ThrowProtocol(MessagingStrings.UnexpectedMessagePartValue, protocol.openid.mode, mode);
                }
            }

            if (message != null)
            {
                message.SetAsIncoming();
            }

            return(message);
        }