I am writing a web application using client side templating. This application needs to interact with a REST Server which supports Basic Http authentication (using ssl). So, with every request that needs to be authorized, username and password are passed in Request header.
My question is where and how to store username and password so that they can be accessed client-side by javascript code.
I wouldn't store usernames and passwords on the user's system. This is a security problem.
Instead, your REST login service should send a session cookie back that includes an encrypted authorization key. That cookie will then get passed back up upon further REST calls and your REST service backend can read the cookie to validate that the user has a valid authorization token.
If you don't want to use the cookie mechanism because you have to use a different header, still consider using the auth token method and storing the auth token locally (using cookies or local storage). If you don't have control of the backend at all, and you have to pass username/password up, then I think you are stuck. Saving the password on the client's machine (in cookies or local storage or whatever) is a bad idea because it can be read in plain text. Any encryption method you use can be easily reverse engineered.
Related
Just started looking a JWT and the examples I have seen first require the user to do a POST request with the body of the request containing the username and password in plain text.
After this request has been authenticated, a JWT is sent which is then used is further requests.
Clearly I am missing something here but have I not just sent unsecure data on my first request? Is this where I would need HTTPS?
JWT doesn't give you security out of the box it's main point is to make sure that the Token wasn't changed by untrusted authority. It just verifies that the data inside is correct.
However, the JWT itself, the data block of it is readable by anyone, you can just parse it on the client, and read the userName / email / from it, if you want to, so an attacker could read it too, if the data block itself is not encrypted.
HTTPS would encrypt all the data wich is passed between client <-> server. It has nothing to do with authentication, its just a protocol, you should use it anyway, either with JWT or not.
JWT are used for authenticating a user that already authenticated himself to the server before, and are really useful in stateless environments, not really in stateful environments.
The purpose of JWT is to store enough data on the user, so that the server that receives it can use it to decide if the user is legit and what he can do. They are really useful in distributed environments, because then you can just pass the JWT from one server to another, and as long as they all hold the signing key, they will be able to authenticate the user only based on the token.
The username and password are only required for the server in the first request, so the server can authenticate the user against a database of users for example, and then, every request after will use the token, making the server to be able to authenticate the user without another round trip to the database on every request.
As far as HTTPS goes, I would say - use it for everything. In today's wireless networks everywhere, your data is much more exposed than before.
Sorry if this has been asked a few times, but can't quite find out a solid response.
I want to secure the login procedure and session (kind of) between an HTML5 app and a PHP web service. I present the user with a login screen that uses HTTPS with the server, and then give the client a random GUID that is stored in a database with their time of login and last request time, and their actual user ID that I store for their row on a users table. So the GUID might be different every time but the user ID it maps to on login can only be seen server side.
I'm vary weary when it comes to authentication and never really dealt with a HTML5/JS app against a web service like this. I've usually developed ASP .NET sites and used sessions.
I've recently discovered JWT tokens which encrypts data stores in the token string that is contained on the client and passed to/from the server. Is this safer than what I'm doing? Should I be using JWT as opposed to this GUID mapping I have now?
What I'm aiming for is a session-less request to a web farm which could put you on to any specific web server, and the request is validated to see if that request has came from a valid logged in user.
Any advice would be welcome :).
Thanks.
Using a JWT token is totally safe provided you don't encode sensitive data in the token because the token can be decoded without the secret.
What you can do is to have two key pairs (private/public) RSA keys.
Private for encoding the token and sending it to the client on login success
the client saves the token to maybe a cookie, HTML5 localstorage e.t.c,
on every request, the client passes the token via the request header back to the web server, then the web server verifies the token with the public key. whilst decoding the token and getting the GUID from the token and can then proceed with the request.
This workflow can work across several server side languages as there are many JWT libraries for them.
We're in the process of migrating our MVC-based server application and making a REST-ful API through which calls will be handled.
I've been reading up on AES encryption and OAuth2 and decided to implement a solution grown form those concepts as follows:
Client sends a request to log in providing a UserID or Email. This request is HMAC'd using an API Secret Key.
The server checks if the UserID/Email matches an existing account and if it finds one, creates and stores a server nonce which it sends as part of the response to the client.
The client creates their own client nonce and creates a new temporary key from the API Secret key and both nonces. It then sends a login request with a password encrypted using this temporary key [for added entropy and to avoid ever sending a password in plaintext].
The server decrypts the password and HMAC using the latest nonce it has stored for this client on this platform [a mobile and a web client can have their own distinct nonces and sessions] and the client nonce which was sent in the clear, if the HMAC checks out it then validates the password against the database [PBKDF2 hashing and salting].
If the request is valid and the password and UserID match records, a new Session Secret Key is created for that UserID on that platform and this Secret key is sent to the client and will be used to HMAC every API request fromt hat client henceforth.
Any new non-login request would include an HMAC signature computed from the Session Secret key and randomized IV's.
All communication is handled through TLS so this is added security and not the only line of defense.
On the mobile apps this would work since you can hide the Mobile App's Secret Key on a config file and this gives some decent measure of security - [perhaps not a lot I'm not fully sure] but if we try to convert all the requests from our webpage to this form this would mean using Javascript to handle the client-side AES encryption and authentication and ... well as this article clearly explains, " if you store your API key in a JavaScript web app you might as well just print it out in big bold letters across the homepage as the whole world now has access to it through their browser’s dev tools."
I could use only the nonces as the API Secret key -- or forgo using AES encryption for those requests altogether and try to validate through other means such as CSRF tokens and making sure all the requests come form our own front end in some way - but this wouldn't work if we wanted to create an API that allows integration with other pages or services and even then, how would I go about securing the client's secret Session key?
The article suggests generating single-use cookies as a tokens but that's a limited solution that works for the poster's services but wouldn't for us. I want to be able to HMAC every request the user sends with a user-specific key that can expire and be reset and since the service will eventually handle money, I want request authentication to be locked down tight.
So what are my options?
Do I just ditch Javascript since it is doomed? Is there some way to store a secret key without exposing it clear as day hardcoded into the .js script? Should I generate a new temporary Secret key to be used for login calls only and send that to the user when they request the server nonce?
Also, the post I linked to first suggests using a cookie to store the Session key for the client and then access the key from JS. Is this ok or would that provide more holes than it seals?
It's good to know which measures prevent which security holes.
You are correct that JavaScript is not well suited for encryption because there is no place to store a secret. There are also no good encryption libraries because you shouldn't be doing encryption in JavaScript.
The session key can serve as the authentication key. If you're using TLS your connection is secure and an attacker can't know the session key.
Additionally, JavaScript doesn't need to know the session key. Cookies, by default, are sent with every request. And you can set the cookie to be an http-only cookie. You don't have to do this, but it does add another layer of security.
You can give the session cookie a very long expiration time so that it essentially works like a secret API key. The browser will take care of storing the cookie securely. It is advised to rotate the session key often, typically at the start of every new session and when authentication information changes (like a password reset).
CSRF-tokens prevent replay attacks. It's definitely recommend to secure a modification request with a CSRF-token. You don't need a CSRF-check for every request, just requests that modify sensitive information (such as your login credentials, or in your case: transactions).
For CSRF-tokens you can use the same approach as the session key: store it in a cookie.
The key part is that JavaScript doesn't need to know about any of this.
One important thing that I'm sure you realize as well is that any keys or nonces you generate must be cryptographically safe. Don't use low entropy functions.
So:
You don't need to encrypt the userid or email, TLS does that for you already. Additionally you can send the password as well, you don't need to send it separately in step 3. We're not going to do any encryption in JavaScript. All encryption is handled by TLS/HTTPS alone.
If you have a separate authentication server (like a single sign on), this approach is fine. Else you can skip this step.
You don't need this.
The server doesn't need to decrypt anything, encryption is handled by TLS. How you store the password is a topic on it's own but I think you've got it.
Ok. Again, the client shouldn't encrypt anything.
Send just the session key. It's is enough.
Revised is:
Client sends login credentials. Connection must be secure.
Server verifies credentials and sends authentication token as cookie and keeps track of the authentication token is a session list.
For every request:
Client includes authentication token. This happens automatically if you use cookies.
Server verifies authentication token and possibly generates a fresh token that the client will use from then on.
Mobile apps should be considered as public clients. This means they should not store any secret. Whatever the encryption algorithm you will use, nothing prevent the client credentials from being compromised.
That is why the OAuth2 Framework protocol defines the Implicit grant type flow which allow public client interaction and do not need any client authentication. You may also consider the RFC7636 to protect the issuance of the access token.
What is the challenge/response method to securely authenticate with a Server without HTTPS (without sending out password)?
I have an app (Javascript client) that connects over CORS (authenticate) to our backend which in turns will return a token containing the claim (JWT) over non-HTTPS. The REST is stateless so we do token-based and not have session at all.
When the client gets that token, (containing claim) it is added to the header for each request of the client and therefore the backend knows which User Id is doing that request and do the appropriate thing. So far this works for us. My concern is with the authentication process and with the security of each request.
To authenticate the clients sends out email and hashed password pair, however I want to know if there's a more secure way even without using HTTPS for now. I've read to not send the password but do a challenge/response, but what is the implementation of that idea?
And last question would be, even if we get around with the authentication process securely, how about on each request which contains the token with claim can it be secured also?
There is no possible way to do this securely without HTTPS. For your server to authenticate users, you need some kind of token (cookie, adding to requests like you have, etc.) However, the problem is that, without https, an eavesdropper can add javascript to your page. They can then capture the token and use it themself (stealing all the user's data), or modify it. If you want your product to be in any way secure, you need HTTPS.
Edit: I guess you could store some information about the device sending the request (user agent and such), and only allow the token to be used on that device. However, an attacker could just fake the user agent when they reuse the token, so this wouldn't be too hard to bypass.
Challenge response is a mechanism to send passwords in non-clear way.
1°/ client and server must share a cyphering key : best is to manually add certificate on client but could be a little bit heavy. Another solution is to store the key only one time into localStorage.
2°/ client requests a challenge to server : this is a "phrase" generated by server
3°/ client concats its password with this "passphrase", ciphers and send response to server : Challenge => Response
4°/ server decrypt message, search and remove its passphrase to get password.
Currently, my authentication flow is as follows:
User fills in a login form in the client browser app (AngularJS, to be precise), username and password are stored into the browser's memory (plain Javascript variables).
When accessing protected API resources, the request is authenticated with HTTP Basic Auth over SSL using the credentials stored in memory.
The problem is, when the user refreshes the page, her credentials are wiped out and she needs to sign in again. Am I missing something obvious here?
Few solutions I've found so far:
Store username and password into a cookie: this seems obviously insecure, even when using secure cookies and/or encryption.
Use session cookies: this seems to be against the RESTful principle of statelessness.
(I guess OAuth has the same problem with securely storing access tokens in the client?)
Session cookies are totally fine here. Once installed you dont care of them, browser will send them with each request via headers.
Inspired by this answer, I ended up doing something like this (link opens a rather large picture).
In short, client stores Access Token in a javascript variable, but Refresh Tokens are stored in a server-side session (on the server hosting our client app, not on the API server).