How to put a password on a WCF Service? - c#

I'm working on a WCF Service that is called by our other softwars to send bug information to our database. The problem is that, since it is an online service, it isn't safe, so I was wondering if it's possible to the service to request a password (i.e. when we call the service, we have to configure the password or something like that).
I googled about it, but it all seemed so complex for such a simple thing ... can you guys help me out?
Edit:
The idea is to authenticate through my software, without the need of a user login.

Another option is to implement your own security. Here's a basic example.
WCF Service
In your service, change it's ServiceBehavior's InstanceContextMode to PerSession and ConcurrencyMode to Single
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
public class SomeService : ISomeService
{
// ...
}
Add a Username and Password property in your service.
public string UserName { [OperationContract] get; [OperationContract] set; }
public string Password { [OperationContract] get; [OperationContract] set; }
Add a private method for checking a security.
public void CheckSecurity()
{
if ((this.UserName == null || this.Password == null) ||
this.UserName == "username" && this.Password == "password"))
{
throw new FaultException("Unknown username or incorrect password.");
}
}
Then call the CheckSecurity method in each of your service class constructor method.
public SomeServiceMethod1()
{
this.CheckSecurity();
// some method codes
}
Client Application
In your client application code, set the service username and password for every instance, or create a static class that will do this for you.
You might also try to use encryption in the username and password to add security.
Note that this is just to add another option for you that might fit your needs but you should always try to use the Microsoft way of doing things.

You can use the ASP.NET Membership provider to authenicate clients. There is an article on MSDN describing how to achieve that.

Unfrotunately security is never simple. For your requirements, have a look at UserNamePasswordClientCredential and UserNamePasswordServiceCredential. They might be sufficient.

All of the answers below are good, but it will depend on who's consuming your WCF service.
For example, I know a WCF service that's consumed by a iPhone application via REST, and some of the schemes above would be very difficult if not impossible to implement. It used something similar to stefan's solution of a session key passed in the message header.

There are many ways to handle this scenario.
Fredrik and stefan's answers together could yield an authentication method and authorization (via token) but you would have to write the login page, db, code, checks, enforcement, token creation, token embedding and token validation logic yourself.
PaulF's suggestion is probably less work because you can use features built into WCF to carry the credentials in the message transport. Could skip the token creation, token embedding and token validation logic pieces.
If you plan on supporting many different devices I would recommend looking into OpenID, Windows Identity Foundation, Azure Authentication Service, etc.
- These are a bit more complicated to setup but provide a solid, standards based and flexible method for passing around credentials. Passive Federation is a good keyword if you want to go that route.
Unfortunately, as Paul said, security is never simple. You have to think about how you authenticate, what you need to know about the person in the service/app, how you pass those credentials other apps/services securely, how they know you are really you and vica versa... Once you get federated authentication setup you no longer have to worry about a lot of those things for this service and others going forward...

Authenticating the software which is generating requests to a service is inherently a very difficult problem, far harder than authenticating a human user. The problem arises from the need to store secret information to be used to construct the credentials sent as the basis for authentication.
When authenticating a human user you can rely on them being able to store a secret (such as a PIN or password) in a data store (the wet grey matter between their ears) which only they have access to.
When you are trying to authenticate some body of software executing in an environment over which you have no control, there is no equivalent storage place for a secret which gives you any assurance that only your software has access to it. So in general there is no way for your software to generate a request which reliably proves that it was generated by your software and not something else.
Your only options are:
Find some way to provide a secret store to the software at runtime, such as a PIN-protected smart card which has to be used in conjunction with your client application.
Rely on security by obscurity, accepting that this can only make spoofing a bit harder and more time-consuming for an attacker, but will not defeat someone determined to break your authentication scheme.

What you need is to implement custom password validation.
Here are good articles about that:
UserNamePasswordValidator and CodeProject.
We use same thing in our project, but API key is used instead of Username. Password can be anything in this case.

Related

IdentityServer4 - Use different user stores based on client_id

I am creating an identity service using IdentityServer4 and AspNetCore.Identity. The service will serve multiple websites which need to have separate users. As such I was thinking the simplest way to keep users separate is to have separate user collections in my database (in my case MongoDb), and simply use a different one based on the client_id.
I am registering my IUserRepository like so:
services.AddSingleton<IUserRepository>(x => new UserRepository(mongoClient));
I was thinking the easiest way to achieve what I want is to handle it at the DI level, so I have come up with so far is to change this to:
services.AddScoped<IUserRepository>(x => GetUserRepo(x, mongoClient));
Where GetUserRepo is a method that reads the client_id out of the request and returns a repository for the correct user collection.
This does seem to work but my issue is how "hacky" the implementation of GetUserRepo has to be:
I have to check if the request url is /connect/token and if it is, manually read the request body to find the client_id
If the user is passing a Bearer token (my identity service also includes a management API for creating users etc) then I have to manually decode the token and find the client_id claim
Really I am just wondering if there is a nicer way to do this (anything provided by IdentityServer4?) and also if this is "ok" to do at all?
The only thing I have found that could maybe help is IIdentityServerInteractionService.GetAuthorizationContextAsync however this requires a returnUrl which I don't have as I am using client credentials or resource owner password credentials methods to authenticate.
Not specifically an answer but as it might help put others on the right track:
After thinking more carefully about our scenario I realised it wasn't really necessary to do what I was trying to do. Instead each website will simply use AspNetCore.Identity to handle their own users (with their own data stores) and I am just using IdentityServer to secure my API and set each website up as a client.

ValidateCredentials() - Security Concerns

I'm hoping all of you .NET devs out there can help me with this dilemma. I currently manage an ASP.NET intranet site at my company. To authenticate our users with Active Directory, we have code similar to the following:
using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, string name, string user, string password) {
bool credsOK = pc.ValidateCredentials(string user, string password);
//Check if the creds come back valid
if(credsOK) {
//Do Stuff
}
}
My concern is that someone with access to the code could potentially set a breakpoint at the if statement after the call to ValidateCredentials, add a watch on the password variable, and thus be able to see the user's password in plain text, which to me is dangerous and insecure, especially in a domain context.
So a couple of questions:
1) Why does ValidateCredentials take credentials as plain strings vs. more secure data types?
2) What are some best practice ways I could pursue authenticating the user against AD using their credentials, without using ValidateCredentials()?
Any help you can provide is greatly appreciated.
Thanks,
-rk15000
My thinking on this, if someone has access to the source code and put breakpoints for harvesting passwords, there is probably bigger concerns to worry about. They are after all going to need to be in a position to be able to attach remote debuggers to your production server(s).
To answer your question though. You will probably need to go down the route of separate sign-in services that would isolate the authentication form your application using some SSO tool like ADFS maybe. However based on the example you've given it's unclear how much of an impact that is going to have

Web API token authentication with a custom user database

I am developing a Web API 2.1 service that needs to authenticate the connecting clients (HTML5/JS clients that I will create and control). Unfortunately, the user information (username, password hashes, roles and much, much more info) is stored in an existing (SQL Server) database to which I only have read access. The Users database table was created 5-6 years ago without any reference to security frameworks, so it's a completely custom format. I'm not allowed to make any changes to either the data or the database structure.
Inspired by this article, I rolled my own token-based method of authenticating users, but I'm lacking the completeness and (re)assurance of using an established security framework.
Is there a way to integrate an existing framework, e.g. OAuth2, within my current project given the constraints I mentioned above? I don't know if it makes any difference, but I'm self-hosting using OWIN.
This is a good answer to a similar question.
It basically says:
Make a custom user class which implements IUser
Define a custom user store which implements public class UserStoreService
: IUserStore<CustomUser>, IUserPasswordStore<CustomUser>
wire everything up
Since the answer is pretty extensive I just provided the basic steps...
details are here: How to customize authentication to my own set of tables in asp.net web api 2?
This is also a very valuable content which also applies to web api:
Customizing ASP.NET Authentication with Identity by JumpStart
https://channel9.msdn.com/Series/Customizing-ASPNET-Authentication-with-Identity
HTH
Someone else, having the competence, can explain the options. But if authentication as service is an option, then check out Auth0 # https://auth0.com
I have tested the service (as Azure plugin) using both HTML/JS- and native Windows Phone applications, against simple Sql Server table and AD. Works liek charm, near zero headache.
I stumbled upon a my solution while trying to implement json token authentication within web api. It is important to note that my solution handles authentication by sending a json token through the Authentication header of the Http request (not via cookies) and not using Microsoft.Identity framework.
Anyway, I basically implemented in a cookbook fashion the solution helpfully described here by Taiseer Joudeh: http://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/
The key thing to notice is the following bit of code:
//Dummy check here, you need to do your DB checks against memebrship system http://bit.ly/SPAAuthCode
if (context.UserName != context.Password)
{
context.SetError("invalid_grant", "The user name or password is incorrect");
//return;
return Task.FromResult<object>(null);
}
Naturally you would replace this bit of code above with your own method for checking your (presumably pre-existing) user database(s). Once I implemented this I realized that you don't need to use new code first identity framework that Visual Studio installs for you.
To make this work I did the following:
1) Created an an empty project and selected Change Authentication/Individual User Accounts. This installs most of the required references and files you need out of the box to use token authentication by way of cookies as well as the code-first identity framework files.
2) Edited these files following Taiseer Joudeh's lead. This requires
some new objects such as CustomOAuthProvider.cs among others. And you need to implement your own user/password check by customizing this code block:
if (context.UserName != context.Password)
{
context.SetError("invalid_grant", "The user name or password is incorrect");
//return;
return Task.FromResult<object>(null);
}
Link to Taiseer Joudeh's instructions: http://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/
3) Pruned my project of extraneous files (AccountBindingModels.cs, AccountViewModels.cs, IdentityModels.cs, ApplicationOAuthProvider.cs, identityConfig.cs, AccountBindingModels.cs, AccountViewModels.cs). Basically, No more microsoft identity references.
I am sure the microsoft.identity thing is excellent, but I was annoyed with the code-first implementation of databases when I was already using some legacy databases of a different structure etc. Hope this helps. I am quite satisfied with the result (after a few days of messing around to get it to work).
I did not want to use any existing classes and finally come out some thing very simple like
var userName = context.UserName;
var password = context.Password;
var userService = new UserService(); // our created one
var user = userService.ValidateUser(userName, password);
if (user != null){
.......
}
See the full details here OAuth Web API token base authentication with custom database
For Role base authentication with custom database
Hope it will help
This might be a completely insane and invalid approach for you but I faced a similar challenge: New web app (MVVM + WebAPI), legacy system used to issue and validate tokens. Inspired by http://tech.pro/tutorial/1216/implementing-custom-authentication-for-aspnet, and because my application would primarily be used by its accompanied GUI (the MVVM webapp), I decided to use a "cookie based" token produced by FormsAuthentication. The FormsAutnentication cookie/ticket is secured by .net internal magic security (which I assume id completely safe and unbreakable).
In my case the cookie simply holds the ticket issued by the legacy system, (but you could store more details there as well, eg by JSONSerializing a custom type). During authorization, my system validates the token against the legacy system. I guess you could use something similar together with a custom AuthorizationFilter.

How are people handling user authentication for web services?

I'm creating a web service to expose some data via publicly accessible APIs. At a high level, what mechanisms are people using to secure their APIs to ensure that a valid, authenticated user is making the call?
The service will be C#, the consumer could be anything (Facebook or iPhone app as well as a website) so Microsoft only solutions are out.
It's not a new problem so I assume there are some standard practices in place to deal with it but my google-fu is failing me on this one. Can the collective point me to any resources? Thanks.
You can still use Membership authentication: have a web service method Login(username, password), inside that method validate user:
[WebMethod]
public bool Login( string username, string password)
{
bool isValid = Membership.ValidateUser(username, password);
if (isValid)
{
FormsAuthentication.SetAuthCookie(username, true);
return true;
}
return false;
}
And that should do it - it will create a cookie that travels with requests and in each method you can check HttpContext.Current.User.IsAuthenticated.
void SomeWebMethodThatRequiresAuthentication(someparameter)
{
if (HttpContect.Current.User.IsAuthenticated)
{
... do whatever you need - user is logged in ...
}
else
{
.... optionally let user know he is not logged in ...
}
}
I believe it can work with different consumers that support cookies because all it needs to work is for consumer to send the auth cookie along with the request to your web server.
I see that ferequently in SaaS web services is used authentication by token key over SSL - we choose this simple method in our last project over OAuth and SAML protocols. Maybe this can be usefull - sometimes simple solutions make things more scalable and over control.
Try the answers in this similar question:
What is the best way to handle authentication in ASP.NET MVC with a Universe database?
We use the WS-Security. It's a published standard so any client (in theory) can use it to send authentication credentials.
Here's another SO question that covers using WS-Security with C#.
How to use WS-Security in C#?

Generating cryptographically secure authentication tokens

Background:
This is really a general best-practices question, but some background about the specific situation might be helpful:
We are developing a "connected" application for the iPhone. It will communicate with the backend application via REST services. In order to not have to prompt the user for a username and password every time they launch the application, we will expose a "Login" service that validates their username and password on initial launch and returns an authentication token that can be used for future web service requests for real data. The token may have an expiration time after which we'll ask them to re-authenticate with their username/password.
The Question:
What are the best practices for generating this sort of token to be used for authentication?
For example, we could...
Hash (SHA-256, etc) a random string and store it in the database for the given user along with an expiration date. Do a simple lookup of the token on subsequent requests to make sure it matches.
Encrypte the user id and some additional information (timestamp, etc) with a secret key. Decrypt the token on subsequent requests to make sure it was issued by us.
This feels like it must be a solved problem.
Based on the feedback from the other answers to this question, additional research, and offline discussions, here is what we ended up doing...
It was pointed out pretty quickly that the interaction model here is essentially exactly the same as the model used by Forms Authentication in ASP.NET when a "remember me" checkbox is checked. It's just not a web browser making the HTTP requests. Our "ticket" is equivilant to the cookie that Forms Authentication sets. Forms Authentication uses essentially an "encrypt some data with a secret key" approach by default.
In our login web service, we use this code to create a ticket:
string[] userData = new string[4];
// fill the userData array with the information we need for subsequent requests
userData[0] = ...; // data we need
userData[1] = ...; // other data, etc
// create a Forms Auth ticket with the username and the user data.
FormsAuthenticationTicket formsTicket = new FormsAuthenticationTicket(
1,
username,
DateTime.Now,
DateTime.Now.AddMinutes(DefaultTimeout),
true,
string.Join(UserDataDelimiter, userData)
);
// encrypt the ticket
string encryptedTicket = FormsAuthentication.Encrypt(formsTicket);
Then we have an operation behavior attribute for the WCF services that adds an IParameterInspector that checks for a valid ticket in the HTTP headers for the request. Developers put this operation behavior attribute on operations that require authentication. Here is how that code parses the ticket:
// get the Forms Auth ticket object back from the encrypted Ticket
FormsAuthenticationTicket formsTicket = FormsAuthentication.Decrypt(encryptedTicket);
// split the user data back apart
string[] userData = formsTicket.UserData.Split(new string[] { UserDataDelimiter }, StringSplitOptions.None);
// verify that the username in the ticket matches the username that was sent with the request
if (formsTicket.Name == expectedUsername)
{
// ticket is valid
...
}
Building your own authentication system is always a "worst practice". That's the kind of thing best left to professionals who specialize in authentication systems.
If you're bent on building your own "expiring ticket from a login service" architecture rather than re-using an existing one, it's probably a good idea to at least familiarize yourself with the issues that drove the design of similar systems, like Kerberos. A gentle introduction is here:
http://web.mit.edu/kerberos/dialogue.html
It would also be a good idea to take a look at what security holes have been found in Kerberos (and similar systems) over the last 20 years and make sure you don't replicate them. Kerberos was built by security experts and carefully reviewed for decades, and still serious algorithmic flaws are being found in it, like this one:
http://web.mit.edu/kerberos/www/advisories/MITKRB5-SA-2003-004-krb4.txt
It's a lot better to learn from their mistakes than your own.
Amazon.com uses a HMAC SHA-1 message token to authenticate and authorize requests. They use this for a fairly large commercial service, so I'd be liable to trust their engineering decisions. Google publishes the OpenSocial API which is somewhat similar. Based on Google and Amazon.com using similar and openly published approaches to securing web requests, I suspect these are probably good ways to go.
Either of the two answers you've provided will suffice. You may find frameworks out there that do this for you, but the truth is it's not that hard to build. (Every company I've worked for has rolled their own.) The choice of database-stored tokens versus encrypted data "cookies" is an architectural decision -- do you want to incur a database lookup on every page view, or would you rather chew up CPU with cookie decryption? In most applications, using encrypted cookies provides a performance win at scale (if that's a concern). Otherwise it's just a matter of taste.
Since you're using WCF, you have a variety of options if using CFNetwork -- for instance NTLM or Digest Authentication:
http://developer.apple.com/documentation/Networking/Conceptual/CFNetwork/Concepts/Concepts.html#//apple_ref/doc/uid/TP30001132-CH4-SW7
I know this doesn't answer your specific question, but I have also been faced with this problem (iPhone - Tomcat) and decided to use the authentication services on the web server as much as possible. There's no significant penalty for including the authentication information with each request in most cases. A quick Google turns up lots of blog posts about WCF and RESTful services (and some related questions on StackOverflow).
Hope this helps!
You should implement:
OAuth2 Implicit Grant - for third-party applications https://www.rfc-editor.org/rfc/rfc6749#section-1.3.2
OAuth2 Resource Owner Password Credentials — for your own mobile application https://www.rfc-editor.org/rfc/rfc6749#section-1.3.3
which are exactly the workflows, from OAuth2, that you are looking for. Do not reinvent the wheel.
This simply sounds like a session identifier with a long expiration time. The same principles used for this in web applications could apply here.
Rather than encoding information, session identifiers are randomly chosen from a very large space (128 bits). The server keeps a record associating the session identifier with the user and other desired information such as expiration time. The client presents the session identifier over a secure channel with each request.
Security relies on the unpredictability of the session identifiers. Generate them with a cryptographic RNG, from a very large space.

Categories

Resources