Scenario:
I have web deployed ASP.NET-MVC 5 application with individual user accounts: Identity 2.x. Every user has an e-mail and password to log in the web application via browser, this means that user can log via any device with internet browser.
I would like to enable user logging on condition that he uses exactly the same PC class machine every time he logs in.
I can politely ask user to run any desktop .NET(.exe) application if necessary. I can also ask user to use Chrome browser if the plugin is necessary to achieve this. Literally I can assume anything. The solution might be very uncomfortable, it's fine.
My semi-solution:
Obtain CPU serial number via desktop(let's call it Authorizer.exe) application which will send this unique ID to the ASP.NET-MVC Web Application while logging into it to authorize that user uses certain PC. Authorizer.exe would detect logging into Web Application by sniffing packets going through network. PLUS Detect user's location, which restrains him from moving his computer.
Create desktop app which can be activated once only with unique serial provided from the web application. Login to the ASP.NET-MVC would be possible only if this desktop app is openned.(I have no idea how to do it).
Why do I ask this question:
If somebody steals user's e-mail and passwords I don't want to let the thief being able to login but the most important to me is that I don't want let user to log in from different devices.
Add log4net in config file config and enter the following details. Add a class Log. cs in the Utilities folder. Now, in the constructor of this class, instantiate logs for monitoring and debugger loggers.
By default MVC apps use Form Authentication and Simple Membership, so you need to make it "false" to run Windows Authentication. Select the project name in Solution Explorer and then in the Property Explorer, click to enable Windows Authentication.
The only solution that I can think of is to issue client certificates, and use certificate authentication in your application.
To manage certificates you need to implement a PKI, which requires:
The weak link is the last. You must pay attentiton to how you install, and how you issue the certificate.
To install the certificate in the browser. You can:
NOTE: in both cases you have to accept the request and issue the certificate or reject it. Certificates are not issued automatically
The first option has a problem: if you send the certificate to your user he'll be able to install it in any machine, any number of times. To solve this problem you'd need to get access to your user's machine, copy the file, install it, and delete it. The second option solves this problem.
The second option is safer. But a user with good knowledge can still recover the file issued by the server in this process, and install the certificate in a different place.
Another very important point to take into account is that, when you issue a certificate there is generally an option that allows to make its private key exportable. If you set this option, the user can export the PK from the browser where it is installed, and install it somewhere else. Obviously you want to avoid this. So, disable this option.
With this option, the user can still export the certificate, but without its private key, so it can't be installed somewhere else.
I don't give additional details on how to setup the PKI, because it depends largely on the infrastructure (OS and version). If you want to know more about certificates and PKI the wikipedia entry for "X.509" and wikipedia entry for PKI. Then you can look for additional information on setting a PKI in your particular infrastructure (OS).
You can rest assure this system is really safe: for example, in my country you can identify yourself by this means to make a lot of "official" things, like declaring and paying taxes.
And, if you're wondering what happens if you want to reject access to a user that already has a certificate. The answer is that you can revoke a certificate whenever you want, so that the server won't allow your user to authenticate with his certificate, because it's revoked.
And another thing that can worry you is that other user takes the same machine and logs to your application. It's harder thanit looks like for this reasons:
I've seen a lot of anwsers that propose using a "magic way" of identifying the user's machine, without him knowing and accepting it, and, or that can be broken by some user actions. Those solutions are unstable, and can even be not legal. Besides, none of the explained solutions is reliable or easy to implement, but the one that I'll so you at the end of my answer. But before this, allow me to explain why I prefer the certificates solution.
Installing an issued certificate is something which isn't hidden from the user, and that can't be broken unless the user deletes the certificate on purpose. The user can be informed that he needs the certificate to access the application, so you're neither cheating, nor making "magic" to identify his machine. It's a clean, supported, and documented solution. Besides a certificate cannot be caracked or hacked (in an strict sense, everything can be cracked or hacked, but this is way too hard to crack). Apart from this, the same certificate can be shared by all browsers, because it's not installed in the browser, but in the machine's certificate store. So, even if the user opens the application with a different browser, the certificate will still be there. And it's very easy to check if the problem to authenticate it's a missing certificate(or something related to it).
However, if you still prefer to implement a solution that can identify your user's machine without him approving it,or without explaining how it works, you can use "supercookies". If you google for thister you'll find in a lot of places that this exploits Flash storage. Or even Flash + HTML5 storage. Or it can use even many other places to store the required information. But you'll see that this techniques are frowned upon. And can be against the low and make you get into trouble. However, that said, if you still want to do this kind of "dirty" thing, you can use evercookie. It's implemented in JavaScript and you can see the information and donwload the code from this link:
Disclaimer: if you use this evil thing and get into some kind of trouble, don't blame on me! I told you!
Your solution is very difficult and requires a lot of work. I'd suggest you something much more simple.
First of all, you add a binary field 'FirstTime' to users db and init it with 'true' by default. When user make log in first time you drop him a cookie (I'd encrypt it for the better security) and change the field in user's record to 'false'. When user log in again you check this cookie and disallow him to log in if cookie not exists. Therefore, you let every user to log in one time from any place, and then he or she can log in only from the same browser and same machine.
See the following pseudo code:
Login (Email, Password)
{
if (FirstTime)
{
DoLogin();
SetCookie();
FirstTime = false;
}
else
{
if (GetCookie())
DoLogin();
else
ConfirmError();
}
}
An only weak point in this solution is the theoretical possibility that user may try to copy the cookie to another machine. It, however, requires from your users to be a quite good hackers, and from your description I suppose that they are not.
UPDATE:
I thought much about you problem and I'll try to suggest you an improved solution which is still easy in implementation, not requires a weeks of hard work, not costs a lot of money and not forces the customers to fulfill the complicated operations.
The idea is to combine a number of the client detection methods, while it's probably not so difficult to pass around each one them, but it's really problem to pass around all of them together.
So, you can do three things:
All this information you can store per user in your DB and the combination of these factors will provide the reliable decision base. For example, if somebody has a cookie but the Local Storage record is missed, it's obvious that the cookie was copied. Disallow access and delete the cookie. Let's imagine the cheater came back to the original computer, found a Local Storage record, copied it as well and try to connect again... but it's already no cookie here! And don't forget about the browser fingerprint, which is more difficult to fabricate. If you limit the number of unsuccessful connection attempts during the certain period of time, it will be REALLY difficult to break your protection.
Checking any hardware info, such as CPU Id is imposibble with javascript, because it can't run out of browser's sandbox. Doing it with c# is possible though:
public static string GetCpuId()
{
var mbs = new ManagementObjectSearcher("select ProcessorId from Win32_processor");
var mbsList = mbs.Get();
var cpuId = "";
foreach (var mo in mbsList)
{
cpuId = mo["ProcessorId"].ToString();
break;
}
return cpuId;
}
But there's no sence in it.
Imagine user tries to log in using email and password. Somebody's sniffing traffic and steals user's credentials. So he wants to sign in to your web app and realizes it's impossible because he also needs CpuId
. Do you really think it's to hard too steal it together with password and after that do a fake sign in request to get cookie? No it's not.
Having desktop authorize application is even worse idea, cause any 10-year old cracker will hack auth tool in a few seconds.
IMHO, good way is to implement some kind of 3D-secure
, e.g. :
Also you need to use HTTPS
for all secure-sensitive traffic.
If you don't want to let user use application from any other device - then you'll need to implement some api
on server-side, that can be used by desktop application (client-side) with integrated hardware licensing
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With