I have two base classes RequestBase and ResponseBase, for request and response respectively. All types of requsets and response derived from these classes. The RequestBase contains ClientKey and AccessToken fields. Also, I have the AuthenticationService service.
[ServiceContract]
public interface IAuthenticationService
{
[OperationContract]
public LoginResponse Login(LoginRequest request);
... other methods
}
Suppose we have the OrderService service.
public class OrderService:IOrderService
{
public OrderResponse GetOrders(OrderRequest request)
{
...
}
}
I need to validate each request for ClientKey and AccessToken, also check whether the user is authenticated. I can do the following:
public OrderResponse GetOrders(OrderRequest request)
{
var response = new OrderResponse(request.RequestId);
// call helper method for validation
var validationResult = ValidateRequest.Validate(request, response, ValidateOptions.All)
...
}
But I don’t want to write this line of code in every method:
var validationResult = Validate.ValidRequest(request, response, ValidateOptions.All)
What is the best way to do this?
PS. This is Validate method:
public static bool Validate(RequestBase request, ResponseBase response, ValidateOptions validate)
{
//Validate Client Key.
// Hardcoded here.
if ((Validate.ClientKey & validate) == Validate.ClientKey)
{
if (request.ClientKey != "ABC123")
{
response.Acknowledge = AcknowledgeType.Failure;
response.Message = "Unknown Client Key";
return false;
}
}
// Validate access token
if ((Validate.AccessToken & validate) == Validate.AccessToken)
{
if (request.AccessToken != _accessToken)
{
response.Acknowledge = AcknowledgeType.Failure;
response.Message = "Invalid or expired AccessToken. Call GetToken()";
return false;
}
}
// Validate user credentials
if ((Validate.UserCredentials & validate) == Validate.UserCredentials)
{
if (_userName == null)
{
response.Acknowledge = AcknowledgeType.Failure;
response.Message = "Please login and provide user credentials before accessing these methods.";
return false;
}
}
return true;
}
One more question: Where is the best place to store _accessToken, _userName on server?
It looks in your case no easy way to achieve what you want. In general you can do some custom things like security validation either on transport level or on WCF level. If your service is hosted in IIS, you can implement custom authentication module, but it’s not your case, since security information is in data contracts. WCF also have several extensibility points, like custom endpoint behaviors, Message Contracts and mentioned by @trydis message inspectors. But they all are not suitable for you out of the box, since it can require taking care on messages serialization and other custom things.
Better is keep doing this in your code, and if you want to optimize your code, take a look at postsharp.