WCF Service Error: At least one security token in the message could not be validated

Hello,

I have a webservice that I,m trying to apply a custome security, when I try to call the service it display the following error:


http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:FailedAuthentication

At least one security token in the message could not be validated.


To add the security I modify the service config file:

[b][b]<services> <service name = "WcfService1.Service1"> <endpoint address="" binding="customBinding" bindingConfiguration="customBindingOasis" contract="WcfService1.IService1"> <headers> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <wsse:UsernameToken> <wsse:Username>USERNAME</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">PASSWORD</wsse:Password> </wsse:UsernameToken> </wsse:Security> </headers> </endpoint> </service> </services> <bindings> <customBinding> <binding name ="customBindingOasis"> <security authenticationMode="UserNameOverTransport" includeTimestamp="false" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"> <secureConversationBootstrap /> </security> <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16" messageVersion="Soap12" writeEncoding="utf-8"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> </textMessageEncoding> <httpsTransport manualAddressing="false" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous" realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false" useDefaultWebProxy="true" requireClientCertificate="false" /> </binding> </customBinding> </bindings> <protocolMapping> <remove scheme ="https"/> <add binding="customBinding" scheme ="https"/> </protocolMapping> [/b][/b]

I suppose that the error is because I,m not sending back and Answer telling that the token is good.

The question is: How I can get the send token in the request and validate it in my service and return it like good or bad? not the function to validate the token, only how to make a get of the token in my code and send the response back.
Jose CollazoAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Dan McFaddenSystems EngineerCommented:
Didn't you ask a similar question about this topic?

Q:  https://www.experts-exchange.com/questions/29073350/C-2015-web-service-oasis-usernametoken.html

I believe the links there cover implementing OASIS Auth in a WCF Service.

Dan
0
Jose CollazoAuthor Commented:
Thanks Dan,


I,m really new to this security options in c# and wcf, What I dont undestarnd is how I can capture the values submited in the soap header and respond with a valid or false answer.

I will be receiving the following header in the request.

<soapenv:Header>
<wsse:Securityxmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"soapenv:mustUnderstand="true">
<wsse:UsernameTokenxmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"wsu:Id="UsernameToken-21621664">
<wsse:Username>bob</wsse:Username>
<wsse:PasswordType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bobPW</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>

How I can get the username and passwordtext that are in the header and pass them to my code  and how I can return a faild when there are not correct?

I know how to validate if the token is good, but need to get the values to my function.

Do you have any generic code that I can use as an example?

Thanks for the help.
0
Dan McFaddenSystems EngineerCommented:
This article presents basic code for using credentials passed to a WCF web service.

Link:  https://www.rhyous.com/2015/02/05/basic-token-service-for-wcf-services-part-1/

Also, the link I postedx to Rick Stahl's Web Log also makes reference to using the submitted credentials.

Something similar to:

var client = new RealTimeOnlineClient();

client.ClientCredentials.UserName.UserName = "TheUsername";
client.ClientCredentials.UserName.Password = "ThePassword";

Open in new window


Dan
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Jose CollazoAuthor Commented:
Hello,

I was able to validate the user credential.

Here are what i did.

1. Create a custom binding in the web.config:

<customBinding>
        <binding name="mycustomBinding" closeTimeout="00:02:00" openTimeout="00:02:00"
          receiveTimeout="00:10:00" sendTimeout="00:02:00">
          <security authenticationMode="UserNameOverTransport" includeTimestamp="false"
            messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
            <secureConversationBootstrap />
          </security>
          <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
            messageVersion="Soap12" writeEncoding="utf-8">
            <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          </textMessageEncoding>
          <httpsTransport manualAddressing="false" maxBufferPoolSize="524288"
            maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous"
            bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
            keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous"
            realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
            useDefaultWebProxy="true" requireClientCertificate="false" />
        </binding>
      </customBinding>

Open in new window


The security authenticationMode have to be set to "UserNameOverTransport" and the  messageSecurityVersion have to be set to "WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"

2. Create a Service Authenticator class. The following is a basic example that should not be used in producction, create your own class.

public class ServiceAuthenticator:UserNamePasswordValidator

    {


        public override void Validate(string Username, string Password)
        {
            if (null == Username || null == Password)
            {
                throw new ArgumentNullException();
            }

            if (!(Username == "test" && Password == "test"))
            {
                throw new SecurityTokenException("Unknown Username or Password");
            }

        }

Open in new window


3. Add a service behavior to the web.config

<behaviors>
      <serviceBehaviors>
        <behavior name ="myBehavior">
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
            <serviceCredentials >
              <userNameAuthentication  userNamePasswordValidationMode ="Custom"  
              customUserNamePasswordValidatorType="MyService.Common.ServiceAuthenticator, MyService"></userNameAuthentication>
          </serviceCredentials> 
      </behavior>
      </serviceBehaviors>
  </behaviors>

Open in new window

4. Configure your service in the Web.config

<service name="MyService" behaviorConfiguration ="MyBehavior">
      <endpoint address="" binding="customBinding" bindingConfiguration="MyBinding"
      contract="YOUR SERVICE CONTRACT">

Open in new window


With that set a user "test" with the password "test" should be able to call the service. Using Passwordtext, if your using passwordtext use a ssl certificate.
0
Dan McFaddenSystems EngineerCommented:
So I guess the links posted helped?

Glad you got it working.

Dan
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
WCF

From novice to tech pro — start learning today.