Returning appropriate fault information in a custom UserNamePasswordValidator
I'm looking at the WCF samples for creating a custom UserNamePasswordValidator (WCFSamples\TechnologySamples\Extensibility\Security\UserNamePasswordValidator\CS\service).
The sample's CustomUserNamePasswordValidator implementation demonstrates that if a username/password combination is not valid, to throw a SecurityTokenException.
However, since the exception occurs during the authentication stage of the pipeline, prior to the message being authenticated, the exception thrown by the client is not a SecurityTokenException, but is always a MessageSecurityException that indicates that: {"An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail."} The inner exception does not contain the SecurityTokenException either, but is a FaultException indicates that {"An error occurred when processing the security tokens in the message."}
This makes sense since we're using message-based security -- the service can't authenticate and issue a token, so the client can't authenticate the fault message coming back from the service. (or something like that ;)
So my question is, it appropriate to catch a MessageSecurityException, say, to indicate to the client user that the provided credentials are invalid, and to re-enter their credentials, or is there another way of flowing the SecurityTokenException as thrown in the custom UserNamePasswordValidator, or another fault message (maybe trace diags?) back to the client?
I've got the same issue. I'm inheriting from UserNamePasswordValidator and providing an override of the Validate method for WCF authentication. If the authentication fails, I throw an UnauthorizedAccessException, but receive a MessageSecurityException on the client. Therefore my exception handling on the client cannot determine if the user entered an invalid username/password, or if there was some other problem.
Anyone know of a solution?
I'm working on the same thing, is there a resolution to this? Can we get a custom fault back or are we stuck with the standard MessageSecurityException?
Can anyone from MSFT fill us in on whether this is a bug or part of the design, what's the best practice for calling a service secured with a custom UserNamePasswordValidator then? Should we be catching faults as well as exceptions, faults being for user errors and other errors that may occur within the business tier and regular exceptions basically just for communications issues (in the case we're asking about it blurs the line a little though because in my system for example we have a session that can time out so i need to be able to fail the Validate method of my UserNamePasswordValidator by throwing an exception/fault when the users session times out but i don't consider this to be in the same category as other communications issues - i'd like to know that this particular case happened so i can just ask the user to login again)? Also what other possible exceptions are there? It would be nice to work out what's recoverable and what's not.
Thanks in advance.
Just enough to give an indication as to why the authentication failed -- For instance when logging into passport Windows Live ID, if the U/P combination is not valid, it tells you so. Likewise, if the authentication succeeded, but some other problem prevents a completely successful authentication -- such as your account being locked out -- it also indicates this.
As you indicated, exceptions thrown on the service are transformed into a fault -- however, since the exception occured prior to authentication, when the client recieves the fault, the client can't trust it because it the client wasn't successfully authenticated.
How can we support the scenarios described above and get at the fault info?
I find working with the UserNamePasswordValidator really frustrating for two reasons:
1) As mentioned above one can't control the exception\fault returned to the client.
2) And, this really sucks, please tell me there is a way around this, other that putting context inside a custom token. It appears you have no access to the OperationContext or any other context which contains information like the service and method being called (i.e. the SOAPAction). Our UserNamePasswordValidator will be used for custom Etrust username password authentication on potentially 100s of services in an SOA framework and we need to know what service and method a client was trying to access when authentication fails. This is so we can log enough information to resolve an authentication failure. Was this by design for security reasons?
Is there any other extension point in WCF where I can achieve custom authentication? I thought about doing authentication in a class implementing the ServiceAuthorisationManager or IAuthorisationPolicy interface, where Context is available. However the purpose of these is for authorisation not authentication.
Can someone give me some guidance here?
This same question was asked here:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=653318&SiteID=1
The answers there were about the same as what you see here. As these other folks have stated, it would be handy to either get the type of the actual exception that's thrown at the service side [to be able to present different messages to the user], or even better yet, being able to get all the exception details of what happened at the server side. We have a number of unique things that can happen when the user logs in, beyond simple yes/no, inactive accounts, accounts where passwords need to be changed, etc. It seems like a pretty reasonable request to have some back channel to get fault reason information back to the client, you can do it with pretty much every other type/phase of service operation, why not the authentication piece?