Sorry for the long title.
This one is about WCF configuration and security. I have the following scenario:
- one server (IIS)
- N clients (WPF applications)
- web services to communicate between clients and the server
- everything is in the same LAN and the same domain
- I need some duplex communication so the server can notifies all clients (no polling, but usage of WCF callbacks)
- user credentials (login/password) are managed by an active directory
- user authentication is "per-user", not "per-Windows account" nor "per-machine"
Ideally, I would like to have 2 different services:
One that requires a WCF session so I can use callbacks:
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IService1Callback))]
public interface IService1
{
[OperationContract(IsOneWay = false, IsInitiating = true)]
void Subscribe();
[OperationContract(IsOneWay = false, IsTerminating = true)]
void Unsubscribe();
}
One that doesn't, so I can use the good old way to write stateless, efficient and maintainable services: each WCF call is authenticated, authorized, and produces on server side a new fresh instance of the Service implementation:
[ServiceContract]
public interface IService2
{
[OperationContract]
int DoSomeStuff();
}
The thing is, we want every client to authenticate against an active directory. So on client application startup, every client must specify login, password and domain. Problem is AD authentication is quite time-consuming:
using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "theDomain"))
{
if (!pc.ValidateCredentials("theUser", "thePassword"))
{
throw new SecurityException();
}
}
My first idea was to use the IService1
service (that is responsible of sending callbacks) as the authentication service:
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IService1Callback))]
public interface IService1
{
[OperationContract(IsOneWay = false, IsInitiating = true)]
void Login(string login, string password, string domain);
[OperationContract(IsOneWay = false, IsTerminating = true)]
void Logout();
}
So inside the Login
operation implementation, we could check the user login/password against the AD only once, and rely on the WCF session for the next WCF requests from the client. Problem is, I don't want to make other requests against IService1
service because of session mode that is Required
, and InstanceContextMode
that is PerSession
(yes, the ugly client-proxy singleton pattern I want to avoid for other operations than just login/logout/client notifications).
So the question is: how could I build and configure my services, so:
- I don't need to request against AD on each WCF request
- I have some server callback
- I only have singleton pattern/session required/instance context per session, for the callback service (not the "actual"
IService2
service)
I was thinking of wsHttpBinding
for IService2
and netTcpBinding
for IService1
.
Concerning the choice of transfer security (transport or message) and the choice of credential type (Windows, UserName,.. ?) I'm not sure.
Any help would be greatly appreciated.