Generate secure shareable URL for access to web app (NodeJS) - node.js

I am building an application in NodeJS + Express where teams can share information with one and other and chat (kind of like an internal messaging forum).
Sometimes there is a need for the team's clients to view and edit some of this stored information on a case by case basis (e.g. a client asks a question and wants to message back and forth with the team, using my app). I don't want the client to have to sign up for an account in this case.
I am thus wondering what is the most secure strategy for generating a URL where anyone with the URL can view and edit a document/POST data to my app within the confines of a single document, without signing in?
(I've seen a couple of posts on this topic but they're quite old and don't focus on this specific case.)

First of all, I can absolutely understand the benefits, but still it is not an optimal idea. However, I would like to summarize some thoughts and recommendations that will help you with the development:
A link like this should not be able to perform critical actions or read highly sensitive data.
Access should be unique and short-lived. For example, the customer could enter his e-mail address or mobile phone number and receive an access code.
If you generate random URLs, they should be generated in a secure random manner (e.g. uuid provides a way to create cryptographically-strong random values).
If I had to design this I would provide as little functionality as possible. Also, the administrator would have to enter a trusted email address and/or mobile phone number when releasing the document. The URL with a UUIDv4 is then sent to this channel and when the customer clicks on the link, he gets a short-lived access code on a separate channel if possible (on the same channel if only one was configured). This way you prevent the danger of an unauthorized person accessing the document in case a customer forwards the original URL out of stupidity.

Related

Advice on whether possible to display iframe already authenticated (credentials)

I have a problem that I need to solve for my client. The situation is that they have a lot of users on one platform (platform_1). In order to use the platform a user must be signed in, therefore these users (credentials) are given out to clients for them to use the platform. The problem is that one user (one set of credentials) may be given out to a few clients, therefore we cannot know which of the clients did what (in this case - bought something) on the platform.
Figured I would just create a new system where the client can be created and a set of credentials would be attached to that account, then I would just display an iframe of that platform (platform_1) with the attached credentials on the newly build platform and then I would be able to track what the user is doing in the platform.
But turns out iframe cannot handle credentials and also it would not be safe to use this method..
Also thought about scraping the whole platfrom (platform_1), which would work, but then I believe it would be extremely hard to do live auctions, for example scrape the live auction and display it on my system and let the user click on some buttons and the script would do the same on the platform_1, but the delays and overall usage could make it very hard.
I would like to kindly ask you to share your thoughts on ways this problem could be solved or whether it aint possible.

IP Based User Authorization in MVC4

We have an MVC application which we need to do some security check before we let user to start using system. The use case is below;
We have Company table which stores valid IP addresses(also range). And company has associated users. If a user logs in from an unidentified email address, we need to make sure that user is still working for corresponding company. Therefore, we use company email address to validate the user.
I have 2 ways to implement this;
1) Generate a token, and send a link with token as query string to the user, when user clicks on this link, I will validate the user for a certain period of time(1 day)
2) Sending user's email a 6 digit number when user successfully logs in, and ask user to enter that pin number. If the pin is valid, then validate the user.
I recently see many big companies using pin numbers and your mobile no. That made me think that the second method is more secure than the first one(I have no facts, only assumption). Is that true?
Which one of these methods is more secure? if non of them, what is the best way of implementing this use case.
Thanks
Have you looked at IP spoofing - I wouldn't recommend using IP addresses for security.
1) - I don't understand how that is secure...
2) - called two factor authentication and would typically involve sending a pin to a mobile, and not an email.
If implemented properly 2) should be secure, but that is an additional step and not a complete security model. I would start by looking at the authentication that is part of MVC5.
If you want to have a jump start on two factor authentication without building a solution from scratch, look at this open source framework that can easily integrate into an MVC4 application. As Joe R mentioned, relying on IPs for security is not a standard practice.

User specific version of extensions from Chrome Web Store

I've been developing and maintaining a Chrome extension for my company where each customer would be assigned a unique ID in the code. We've been using the ID to determine license status and login to our services (paid extension with monthly subscription fee).
So far we've hosted the extension files ourselves and had unique update URLs for each customer extension. This has been nice and simple; go to our website, click install and you're done. With the latest Chrome release, however, that installation procedure has been thwarted by Google since they now require users to install extensions by dragging and dropping the CRX files into the chrome://chrome/extensions/ tab. Unless of course your extension is available through Chrome Web Store - which leads me to the problem:
We don't want the drag and drop CRX installation - requires Web Store.
We don't want multiple versions of the extension (one for each customer) on the Web Store since that's a maintenance hell every time we update the extension.
We don't want to use Web Store licensing because:
It requires OpenID login.
We sell the extension to schools with many students where the school pays the bill - not the student.
We don't want to lock our payment method to one browser, i.e. we want to be able to maintain licensing and payment through our or servers.
We don't want to have users input a license key since that's too much of a risk with several thousand students having to input the key - also it requires some kind of storage (cookies/localStorage) which would eventually get cleared requiring the license key to be input again.
I'm not 100% certain that my statements are completely correct, so feel free to enlighten me if I missed something.
If they are, the question is whether or not we can somehow tailor the extension for each customer through the Web Store (using the unique ID) without needing to publish one extension per ID?
As a side question any answers that might solve the problem with another method will also be accepted.
For the answer below, I assume your app is a packaged app, not a hosted app.
I have a solution that's fairly similar to your current implementation, but adds one extra step for users. For the student user, the process will work like this:
Download the app from the Web Store. The app does not function yet, and launching it just displays a "Please click the activation link provided by your school/institution" message.
Click a link hosted on your server (i.e., the server where you used to host the update URL) that looks like https://myserver.com/activateapp.php?custid=123456789. You host one such link for each institution you support, and it is the institution's job to provide its link to its students. This link activates the app.
From an implementation point of view, here's how it works:
Host a page, https://myserver.com/activateapp.php, on your server. Server-side, check that the custid parameter is valid. If it is not, send a 404 error.
Your app has a content script that is injected into https://myserver.com/activateapp.php that scans the URL and picks out the customer ID. Once the app finds the ID, it stores it in localStorage. Since invalid customer IDs produce a 404 error, you know that when the content script runs, the page is not a 404 error; therefore, it is reading a valid customer ID.
Any time the app wants to query your services, it checks if it has a customer ID in localStorage. If it does, it uses that ID; if it does not, it displays a message that the app has not been activated yet. Packaged apps will never have their localStorage erased unless your app is programmed to wipe its own storage, or the user does it from the console. Storage erasure will never "accidentally" happen. Even the strongest browser-wide data/cache purge will only clear localStorage from Web pages, not from apps and extensions.
For extra security -- if you don't want people randomly guessing customer IDs -- you can add an extra signature parameter, like https://myserver.com/activateapp.php?custid=123456789&sig=2464509243. This extra parameter is some server-verified transformation of the customer ID (ideally a cryptographic signature or a purely random value associated with the ID in a database) that is impossible for anyone to guess. When the request for activateapp.php hits the server, it checks for a valid customer ID and a valid corresponding signature. Of course, this doesn't stop people who have legitimate access to a valid link from sharing the link to unauthorized people, but I expect that was a vulnerability that existed in your old system anyway.

Securing a login system without passwords

I'm developing a mobile application for a company. Everyone at the company has an #company.com email address. The app itself is confidential, so it will only be installed on employees' devices. This app communicates with an external server to store and retrieve data.
Ideally what I would like to accomplish is to let people log in to the app by just providing their email address, without a password. Here is my current thinking:
A new user opens the app for the first time on a certain device and puts in their email address. The email address is sent to the server, along with a static token embedded in the application (which is the same for all instances of the application).
The server verifies the token and the fact that the email address is #company.com. It responds with a new token/key for use only with that user and device, which the client stores in plain text locally. That key is effectively the user's password. It is hashed, stored in the server database, and marked as disabled.
There are two possibilities at this point:
The server sends an email to that address confirming that they want to log in on a new device. The email contains a link which, when clicked, marks the key as enabled. There would need to be rate-limiting on new device requests so people can't get spammed if someone discovers the token embedded in the app.
An administrator specifically approves new device requests.
Every subsequent client request to the server must include the key.
Assuming all communication is over SSL, does this sound like a secure strategy? Is there a more secure or simpler approach?
Additionally, what is the best way to generate the token that will be stored client-side? Since I want users to only put in their email address the first time they use the app, I believe that this token will never change. Here is my current algorithm (PHP) loosely based on Drupal's drupal_get_token():
// Usage: get_token($email) or get_token($client_token)
function get_token($value = '') {
$salt = hash('sha256', 'Some static, predefined phrase');
$hmac = base64_encode(hash_hmac('sha256', $email, $salt, TRUE));
return $hmac;
}
As you can see it doesn't protect against parallel attacks (e.g. if someone figured out the predefined phrase and algorithm and they had access to the database, they could generate hashes and compare them against the ones stored in the database) but because the original key value is already long I don't think this would be nearly as effective as it would be against normal passwords. Additionally I am not sure of a way to create a dynamic salt that an attacker would not already have access to if they could access the database (or honestly if it would even matter at that point, since getting access to the database would expose the data we're trying to keep confidential anyway).
After some research and more thought, I believe that the answer to this question comes down to the vulnerability of the local storage. Since it's safe to assume in this case that only company employees will be using the app, there is insignificant risk of malicious code running in it even if there was a problem in the code that would make that possible. As a result the main risk is from some other app taking advantage of a security hole in the OS's local storage implementation to read the local private key off the disk. Since the existence of the app should not be known to anyone outside the company, it is very unlikely that this information would be directly targeted. So I think this is an acceptable process for this company.
In the general case though, anyone considering implementing a similar model should be aware of the risks of basically storing a password in plain text locally. (This is as opposed to storing a password in the user's head, or equally likely in plain text in a password file elsewhere on their machine; it's your call which is more secure.)

Facebook Javascript SDK security

I'm in the process of using the facebook javascript sdk to provide user login functionality for a website.
What I'd like to do is simply take the logged in user's unique facebook id and then put/fetch data to/from a mysql database using the id to determine what data is available to said user.
However I don't really feel like this is very secure. Whilst I'm not storing anything sensitive like credit-card details etc, I'd obviously prefer it to be as secure as practically possible.
My fear is that with javascript being what is it, someone could fake the facebook id and just pull whatever they wanted.
I'm aware that the php sdk would provide a solid solution to this problem, but i like the javascript one mainly because it's easy to use and I have the basis of it set up (I admit it, I'm lazy).
So, my questions are:
Would this set up be as insecure as I feel it might be?
Is there anything I can do to improve the security of such a system, other than switching to the php sdk?
Thanks!
Facebook Ids are pretty hard to make up (at most a user will only know their own). Depending on what you store in the database (which will not be anything that the user cannot get on their own, unless you ask for extended permissions)
If you are worried about a user trying to get information from the database, add an access token or signed request to each row and us that and facebook id to get data. That will greatly increase security.
EDIT
There are few occasions where you get a signed request from a user:
* A signed_request is passed to Apps on Facebook.com when they are loaded into the Facebook environment
* A signed_request is passed to any app that has registered an Deauthorized Callback in the Developer App whenever a given user removes the app using the App Dashboard
* A signed_request is passed to apps that use the Registration Plugin whenever a user successfully registers with their app
Signed requests will contain a user id only if the use has accepted permissions though, and are not passed again if the user enters the application, and accepts permissions (meaning that the signed request would not contain the ID). Because of this saving an access token may be a better idea. Here is more on the signed request
Also the signed request is in the url (param = "signed_request"). I always parse it through c# but I am sure you can at least get one through javascript
It's pretty easy to spoof the origin using curl. I'd imagine Facebook has another mecanism in place to make this possible. If you inspect their code, it appears that they generate an iframe and pass requests through. If I had to guess, they have setup the requests to only be made from the Facebook domain, and ensure that the iframe can only be embedded in a page that has a white listed domain.

Resources