Exemple #1
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.associate))
                {
                    if (fields.ContainsKey(protocol.openid.dh_consumer_public))
                    {
                        message = new AssociateDiffieHellmanProviderRequest(protocol.Version, recipient.Location);
                    }
                    else
                    {
                        message = new AssociateUnencryptedProviderRequest(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
                    {
                        ErrorUtilities.VerifyProtocol(!fields.ContainsKey(protocol.openid.claimed_id), OpenIdStrings.IdentityAndClaimedIdentifierMustBeBothPresentOrAbsent);
                        message = new SignedResponseRequest(protocol.Version, recipient.Location, authMode);
                    }
                }
                else if (string.Equals(mode, protocol.Args.Mode.check_authentication))
                {
                    message = new CheckAuthenticationRequest(protocol.Version, recipient.Location);
                }
                else
                {
                    ErrorUtilities.ThrowProtocol(MessagingStrings.UnexpectedMessagePartValue, protocol.openid.mode, mode);
                }
            }

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

            return(message);
        }
        /// <summary>
        /// Verifies the signature by unrecognized handle.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="signedMessage">The signed message.</param>
        /// <param name="protectionsApplied">The protections applied.</param>
        /// <returns>
        /// The applied protections.
        /// </returns>
        protected override MessageProtections VerifySignatureByUnrecognizedHandle(IProtocolMessage message, ITamperResistantOpenIdMessage signedMessage, MessageProtections protectionsApplied)
        {
            // We did not recognize the association the provider used to sign the message.
            // Ask the provider to check the signature then.
            var indirectSignedResponse = (IndirectSignedResponse)signedMessage;
            var checkSignatureRequest  = new CheckAuthenticationRequest(indirectSignedResponse, this.Channel);
            var checkSignatureResponse = this.Channel.Request <CheckAuthenticationResponse>(checkSignatureRequest);

            if (!checkSignatureResponse.IsValid)
            {
                Logger.Bindings.Error("Provider reports signature verification failed.");
                throw new InvalidSignatureException(message);
            }

            // If the OP confirms that a handle should be invalidated as well, do that.
            if (!string.IsNullOrEmpty(checkSignatureResponse.InvalidateHandle))
            {
                if (this.rpAssociations != null)
                {
                    this.rpAssociations.RemoveAssociation(indirectSignedResponse.ProviderEndpoint, checkSignatureResponse.InvalidateHandle);
                }
            }

            // When we're in dumb mode we can't provide our own replay protection,
            // but for OpenID 2.0 Providers we can rely on them providing it as part
            // of signature verification.
            if (message.Version.Major >= 2)
            {
                protectionsApplied |= MessageProtections.ReplayProtection;
            }

            return(protectionsApplied);
        }
Exemple #3
0
        public void IsValid()
        {
            Protocol protocol   = Protocol.Default;
            var      request    = new CheckAuthenticationRequest(protocol.Version, OPUri);
            var      response   = new CheckAuthenticationResponse(protocol.Version, request);
            var      dictionary = this.MessageDescriptions.GetAccessor(response);

            Assert.AreEqual("false", dictionary["is_valid"]);
            response.IsValid = true;
            Assert.AreEqual("true", dictionary["is_valid"]);
        }
        /// <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>
        public bool PrepareMessageForReceiving(IProtocolMessage message)
        {
            var signedMessage = message as ITamperResistantOpenIdMessage;

            if (signedMessage != null)
            {
                Logger.DebugFormat("Verifying incoming {0} message signature of: {1}", message.GetType().Name, signedMessage.Signature);

                EnsureParametersRequiringSignatureAreSigned(signedMessage);

                Association association = this.GetSpecificAssociation(signedMessage);
                if (association != null)
                {
                    string signature = GetSignature(signedMessage, association);
                    if (!string.Equals(signedMessage.Signature, signature, StringComparison.Ordinal))
                    {
                        Logger.Error("Signature verification failed.");
                        throw new InvalidSignatureException(message);
                    }
                }
                else
                {
                    ErrorUtilities.VerifyInternal(this.Channel != null, "Cannot verify private association signature because we don't have a channel.");

                    // We did not recognize the association the provider used to sign the message.
                    // Ask the provider to check the signature then.
                    var indirectSignedResponse = (IndirectSignedResponse)signedMessage;
                    var checkSignatureRequest  = new CheckAuthenticationRequest(indirectSignedResponse);
                    var checkSignatureResponse = this.Channel.Request <CheckAuthenticationResponse>(checkSignatureRequest);
                    if (!checkSignatureResponse.IsValid)
                    {
                        Logger.Error("Provider reports signature verification failed.");
                        throw new InvalidSignatureException(message);
                    }

                    // If the OP confirms that a handle should be invalidated as well, do that.
                    if (!string.IsNullOrEmpty(checkSignatureResponse.InvalidateHandle))
                    {
                        if (this.rpAssociations != null)
                        {
                            this.rpAssociations.RemoveAssociation(indirectSignedResponse.ProviderEndpoint, checkSignatureResponse.InvalidateHandle);
                        }
                    }
                }

                return(true);
            }

            return(false);
        }
Exemple #5
0
        public void ExactPositiveAssertionPreservation()
        {
            var rp = CreateRelyingParty(true);

            // Initialize the positive assertion response with some data that is NOT in normalized form.
            var positiveAssertion = new PositiveAssertionResponse(Protocol.Default.Version, RPUri)
            {
                ClaimedIdentifier = "https://HOST:443/a",
                ProviderEndpoint  = new Uri("https://anotherHOST:443/b"),
            };

            var checkAuth = new CheckAuthenticationRequest(positiveAssertion, rp.Channel);
            var actual    = rp.Channel.MessageDescriptions.GetAccessor(checkAuth);

            Assert.AreEqual("https://HOST:443/a", actual["openid.claimed_id"]);
            Assert.AreEqual("https://anotherHOST:443/b", actual["openid.op_endpoint"]);
        }
        /// <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);
        }
        /// <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>
        public MessageProtections?ProcessIncomingMessage(IProtocolMessage message)
        {
            var signedMessage = message as ITamperResistantOpenIdMessage;

            if (signedMessage != null)
            {
                Logger.Bindings.DebugFormat("Verifying incoming {0} message signature of: {1}", message.GetType().Name, signedMessage.Signature);
                MessageProtections protectionsApplied = MessageProtections.TamperProtection;

                this.EnsureParametersRequiringSignatureAreSigned(signedMessage);

                Association association = this.GetSpecificAssociation(signedMessage);
                if (association != null)
                {
                    string signature = this.GetSignature(signedMessage, association);
                    if (!MessagingUtilities.EqualsConstantTime(signedMessage.Signature, signature))
                    {
                        Logger.Bindings.Error("Signature verification failed.");
                        throw new InvalidSignatureException(message);
                    }
                }
                else
                {
                    ErrorUtilities.VerifyInternal(this.Channel != null, "Cannot verify private association signature because we don't have a channel.");

                    // If we're on the Provider, then the RP sent us a check_auth with a signature
                    // we don't have an association for.  (It may have expired, or it may be a faulty RP).
                    if (this.IsOnProvider)
                    {
                        throw new InvalidSignatureException(message);
                    }

                    // We did not recognize the association the provider used to sign the message.
                    // Ask the provider to check the signature then.
                    var indirectSignedResponse = (IndirectSignedResponse)signedMessage;
                    var checkSignatureRequest  = new CheckAuthenticationRequest(indirectSignedResponse, this.Channel);
                    var checkSignatureResponse = this.Channel.Request <CheckAuthenticationResponse>(checkSignatureRequest);
                    if (!checkSignatureResponse.IsValid)
                    {
                        Logger.Bindings.Error("Provider reports signature verification failed.");
                        throw new InvalidSignatureException(message);
                    }

                    // If the OP confirms that a handle should be invalidated as well, do that.
                    if (!string.IsNullOrEmpty(checkSignatureResponse.InvalidateHandle))
                    {
                        if (this.rpAssociations != null)
                        {
                            this.rpAssociations.RemoveAssociation(indirectSignedResponse.ProviderEndpoint, checkSignatureResponse.InvalidateHandle);
                        }
                    }

                    // When we're in dumb mode we can't provide our own replay protection,
                    // but for OpenID 2.0 Providers we can rely on them providing it as part
                    // of signature verification.
                    if (message.Version.Major >= 2)
                    {
                        protectionsApplied |= MessageProtections.ReplayProtection;
                    }
                }

                return(protectionsApplied);
            }

            return(null);
        }