We are building a web service with WCF on .net 4.0. The service will be used mainly by an ASP.net MVC frontend, but will also be used by a .net Windows App.
The basic username/password auth provided won't do since we don't want to save user credentials, so I was thinking about authenticating once and creating a simple token (or should I call it a cookie?) with RNGCryptoServiceProvider.GetBytes() and then using that to authenticate further requests.
I've looked into the various common methods to do security with WCF and they mostly seem overly complex, especially when all we want to do is essentially pass a cookie to every method call.
What would be the best strategy to pass this cookie from a WCF client to our WCF services? The preferred method would be as tightly coupled with WCF's security architecture as possible.
So far I was leaning on either using custom HTTP headers, or custom authorization but I'm not convinced which is the more appropriate method, if any.
Keep in mind that for the ASP website, a new channel would be created for every request, while it would be reused on the Windows app.
IMO there are two ways to do wcf security, Transport or Messsage.
You could implement username type authentication in your application. So the client side would have to fill in a username and password for sending a message.
so the binding on the client side would look like
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
On the server side you could implement your own password validator, as shown in this example
doing this would authenticate your message on the server, you can implement whatever logic you want for your password validation. using this your message would be encrypted using ssl and authenticated using your own logic implemented on the service side.
Related
I have a .NET MVC web application with a custom forms authentication implementation that uses a FormsAuthenticationTicket embedded in an HttpCookie to manage session-based security.
We are expanding the system and the .NET MVC server layer is now going to call a secondary layer of WCF services (using HttpClient to call RESTFul services using JSON payloads). The secondary layer of services will be accessible over the internet and must therefore be secured.
What is the best way (and simplest way) for me to secure the second layer of services so that the first server layer can most easily and securely access them. Could I simply embed the existing HttpCookie containing the FormsAuthenticationTicket in the request to the second server layer?
You can secure the channel with ssl and use server authorisation mechanism for it.
I have a WCF service that needs some authentication functionality
The service is exposed by a SOAP endpoint and a REST one. (i.e. the authentication mechanism should be usable from both types of clients)
I have custom user/password authentication on the back end.
I need the credentials to be passed from the client in plaintext, i.e. unencrypted (service runs in corporate VPN, password is already hashed).
What's the most elegant way to handle this?
Thanks.
For username+password authentication, current recommended way is to use UserNameSecurityTokenHandler:
http://msdn.microsoft.com/en-us/library/system.identitymodel.tokens.usernamesecuritytokenhandler.aspx
You need System.IdentityModel which is newest version, do not mistake it for Microsoft.IdentityModel.
It works great with SOAP when you're able to generate proxy classes on the client side. You simply have to supply credentials to your client proxy class and handle the logic on the server side via the mentioned token handler.
I would strongly suggest this blog to use as a reference, just search for blog comments that contain word WCF. Dominick is one of the top experts in the field.
http://www.leastprivilege.com/
There's a Dynamic CRM instance on a server ("on-premises"). It will be used by a few sites that run on distant machines (another domain, another Active Directory). The communication between those sites and the CRM instance is done via a CRM proxy, a WCF service that sits near it (near CRM), handles requests, queries CRM etc.
That WCF service is facing the Internet. Although secured communication channels aren't that necessary, authentication is. We cannot let random clients to use the services provided by the CRM proxy.
So, Authentication Service (cookies?) / hand-coded token passing (as a parameter for each service operation) / this solution - on stackoverflow.
Thank you in advance!
PS: hand-coded tokens would be "time-sensitive" and hashed a few times with some secret keys. Man-in-the-middle might not be such a big problem, as a token can be invalidated after a request.
Hand-coded token passing is not very elegant. It pollutes your method signatures and makes you duplicates checks all over the place.
If you are able to distribute credentials to your service clients, or pass in credentials that they already use for your system, then I suggest using message security with a custom username & password validator.
The steps to implement it are simple enough. You only need to implement a UserNamePasswordValidator:
A short configuration summary from the linked article:
Specify the security mode in your binding:
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
In your service behavior add:
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="YourFullUserNameValidatorType"/>
</serviceCredentials>
Then clients just need to set their credentials directly on the service proxies. So they're not passed in service operations.
serviceClient.ClientCredentials.UserName.UserName = "username";
serviceClient.ClientCredentials.UserName.Password = "password";
Your UserNamePasswordValidator will get these credential for each service operation call and you will have the chance to validate them against your credentials store.
However, for more security, you could look into certificate authentication. It's more reliable and you are not required to buy a cert from a CA. If you can also setup yourself as a CA on the client computers, then your good to go. It's appropriate especially because you only have a few clients, so they would be easy to manage.
For the question above the preivous answer is good enough. However, I want to suggest another approach: Custom Token Authentication.
It is more poweful by giving a possibility to create/support Custom Service Credentials which are created based on the authentification token (UserName).
In my case I have encrypted access token which holds all needed information for the access: user name, user groups (authorization information), validation period, ect.
In your case it can be UserName & Password. The Credential will hold the information about your user and can be used later on in the code.
See the following link for implementing Custom Token Authentication:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/token-authenticator
I'm currently developing a web api, with WCF web api, which allows me to write restful apis. One concern I have is security. For this reason I decided to protect my api with the OAuth protocol which works very good. However, the team got to the conclusion that our own applications shouldn't be authorized by oauth, instead they sould be authorized by http basic, meaning that the client application should send username and password.
So I have 2 questions:
How can I set up WCF Web Api to work with SSL, I'm using Web Api preview 6, and the project is a MVC3 application?
I have an operation handler which takes care of the creation of IPrincipal from the client access token, and then injects it into the operation parameters, so I can access the user's info. I would like to have in the same operation handler a condition where I could check if the authorization scheme is OAuth or http basic, and then in the case of http basic extract the user's credentials and authenticate that specific user against my data base, if authentication is successful create an IPrincipal and inject it to the operation parameters. However, as I see it, everytime an application using http basic requests something to the api, I would have to go to the data base and authenticate. So my question is: Am I in the right path, or this could be accomplished in some other way?
Any answers would be appreciate it. Thank you in advanced!
You setup SSL for WCF Web API just like you would any other WCF service exposed over HTTPS. If you are hosted in IIS, then you need to configure a site binding for HTTPS. If you are self hosted, then the configuration is bit more involved. See http://msdn.microsoft.com/en-us/library/ms733768.aspx for all of the details.
To handle basic auth against a custom identity provider you would typically use a custom authz module when hosted in IIS. See [http://custombasicauth.codeplex.com/] for an example of how to do this. If you are self hosted then you can use a custom username passworld validator. See http://msdn.microsoft.com/en-us/library/aa702565.aspx for details.
Yes, I believe you are correct that every request will require authentication unless you establish some sort of session-like semantics.
Hope this helps.
I am building a wcf service that needs to be secured as information that the client inter-exchanges with the service is sensitive to the company. I am planning to have it hosted on iis6. What would be the best practice to make sure that nobody but the client application can call the service to get/set data?
The service calls need to happen under the user's real identity as all the calls have to be monitored and audited. I am planning to use PolicyInjection for audit calls.
It all depends.
But basically there are two main approaches:
Transport security with SSL with basicHttpBinding
SSL security with wsHttpBinding
If you provide more information, I should be able to help you more.
There are certain aspects of security:
1) Data integrity: no-one has tampered with data but the data itself are not secret. This is achieved by signing.
2) Data security: This is so that no one could see sensitive/secret information. This is by encryption.
3) Authentication: this is by sending username/password or using certificates. This makes sure the person is the same who is claiming.
4) Authorization: This is to make sure the person has access to the specific features in the service.