WCF services: passing a token to validate a subscription and get database info - wcf

I'm creating a smart client application using .NET 3.5. A Winforms client connecting through WCF services to retrieve data from SQL Server 2008. I need to pass a username/password (encrypted and over HTTPS) and return information such as:
Is this user (e-mail address) under a current subscription
What server should we go to next for all subsequent calls (poor man's load balancing)
What server/database should be used in the connection string (credentials not required), as people could be using different databases depending on their subscription, etc.
So my first call when signing on sends the credentials which a lookup is performed. A serializable class will be used to create a token object (I assume this is the way to handle this) which will return the expiration, server info, database info.
The question is on all subsequent calls do I pass this token as a parameter to every service contract (web method) or can I leave all my current contracts as is and pass the token in a header or some other more universal method?
How do you suggest implementing a token system such as I describe?
Thank you

For one, I would only return a TokenID - some unique ID to clearly identify the user and his subscription in question - from your first "authentication" call. No need to send back and forth the whole set of information all the time - only the service on the server side needs those details, so you can leave that info on the server and only consult it in your server code when needed.
So that first call - the authentication call - would most likely check the credentials being sent against a database table, against a subscription table, and then put that information (who's calling in, based on what subscription) and possibly some kind of an expiration date/time into a "Valid Callers" table and generate an ID from that (a GUID or something). You might want limit the "lifespan" of a TokenID - e.g. it's valid for 30 minutes or so - so that it can't be hijacked and used perpetually after a first successful call. That generated GUID is then returned as the TokenID from the Authentication call and can be used as an identifier in each subsequent call.
Things like what database server to use have really no place in messages going back and forth - they're strictly important to the server-side service code - just leave it there!
It is definitely preferred practice to put such "meta information" that isn't the real value information for your calls into headers and go search for it there. WCF supports this quite nicely and easily - with either message inspectors (sample for that here and here) on client and service side, or by using the OperationContextScope (sample blog post here and here) - both work just fine.

Related

WCF Authenticate Client with database

I have a WCF service that supposed to provide service to several clients.
The WCF will have a Data-Access-Layer that will communicate with the database.
This is part of my design idea : My Design
As you can see - each client will connect to the 1st WCF service for pulling information (get product, update product), and also to the 2nd WCF service in a pub\sub manner, so it would be able to receive notifications about different things it wants.
I have a table in the database for 'Users' with all the users in the system.
(there is an administrator, a normal user and a technician).
My question is - how do I do the 'logging' in from the client to the database ?
My current idea - have a function in the services called 'Connect ( username, password )' and when a client connects - it will pass the username and password to be authenticated in the database, and only if authenticated - the client will start sending commands.
Problem with this is - anyone can write his own client that connects to my service and runs other functions without authenticating. I can solve this by saving in the service whether or not the client has authenticated.
But is there a better solution that just having a 'Connect' function in the service ?
Hope there is something simple yet effective.
You should create a custom user name and password validator that derives from the UserNamePasswordValidator abstract class and implements the Validate() method. Then you can validate the provided user name and password however you want. To learn more about setting this up, read this article.

WCF and UserName credentials when using basicHttpBinding

As far as I know, in order to use UserName credentials with basicHttpBinding to authenticate against the SQL Server membership provider, I need to set TransportWithMessageCredentials security mode. But recently I had a look at the WCF Security guide. And in this book I found the similar example, but instead of TransportWithMessageCredentials, Basic mode is used and a custom HTTP module is created that will authenticate users.
I'm wondering which approach is worth using?
Both approaches do the same but they use different approach. The first approach uses SOAP header to pass credentials whereas second approach uses HTTP header to pass credentials.
The second approach involves additional network roundtrip (handled internally by WCF) because first call is rejected with 401 status code and demanded Basic authentication and only second call contains the header with credentials. This is the way how HTTP authentication works and client should not send credentials until server requires them (even there is possibility to preauthenticate but I think WCF doesn't use it). The second approach cannot be used with streamed transfer mode.
There can be one additional difference between those two methods. The first approach authenticate each call whereas second approach authenticate connection so if you call the service multiple times from the same proxy (and the same connection) you will be authenticated only once with the second approach but for each call with the first approach.
Edit:
There is no preference between those two. You will use the one which is more suitable for your needs. If you have control over both client and server or if you know that client will use some more powerful SOAP stack the first one is easier to set up. If you don't have control over your clients and they can use different platforms you can find second more interoperable.
As a side note the first one works only with SOAP protocol whereas the second one works for SOAP, POX and REST (POX and REST require different binding).

One way web service still returns a response

I aplogise if my terminology is inaccurate, still deep in learning.
I am creating a web service to act as an intermediary between Silverlight and XMPP. To start all of this I have created a web service call to enable me to ask the server to log on on my behalf and the idea is that the server will log on and then push back to my client once complete.
I have based the idea on the code form this site: http://weblogs.asp.net/dwahlin/archive/2011/02/06/syncing-data-with-a-server-using-silverlight-and-http-polling-duplex.aspx
Now the problem I have is that the Register call I have created will use an asynchronous call to log into XMPP. But the register call itself is also asychronous. So I don't know the best way for a web service call to wait for another service's async call
What I thought of doing was making the Register a one way call with the idea being that my server will log into XMPP then push the client once logged in (or fileld etc)
[OperationContract(IsOneWay = true)]
void Register(string name, string password, string nickname);
But when I imported the Service Reference the class generated appears to have a RegisterCompleted() call which debug shows is invoked. But I thought one-way meant no response is called so why is it?
One Way means No Response Data. Internet protocols are a request-response model where there is an acknowledgement for the receipt of the request. Your Register service returns no data (void) so RegisterCompleted really did "completed accepting three string parameters and returned no data".
This is a good thing - now you know if you had a problem starting the registration or everything is good so business as usual until you hear back from the server. You don't know yet if you're actually registered yet so that's why your client continues to Poll the server until the server responds - good or bad.
His previous article references an good MSDN example on using the PollingDuplexHttpBinding.

Restrict methods of a WCF service from unauthorized (unwanted) user access

I'm wondering how I can restrict some methods from unauthorized user access. Let's assume I have a WCF service with the following contract:
int Login(string username, string password);
Invoice[] GetCustomersInvoices(int customerId);
A user should act in the following way:
Login to verify against the service and get his custumerId
fetch his invoices by invoking the corresponding method with his customerId
Well, that's maybe a stupid question, but what if customerA's id is 23, but somehow customerA knows customerB's id, which is 42. Now customerA could read customerB's secret invoice data...
What could I best do to avoid this?
You shouldn't use a single id for identifying someone. There are many ways of enabling authn/authz in WCF, I like the article at http://msdn.microsoft.com/en-us/magazine/cc948343.aspx for a good introduction on some ways of doing it.
Your current approach of calling methods will only work if you are able to implement secure(persistent) channel between client and server using SSL or any other such mode (typical scenario would be Baking Payments Getaways)
So IMO you need to implement your user authentication inside the method (no separate calls). i.e. you have to pass userid and password along with invoiceid to GetCustomersInvoices() method and inside it you need to authenticate the user and retrieve the data.
Following would be solution for such scenario,
Implement your own User Name Password Validations (custom usernameathentication), which will first authenticate the user and than it will call the method given. Since this will happen in one request so it will solve your problem.
Typical service method call would be like,
Service.UserName = "abc"
Service.Password = "***"
Service.GetInvoiceDetails(1233)
You can get the use of Message Headers and Body to pass your custom values, Webservices support such scenario where you can pass encrypted data in SOAP headers.
Alternatively you can use Certificates also, but these are not free.
In general you can go through following links to get more info in various kinds of security WCF supports,
http://msdn.microsoft.com/en-us/library/ms731925.aspx

How to get information about WCF service client from operation implementation?

I especially need to get client's certificate used to call service's method. This is to react differently for different clients.
In your operation code, you can examine things like:
OperationContext.Current
or
ServiceSecurityContext.Current
but I'm not sure if you can access the actual client certificate from those.
The ServiceSecurityContext.Current.PrimaryIdentity will contain an IIdentity for the current caller - if it's NULL, then you're dealing with an anonymous call. Otherwise, the PrimaryIdentity will be one of several possible identity types, depending on how the calling user was authenticated - it could be a Windows identity, or something else - depending on your scenario.
See this blog post for a few more tidbits of information on X.509 and WCF.