Reputation: 123
I have a custom user validator implementing UserNamePasswordValidator. This validator is calling another authentication web service using WCF to validate the user.
It works fine, but I'd like to throw a custom message to the final client in case the authentication service call (on middle server side) fails for some reason (FaultException, CommunicationException, TimeoutException or any other Exception).
All I am getting on the client is always the same message popup telling that authentication Basic failed.
How can I throw a custom message back to the client (as a FaultException or any other way) ?
class CustomUserNameValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
try {
string domain="";
string userNameOnly;
//Parse userName to extract domain and userNameOnly
if(userName.Contains('\\')) {
String[] splitted = userName.Split('\\');
domain = splitted[0];
userNameOnly = splitted[1];
}
else {
userNameOnly = userName;
}
//throw new FaultException("Test fault exception from CustomUserNameValidator");
//Get the authentication service
ServiceReference1.AuthWSClient service = new ServiceReference1.AuthWSClient("AuthWSPort");
//Call the athentication service
ServiceReference1.user user = service.connect(domain, userNameOnly, password);
//TODO: Catch exceptions (invalid user throws one)
//throw new SecurityTokenValidationException("Authentication failed for \"" + userName + "\"");
}
catch (FaultException ex)
{
//throw new FaultException("Authentication service (called from ATLAS server) returned an error: \n\n" + ex.Message);
throw new SecurityTokenValidationException("Authentication service (called from ATLAS server) returned an error: \n\n" + ex.Message);
}
catch (CommunicationException ex)
{
//throw new FaultException("Communication issue with authentication service (called from ATLAS server): \n\n" + ex.Message);
throw new SecurityTokenValidationException("Communication issue with authentication service (called from ATLAS server): \n\n" + ex.Message);
}
catch (TimeoutException ex)
{
//throw new FaultException("Connection with authentication service (called from ATLAS server) has timed out: \n\n" + ex.Message);
throw new SecurityTokenValidationException("Connection with authentication service (called from ATLAS server) has timed out: \n\n" + ex.Message);
}
//catch (Exception ex)
//{
// //Unexpected exception
// log.LogError(ex.ToString());
// throw;
//}
}
}
The client has similar try/catch block, but looks like it is not used for UserNamePasswordValidator: there seems to be a specific WCF internal catch for errors from UserNamePasswordValidator.
Upvotes: 1
Views: 1051
Reputation: 469
When throwing an exception from the Validate
method of a UserNamePasswordValidator
, the exception is wrapped as the InnerException
of a MessageSecurityException
(from System.ServiceModel.Security
package), which is the type you have to catch client-side:
try
{ ... }
catch (MessageSecurityException e)
{
Exception exc = e.InnerException;
// Process "exc" here, depending of its type
}
I hope it will help.
Upvotes: 1