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.
Related
I'm currently working on a backend infrastructure and I could need some advice.
First, here is the current global architecture:
I have WCF services hosted in IIS
I have multiples databases hosted on SQL Server. One ClientData database per client and one global MasterDatabase.
MasterDatabase contains a mapping of credentials associated to a connection string. That database allows me to use the appropriate ClientData database (via Entity Framework) depending on the credentials provided.
I'm using Basic Auth over SSL.
Credentials verification are done in overridden method checkAccessCore() in my ServiceAuthorizationManager subclass. Inside that method, I fetch MasterDatabase, ensure credentials are correct (password are saved in DB using Bcrypt) and retrieve the connection string.
Once the connection string is retrieved, I create an instance of my class CustomIdentity that inherits from GenericIdentity. Using that instance I can then set the Thread.CurrentPrincipal property.
Each WCF service implementation retrieves the connection string from the CustomPrincipal in order to fetch data from the appropriate ClientData database.
My questions/thoughts are the following:
If I decide to use concurrency in my WCF services, how will I handle that due to the fact that CheckAccessCore is a method of a WCF extension that force concurrent operations to run sequentially?
http://support.microsoft.com/kb/KbView/2907010
This means that all my call will be enqueued and blocked at the checkAccessCore level.
Overriding checkAccessCore is the best way I found to intercept calls early in the call stack in order to verify user credentials.
Should I use a different way to transport the client connection string other than over the custom identity? Is it secure?
If I use concurrency, I guess the identity set into the CustomPrincipal will be overridden. If yes, how to handle that?
i am new in wcf so one question bugging me like wcf and user authentication. generally in asp.net i send user name and password and at the server end it is validated against database and if user is valid then i store some data in session and in every page i check the session and if the session exist and true is stored for that user in that session then i let the page execute otherwise i redirect user to login page. so i want to know how to implement this kind of user authentication in wcf. i want when first time user will call any method of my service then he will pass credential and if credential is fine then he can call any method of my service. please guide me how could i do it in wcf. in wcf how i can store any data in session for each user who will call my service....is there any way??
i search google and found one like http://blog.adnanmasood.com/2010/04/29/step-by-step-guide-for-authenticating-wcf-service-with-username-and-password-over-ssl/
but here anyone notice caller pass user name & password but code look like user name and password comes twice like
private static void Main(string[] args)
{
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(
delegate { return true; });
var client = new WcfServiceClient();
GetCredentials();
client.ClientCredentials.UserName.UserName = username;
client.ClientCredentials.UserName.Password = password;
Console.Write(client.GetData(1));
client.Close();
Console.Read();
}
...but why two user name and password is coming UserName.UserName it looks very ugly.
give me the best idea how to authenticate users against DB when they first time call my service and once authenticated then from the next time he can call any method of my service without giving credentials.
some one told me to develop service for authenticate user.once user authenticate then service will provide some unique token id to each wcf client and client will pass that token as message header when call any method......i have no idea how to implement it and even i do not know would it be best or not. so looking for guidance and suggestion. thanks
The most common way of dealing with WCF authentication is to have the client program ask for username and password once (or retrieve it from a config file), and have the client program provide it for every service call. Some examples can be found at http://msdn.microsoft.com/en-us/library/ff405740.aspx.
The alternative is to have user sessions, which are generally a bad idea. Sessions do not scale easily, there are client and server platform compatibility considerations etc...
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
I have a WCF service which uses a custom authentication and authorization manager.
Each time a client makes a call the authentication manager looks for a message header and uses the information to identify the user. The user gets created as an IPrincipal and placed into ServiceSecurityContext.Current.AuthorizationContext.Properties["Principal"].
I noticed on subsequent calls, where the users is different, the old user info is in the Current context. My service is tagged as PerCall. I am stumped on why the context is not getting cleared for every call.
Or is OperationContext different lifetime from SecurityContext?
If so any ideas on how to achieve what I described above? Thanks for help.
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.