Prevent sharing login credentials between users in WCF - wcf

I have a service hosted in a Worker Role in Azure. Clients connect over NetTcp bindings using certificates for mutual client/service authentication and with a custom username password validation.
Clients also receive event notifications that are broadcast through the Azure service bus using shared secret authentication.
I want this to be secure and not allow one person to share his/her login information with friends or anyone else - their login is for their use only. Similarly, a user that forgets to log off at one machine and then logs in to the service from another machine (i.e. tablet, work computer etc.) should trigger a automatic shutdown of the application that was not logged off from.
I am using a per-call serivce, and to have implement a solution using sessions would require alot of rewiring.
I figure I need to keep track of the users' context when they make a operation call and track which IPs are currently using that login/credential. I would like to be able to have some kind of "death touch" whereby the service can send a kill command to a client when multiple logins are detected.
Any suggestions or pointers to patterns that deal with this issue would be appreciated.
Thanks.

Even if you did go with PerSession you would still need to determine if the same user was in more than one session and you have the overhead of session.
I have only tested this over WSHttpBinding and not hosted in an Azure Role so please don't vote it down if it does not work on NetTcp Azure Role - comment and I will delete it. Even with PerCall the SessionID is durable and SessionID is available on both the client and server. More than one user could have the same IP address but SessionID is unique to the session. Clearly you would need to record the userID, SessionID but table storage is cheap.
Maybe update license model for concurrent usage. By recording userID and sessionID you could write an algorithm to calculate max concurrent usage.

Related

Single Sign on implementation for my sites in same domain

We have a application running already lets say a.example.com, now we are planning to add one more application as b.example.com. We are already storing user session of a.example.com in Azure Redis cache. Is there a simple way to provide SSO between my two sites, by utilizing the existing Redis session store.
Note : please dont suggest using identity framework, as I dont want to have a separate server, to do authentication. Correct me If I was wrong here guys.
Thanks in Advance
Ganesan S
I will first say what could be a solution, then give what my work has done since we have multiple sights that all deal with their own sessions, but are all linked.
When you create a session for a.example.com, could you also create b.example.com as well and have both put in the Redis store? Then when a person signs out you can find the session for both sites based on the user and delete both at once.
Another option could be to have 1 session that both sites look for. That way each user only has 1 session, so there is only 1 to create and 1 to destroy. You could set up the domain to be by example.com unless there are other sites that should not see that domain.
We use a Service Provider that creates a sign in hub that all of our sites point to. Then each site gets its own session that has a domain over everything. Then when someone logs out the server will delete all sessions at once and call logout for the user at the service provider. In your case you could treat the Redis session store as a sort of Service provider storing the sessions for the users that your websites look at for user validation?

SOA Service Design / Authentication

I'm rather new to SOA and therefore experimenting around.
Currently, the part that creates the biggest problem to me is authentication, my current thought about it involves the following:
The client sends some kind of authentication message to the authentication / user service, this service queries the db and if the user is found and the password is valid, it will respond with a session id, this id will be used in all further requests of this client.
This seems rather ok to me but I don't know how I should handle the requests to other services, I thought of three different approaches.
Every service asks the authentication service if the session is valid and if so, what roles the user is in. The authentication service looks in the db and replies accordingly.
The authentication service keeps all session information in ram and responds without the db roundtrip to the requests.
The authentication service sends an authorized message to an esb, the esb forwards this authorized message to every service and these services cache it. No further requests to the authentication service would be necessary. If the user logs out or his roles change, another message would be send around and processed by all services.
I think the first approach creates too much stress on the authentication service / db but takes the least effort to implement.
The second is still very easy to implement but the stress on the authentication service remains almost the same.
The third is a little more complicated to implement but would has reduced response time as no trips to the authentication service take place. Though, if there are too much session information this approach would just fail and scalability is hardly given.
The best approach should be like this if all the services are internal,
The authentication service issues a token the the service client.
Service client includes the token in the SOA message wrapped in WS-Security or something similar.
The service should validate the token with authentication service before providing the service.
For external services, I suggest you look at federated solutions like SAML.
Don't do premature optimization. Your option no. 3 which you acknowledge will be more complicated to implement is unnecessary. Choose option no. 2 if that's what you can implement fast. You can profile later and change it, but I'd bet money that you won't have a 'bottleneck' when going with option 2.

Pattern for WCF Kerberos Clients where Server uses User Account

We have a WCF (Windows Communication Foundation) client and service application. We're using Windows Authentication with Kerberos.
The issue is that the service may be run under one of many accounts (maybe Network Service, maybe a specific user account -- depends on the IT group). This account is not not likely to change daily, but possibly on occassion (every few months maybe). Additionally, we deliver this client/service package to several groups, and each group may have its own account that they use to run the service on (this is to just let you know that we can't do a custom solution for a single team).
Now the reason the above paragraph is an issue is apparently if the service is not running in the SYSTEM or NETWORK SERVICE account, i.e., a user account, then the client must specify the name of the user account in the identity of its endpoint.
For more on this restriction see: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/feb6bc31-9a4b-4f8d-a887-ef6d2c7abe41
and http://www.vistax64.com/indigo/146204-using-localhost-v-s-environment-machinename.html
Now this seemingly makes it tough to deal with the situation where the IT department changes the account that the service runs on. What is the pattern for handling this, if there is one? How have other people handled this? One solution I've thought of is that the admin sends out an email when the user account of the service has changed, which has a weblink to an application that updates the client or a config file, so the client refers to the new user account. But that seems hackish.
Admittedly, this is a lot like the URI of the endpoint moving. Except, I think there's a lot more expectation on behalf of people that changing the URI is something the client should have to know about, but changing the account the service is running on is something that should be relatively transparent to the client.
BTW, this is required to be hosted on IIS 7.0, if that matters.
I think you can set NegotiateServiceCredential property to True so your binding uses SPNego instead of hard-cold Kerberos. When is set to true, the client does not need to specify the SPN and it can connect to a server running a non-machine account.
Note that since the client no longer requests a specific SPN, it can no longer detect if is connected to a hijacked impersonator of the service, but this is usually a minor concern unless you are really paranoid about security.
Also, as a side rant: the fact that WCF requests as SPN the account name is basically a brain fart. It client should use the DsMakeSpn API to compose the SPN from the service name, host and port. The server should register that SPN for itslef at start up or let an administrator do it using setspn.exe. This is the way they do it by all traditional (well behaved) services in the Kerberos/ActiveDirecotry/Windows environment.
Update
On second though I don't see anything specifying that the client must use the account name as SPN. Looks more like a documentation oversight, instead of documenting the proper way they just recommended what is basically a bad practice. Or maybe just the forum advice is bad, since I did not dig to see what does the MSDN binding spec actually says about the SPN to use...
I don't have a WCF environment handy to test with, but perhaps you can configure the clients to requests a proper SPN like YourService/server:port and you also register the same SPN on the server side. Either manually as an exercise left to the admins, or automatically from your service when it starts up, and unregister it at shut down. The proper way to do it is to let the admins do it, but in reality that is such a pain that most services register the SPN themselves and you can probably follow this practice too. To register an SPN, your service calls DsWriteAccountSpn. The write has to propagate to the AD and be replicated between AD servers, and this at least one reason why having the service auto-register/auto-unregister the SPN is a questionable practice.
If you want to learn more about the wonderfool world of SPNs and how they can wreck your day, you can read up on How Service Publication and Service Principal Names Work.
Update
I'm pretty sure you can use any SPN you like. Most exmaples out there use the account name as 'UPN' (User Principal Name) instead of SPN, but that is just for the convenience of samples as using a true SPN would run into administrative issues setting up the SPN under an user account (again, why admins should do it...). From Overriding the Identity of a Service for Authentication, relevant emphasized:
By default, when a service is
configured to use a Windows
credential, an element that
contains a <userPrincipalName> or
<servicePrincipalName> element is
generated in the WSDL. If the service
is running under the LocalSystem,
LocalService, or NetworkService
account, a service principal name
(SPN) is generated by default in the
form of host/<hostname> because those
accounts have access to the computer's
SPN data. If the service is running
under a different account, Windows
Communication Foundation (WCF)
generates a UPN in the form of
<username>#<domainName>. This occurs
because Kerberos authentication
requires that a UPN or SPN be supplied
to the client to authenticate the
service.
You can also use the Setspn.exe tool
to register an additional SPN with a
service's account in a domain. You can
then use the SPN as the identity of
the service. To download the tool, see
Windows 2000 Resource Kit Tool :
Setspn.exe. For more information about
the tool, see Setspn Overview.
Set NegotiateServiceCredential and EstablishSecurityContext properties to False.

wcf operationContext

hello i have a desktop application that communicate with a wcf service that i building as well
i want to be able to manage the logged on users inside the server without a db (statefull server)
i also want the server to know how to handle 2 client from same computer, whats the simplest way of doing it?
i also have more than 1 service that the client work with (login service and app service)
is there any operationContext Property that can help me?
You can deffinetly manage the logged users inside the server. I have created a personal pattern for dealing with such situations, and it ussually goes like this:
create a client class inside the WCF server that will hold all the needed information about the client.
create 2 methods in the service: logIn, logOut. the login method should be able to gather all the informations about the client that you want to store. Make sure to define properties that can uniquely identify a client instance. When the client conencts to the server it calls the login method, allowing the server to gather and save the information from the client. If using callbacks, this is the place to save the CallBack context object, in the client obejt. You can now save the Client object in the WCF server instance (I use a dictioary). When the client logs out, it calls the log out method and the server removes the entry.
create a KeepAlive method in the server that regularry checks the connected clients to see if they are still connected (in case of network failure or app crash a client may not call the logout method).
I think this is the simplest way (not saying it's the best) to manage clients in the server.
There is no problem with having multiple clients from the same computer (you save the Context when a client logges in) as long as you have a way of uniquely identify clients.
As for your last question, having multiple services should not be a problem. In fact you have the same WCF server with different contracts (and endpoints) for the different services you offer. ALl the contracts reside in the same WCF server instance so they all can access the connected client list.
If you have further questions, I would be happy to answer them.

WCF sessions or pass username/password per call?

For an enterprise type WCF service, where potentially 10K's of thousands of clients will be authenticating and sending data to central servers, what is 'best' practice when it comes to sessions or authentication?
does WCF support a session, if yes, should I use it?
or should I simply pass username/password on a per call basis?
As blowdart mentioned, WCF Sessions are not the same as ASP.NET Sessions. You can read up on them here: http://msdn.microsoft.com/en-us/library/ms733040.aspx. Before you roll your own security, you'll want to get familiar with what WCF gives you out-of-the-box: http://msdn.microsoft.com/en-us/library/ms734736.aspx. They may get you close to your goal without writing a lot of code. Specifically, check out How to: Create a Secure Session. With secure sessions, the Client and Server cache credentials so you don't have to fully authenticate with each request. By default, you'll lose a secure session if the web server recycles. If you want a secure session that lasts through a recycle, you'll want to look at How to: Create a Stateful Security Context Token for a Secure Session.
WCF does support sessions yes; but they are not like ASP.NET sessions. Sessions are there to deliver messages in order (and other bits and bobs), they are not there to add shared storage between calls.
For authenticated service calls you should send your authentication details every time; security is applied on a per message basis.
If you host the service within IIS, you can still use the session that is from ASP.NET
by enabling aspnetcompatibility for the service behaviour.