I created a custom Membership Provider which is now working in production just fine validating my WCF calls.
I do have an issue every now and then that for some unknown reason my provider cannot validate the user. In those cases I do not want the ValidateUser function to just return false, so I thought of throwing and excception with a little more help (not too much, just a little).
My problem is, even though I am throwing a ProviderException the client always gets a MessageSecurityException with no helpful info... just the good old:
"An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail."
with "An error occurred when verifying security for the message." in the Inner.
How can I get the message I am throwing in my own ValidateUser method? what about a custom behavior?
Thanks in advance
I found this post that led me to a solution, I'm not sure if it is the right move
Properly catch SecurityTokenException from a WCF UserNamePasswordValidator
Basically I have to throw a FaultException which I'm not really happy abou because my Membership Provider implementation is WCF agnostic (or at least was until now) now it knows about FaultExceptions :(
Is there a better solution out there?
Related
My experience with WCF is minimal so I'm sure I'm doing something wrong. But after hours of research I'm either not asking the right questions or I'm just old fashion stuck.
I have a windows form application (VB) with a service reference to a WCF WSDL that according to the WCF test application uses transportWithMessageCredential security.
When I attempt to connect to it I get badusernameOrPass every time. I've verified the credentials with the service operator so it's unlikely they are wrong.
Dim serviceProxy As New Provider.SubmissionServiceClient
serviceProxy.ClientCredentials.UserName.UserName = "user"
serviceProxy.ClientCredentials.UserName.Password = "pass"
Dim rtn2 = serviceProxy.ProcessSubmissionFromString(mystring)
Yields error:
System.ServiceModel.Security.MessageSecurityException
HResult=0x80131501
Message=An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.
...
Inner Exception 1:
FaultException: There was a problem authenticating your username or password. BadUserNameOrPassword**
Does this methodology not work with that type of security or am I just missing an element or way off base?
Any help or insight would be appericated.
Credentials were incorrect. After quite a bit of back and forth they provided a fully qualified username that worked right away. The shortened version (without the domain) would work on their other systems but apparently their custom validator for this WCF services needed the longer username.
Had I been more confident in my WCF and skills in general I could have saved myself several hours of work and worry on deadline project.
We have an WCF service, using webhttp binding. Users get authenticated, and then a method is called. In the method, we check a variety of settings associated with the user and some information specific to the request before knowing if the user is authorized to make the call.
Since this is WCF, I think I should be throwing a FaultException of some sort, but it's not clear if there is best practices.
My thoughts are that once I know what exception I will be throwing, I'd add a IErrorHandler which would set the headers correctly to 403.
Two questions:
1) Is there a standard FaultException for unauthorized requests? i.e. the equivalent of the http status code of 403?
2) Should I be able to handle the exceptions that I'll be throwing and change the response code to 403? Will I be able to pass through a custom error message? I've seen some posts that setting headers using the operation context in a catch does not get propagated to the client.
Ideally I'd be able to set the status to 403 with additional information like "You must be part of the administrators group to add a user"
Because you're using webhttp binding, traditional WCF fault management is not pertinent here and it's better to use WebFaultException and WebFaultException<>.
Public string MyOperation()
// Operation logic
// ...
throw new WebFaultException<string>("You must be part of the administrators group to add a user", HttpStatusCode.Forbidden);
}
As you think, it's very important to use standard HTTP status codes when developping an HTTP (REST-like) service.
It's been my experience that throwing fault exceptions, at least with wshttpbinding and basichttpbinding, can cause your web service to fail, so I don't recommend that approach.
If you want to send a message back to unauthorized users, just send an HTML response, setting the status to any one of the 400 responses that seem appropriate.
But from experience, fault exceptions, even if they're a controlled response to user actions and not from an actual processing error, will cause your web service to fail. I think they should be reserved genuine processing exceptions.
I went ahead and derived custom exceptions from FaultException, and then added an IErrorHandler to set the appropriate headers.
This seemed to be the best of both worlds. The code only throws exceptions derived from ones used in WCF, and all the handling specific to http binding is done via an IErrorHandler outside the business logic.
Strangely I can't find anything on google for this. When doing regular exception stuff you'd create a MyCustomException : Exception and I assumed the same applied to ExceptionFaults.
When someone calls my service with an invalid api key, I wanted to throw an InvalidApiKeyExceptionFault. I can't seem to find an example online of how to set this up and have the client be able to catch it (presumably an attribute somewhere to include it into the WSDL).
Any suggestions where to look, or am I trying something that's not possible?
You should use FaultException<TDetail> and put your specific information in the serializable TDetail type.
Your service contract should have a fault contract specifying the TDetail type.
This technique enables you to communicate error information in an interoperable way, including to clients that know nothing about .NET exceptions.
If for some reason you don't want to use fault contracts, you could consider using the non-generic FaultException, and communicate additional information about the error in the fault reason and/or fault code / subcode.
I have a WCF service configured to use custom UserName validation via the overridden Validate() method of the System. IdentityModel.Selectors. UserNamePasswordValidator class.
When the validation fails, I throw a SecurityTokenValidationException.
The way it was built, in my client, I'm receiving a CommuinicationException with the message: The remote server returned an error: NotFound.
What's the best way to handle this exception in the client side?
My validation code:
if (user == null || (Environment.TickCount - user.LastCall) > 300000)
{
if (!LoginUser.ValidateUser(userName, password))
{
throw new SecurityTokenValidationException("Usuário/Senha inválido");
}
}
Throwing an exception from a service will (I believe) fault the channel, and the client will receive a a non-descriptive message. This is by design - WCF "hides" exceptions on the service side.
To return an error to the client so the client can handle it you should use a FaultException. You can specify a FaultContract for the operation and that will be returned to the client.
Do a search on error handling in WCF and you should get plenty of examples. I'm short on time or I'd add some, but hopefully this will get you pointed in the right direction.
Edited to add
Change the line
throw new SecurityTokenValidationException("Usuário/Senha inválido");
to
throw new FaultException("Usuário/Senha inválido");
Throwing the FaultException will prevent the communication from being faulted - the client can then receive the exception, know it was due to validation failure, and decide what to do from that point (retry, prompt the user to reenter credentials, etc).
This is a very simple change and the example is to illustrate the point. The links I posted below will give more detailed information.
How are you identifying the user object that you check the last call on? Are you using a LINQ Single call? if so this will throw an exception if the user is not found and so the server will abort authentication at that point rather than with the SecurityTokenValidationException which I think would give you the behavior you are seeing
I am having a wcf method which has got isoneway attribute set to true.Now when i call this service from client ,service is throwing an invalid operation exception back to the client bcos of some business scenario going wrong.My understanding was that it will throw only endpointnotfound exception and timeoutexception.Can someone please explain why thats happening ?
Marking your contract as One-Way means exactly that: messages flow in one way only. Clients won't get an answer or wait for the service to execute at all, so there's no way that your client could possibly get a reply or fault from the service most of the time.
If you want that, then maybe a One-Way service isn't for you and what you really want is a two-way service with an empty reply (i.e. void)
Does the OneWay method return a value or has ref/out parameter? If yes, then that's the reason you are getting InvalidOperationException. This is expected behavior as per MSDN help for OperationContractAttribute.IsOneWay Property (http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.isoneway(v=vs.110).aspx).
Look for remarks section, it has following text:
One-way methods must not return a value or have ref or out parameters; otherwise a System.InvalidOperationException exception is thrown.
PS: I know it's too late to reply to the thread, but for someone like me who stumbles across the post after 3 years or so, it might be useful.