Store password in Javascript localStorage - javascript

I'm building an Outlook Add-in (which is basically an iframe served in Microsoft Outlook client, be that Windows, Mac or browser). It's an internal company tool that sends data to our server. It uses React/JS/Node.
Our endpoints use basic authentication, so I need to pass a username/password with each request.
The problem is I would like to "remember" each user so they don't have to enter credentials every time the app loads up. I've figured I can use HTML5 localStorage to persist username/password values.
However I'm wondering how safe this is and suggestions for how to keep a copy of the password?
Maybe do a base64 encoding of 'username:password' (for Authorization HTTP header) and store that instead?

I think there's no safe way to store the password on the client side. However I have two recommendations.
Because you are using React you don't have lot's of page refreshes, you can ask for the password on each page refresh and store it as a variable (very safe).
If you want to store it, then do not use base64 encoding. Instead sign the password with jwt on the client and store the signing secret as a config variable then uglify the config file and minify it. This will make it very hard to find the secret.

A session key might be a good alternative. Instead of passing around the username/password pair, you can instead have the server create a session cookie to be used for authentication.
I'm not an expert on this, but here is one way I'd do it if I had to:
The client should generate two keys: A public and private key. Store these keys in sessionStorage (not localStorage).
When the client attempts to "authenticate" with a username/password, the username, password, and secret key, should be encrypted with the server's public key and sent to the server.
The server's public key can be stored in localStorage. Find a way to transmit this key to the client. Maybe an endpoint like /pub-token?
The server will decrypt this username/password and after validating the pair, store the client's secret key, and generate a session cookie, which is sent back to the client.
Now in subsequent requests, the client will encrypt any message being sent to the server using it's public key and the session cookie will accompany those requests.
The server will validate the session cookie, and decrypt messages sent by the client using the client's secret key.
On the server side, you can use a fast key-value store like redis or memcached to map the session key to a client's secret key.
When the server determines the session is "over", it will delete the session cookie and the client will need to generate a new key-pair again (or keep using the same one...).
I'm not sure if this flow fits the notion of a "session key", but I find this is more secure than simply having the server generate a key and using only that key as authentication.

Related

Encrypt in frontend and decrypt once it reaches backend

What would be the most secure way to do so?
So far I tried providing the same public key for every user which automatically encrypts the data sent over a https request to my backend.
For that reason, people with enough knowledge can get the json payload before its encrypted and encrypt it by themselves on their end and send it over my server.
The most ideal case would be so the client side only has access to the public key while the server can view both user's private key and public key.
I'm currently using RSA for this
Frameworks in use: VueJS and NestJS
The web browser belongs to the user. It is completely under their control. Anything you do in the browser can be inspected and manipulated by the user.
You can encrypt data during transmission to protect it from third-parties with HTTPS.
You can't make the user's browser compensate for you not trusting the user.

RESTful API write security

I've recently started using modern front end technologies like React/Angular and as a result have started using tools like JSON Server to recreate dummy restful db interactions.
My understanding is that most rest api's authenticate via some kind of token and secret that is either passed as part of the url or as a header. This seems fine for retrieving data, but is it not risky exposing these login credentials in a front end language like JS when writing is possible?
My thinking is that all it would take is a simple view source for somebody to steal my token/secret and potentially start populating my db with data.
In the problem that you describe the client (browser) has the login credentials because the server provide them. There is no "exposing" as the credentials are already exposed. Exposing your credentials to every client means that there is no security.
When we talk about security we consider as a client the browser not the real person that operates the browser. As you said, the real person can access all the browser's data.
To secure your API the secret key must be kept secret. This means that each client has a different key and uses it to get their data/services from your RESTfull server.
In a simple senario this key can be used/managed like the session id.
The client should first pass through an authorization process (login maybe) and then a temporary key can be generated for the client's session.
Generally, a key is converted to rights. If every client by default has the key, everyone has the default rights, so you may also remove the key and set the default rights to every request.
A client that you don't want to have full access to your db should have a key that gives him limited access to your db.
On the other hand, if the client provides the key, this is secure. For example a php code on a server that uses the secret key for accessing your API.

Understanding JWT

I've spent a couple weeks trying to wrap my head around JWT objects. The premise makes sense but where I get confused is the security aspect. If I am a Javascript Client (e.g. Firebase) and want to send a secure request to an api using Open Auth, I would encrypt my message with a key. However, since the client source may be viewed how can I secure my Key so malicious requests don't go through. Am I missing something. Is there a way to secure the key?
Joel, I think you got the directions wrong ;)
One would use JWT within the OAuth protocol to achieve what some people might call "Stateless Authentication", meaning that the auth server would issue a signed token (for e.g. a client application or a user) after successful authentication (of the client or user) without storing info about/ of it, which would be required when using opaque token.
The signed token could be used by your JS client to e.g. call a certain REST-API endpoint (on a so-called resource server) that would verify the signature of the token and authorize your request or not, based on the content (the claims) of the JWT.
Both, your client application as well as the resource server are able to introspect the token and verify its signature because they either have a shared secret with the auth server (who used the secret to sign the token in the first place) or know the public key that corresponds to the private key the auth server used to sign the token (as Florent mentioned in his comment).
JWTs can also be encrypted, which is useful if the resource server or the auth server require sensitive information but don't want to store/ access the data. You would not be able to introspect it as long as you don't have the used encryption secret.
... long story short, the OAuth protocol describes client auth against a resource or an auth server. JWT can be used to transfer auth prove (as a Bearer token within the Authorization header). However, the idea of using JWT in the OAuth flow is not to "send a secure request to an api".
The encryption process is performed using the public key of the recipient.
Your client has no private key to generate and manage.
If you want to receive and decrypt such JWT, then your client has to create a key pair (private and public) for the session only and then exchange the public key with the server.
When building an api server, I prefer the client do the encryption process on their own server, and send the encrypted data after that. Everything is under https.
If the encryption somehow must be done on the web client side, I prefer the key to be very short-lived & time based, and both the api server and client have the agreed special algorithm to generate that key again. Therefore, if the key is hacked somehow, the attacker can not benefit in long term.

AngularJS SPA and RestfulAPI Server Security

Quick background:
Full Javascript SPA AngularJS client that talks to a REstful API server. I am trying to work out the best authentication for the API Server. The client will have roles and I am not concerned if the user can see areas of the client they aren't allowed because the server should be air tight.
Authentication flow:
User Posts Username and Password to let's say /api/authenticate
If a user the server generates api token ( sha hash of fields or md5) and some other meta data determining roles to pass back in 1) post reply.
The token is stored in a session cookie (no exp, http only, ssl)
Each request after authentication takes the token in the cookie and verifies this is the user.
SSL user on server.
Questions:
Is this the best way to secure the server?
Do I need to worry about replay attacks w/ SSL? If so best way to manage this?
I tried to think of a way to do HMAC security with AngularJS but I can't store a private key on a javascript client.
I initially went the http authentication method but sending the username and password each request seems odd.
Any suggestions or examples would be appreciated.
I'm currently working on a similar situation using angularjs+node as a REST API, authenticating with HMAC.
I'm in the middle of working on this though, so my tune may change at any point. Here's what I have though. Anyone willing to poke holes in this, i welcome that as well:
User authenticates, username and password over https
Server (in my case node.js+express) sends back a temporary universal private key to authenticated users. This key is what the user will use to sign HMACs client side and is stored in LocalStorage on the browser, not a cookie (since we don't want it going back and forth on each request).
The key is stored in nodejs memory and regenerates every six hours, keeping record of the last key generated. For 10 seconds after the key changes, the server actually generates two HMACs; one with the new key, one with the old key. That way requests that are made while the key changed are still valid. If the key changed, the server sends the new one back to the client so its can flash it in LocalStorage. The key is a SHA256 of a UUID generated with node-uuid, hashed with crypto. And after typing this out, i realize this may not scale well, but anyway ...
The key is then stored in LocalStorage on the browser (the app actually spits out a your-browser-is-too-old page if LocalStorage is not supported before you can even try to login).
Then all requests beyond the initial authentication send three custom headers:
Auth-Signature: HMAC of username+time+request.body (in my case request.body is a JSON.stringify()'d representation of the request vars) signed with the locally stored key
Auth-Username: the username
X-Microtime: A unix timestamp of when the client generated its HMAC
The server then checks the X-Microtime header, and if the gap between X-Microtime and now is greater than 10 seconds, drop the request as a potential replay attack and throw back a 401.
Then the server generates is own HMAC using the same sequence as the client, Auth-Username+X-Microtime+req.body using the 6-hour private key in node memory.
If HMACs are identical, trust the request, if not, 401. And we have the Auth-Username header if we need to deal with anything user specific on the API.
All of this communication is intended to happen over HTTPS obviously.
Edit:
The key would have to be returned to the client after each successful request to keep the client up to date with the dynamic key. This is problematic since it does the same thing that a cookie does basically.
You could make the key static and never changing, but that seems less secure because the key would never expire. You could also assign a key per user, that gets returned to the client on login, but then you still have to do user lookups on each request anyway, might as well just use basic auth at that point.
Edit #2
So, after doing some testing of my own, i've decided to go with a backend proxy to my REST API still using HMAC.
Angular connects to same-domain backend, the backend runs the HMAC procedure from above, private key stored on this proxy. Having this on same domain allows us to block cors.
On successful auth, angular just gets a flag, and we store logged in state in LocalStorage. No keys, but something that identifies the user and is ok to be made public. For me, the presence of this stored value is what determines if the user is logged in. We remove the localStorage when they logout or we decide to invalidate their "session".
Subsequent calls from angular to same domain proxy contain user header. The proxy checks for user header (which can only be set by us because we've blocked cross-site access), returns 401 if not set, otherwise just forwards the request through to the API, but HMAC'd like above. API passes response back to proxy and thus back to angular.
This allows us to keep private bits out of the front end, while still allowing us to build an API that can authenticate quickly without DB calls on every request, and remain state-less. It also allows our API to serve other interfaces like a native mobile app. Mobile apps would just be bundled with the private key and run the HMAC sequence for each of their requests.

Secured data client side cache?

Are there any ways to cache secured data at client side such that it cannot be modified by users so that it is safe to be used again at server side ?
Or if there is any modification by user then it should be available but probably with flagged as not original data.
Are there any ways to cache secured data at client side such that it cannot be modified by users so that it is safe to be used again at server side?
No. Once the data is client-local, you've lost the game.
Or if there is any modification by user then it should be available but probably with flagged as not original data.
You could sign this data with a key known only to the server. With cryptographic signing, anyone can verify the identity of the signer, but only someone with the private key can generate the "right" signature.
Short answer - no.
Longer answer - you could probably use web storage/indexedDB/Web SQL Database, in conjunction with some kind of salted hash to check later that object hasn't changed, e.g.
Hash object with salt in server side
Send object and hash to user
get object and hash back from user
hash the object you got back from user again and check that the hash is equal to the one that you got back from user
Since storage on client side is limited to - websql(low support) localStorage/sessionStorage('argued support'), indexedDB (low support), and of course cookies are easily accessible, no, there is no way to secure data stored on the client side.Even if you encrypted the data using some JS method, the method could be found by a hacker. Server side is the only true way to secure data using some sort of HMAC.

Categories

Resources