Good time of day!
I am wondering about right way to implement authorization on abstract website.
I have a server on which mysql is running. And in one of it's databases it has pairs: login + password.
Also I have a web page with "sign in form". User's input (in plain text) i need to transmit to the back-end and check it over. This plain text delivery is pain in my neck.
I know that there are various modern technologies such as openID and OAuth. I cant use them. I need to do tiny web application.
I was thinking about using salt with hashing on the destination server, but came to a conclusion that it is useless against sniffing network. Then I decided to modify with some instruments login+password pair on the client side.
But the only way how I can accomplish that is with client javascript, that can be easily read by someone and do all steps to prepare his value that would be fatal to my auth system ).
I am really interesting in theory, not a list of ready solutions but explanations of how it is right to do. But ready solutions are welcome, too.
Thank you in advance!
If you want to keep it simple I would suggest you keep your standard login form (plain text POST) and force to use SSL when posting (i.e. use https instead of http in the post url). This way, nobody can sniff the user/password information.
Once you confirm the user/password is valid, then you use cookies to store a session id and keep using the session id from the cookie. If you still want to make sure nobody hijacks your session id, you should keep using SSL in the communication with your server from then on. This second part is pretty much standard even in all these authentication frameworks (they rely on cookies for storing the temporary session token).
Related
Frontend is Vue and my backend is an express rest api that pulls data from mysql. I want to secure both the frontend (login form) and backend api, but without limiting use of the api to just my frontend. I may want to use this api for other projects in the future.
What I'm strugging with is understanding how to have a user log in on the frontend but also give them access to the api without preventing future access to the api from other projects. I know I could set a JWT, but recently there seems to be a lot of "DON'T USE JWT!" articles out there, and I can understand why they might think this. Using cookies and sessions doesn't seem practical either without needing to create a session/cookie for each frontend and backend. Then I thought maybe using cookie/sessions for frontend, and having the frontend be authenticated with an API key to the backend API. This might allow other web applications to access the api while protecting it from unauthorized access.
Apologies for the lack of knowledge and seemingly rambling. I've been stuck on this aspect of my project for a while now. I know it's due to my poverty of knowledge on the subject. Any resources and points in the right direction will be greatly appreciated.
There is nothing wrong with JWTs, though it can depend on the implementation. The simplest way of doing it is just signing the JSON string with a private key. A little more complicated is base64 encoding it, encrypting it and signing only after that with a different key. And ofc. you need to send it through SSL. You need to add expiration time to it. Probably bind it to IP, browser, language, location, etc. too. If you want to revoke it, then you need to maintain a very small global revoked JWT database and remove it after it expired. You can add a JWT verification cache too, which spares you checking the signature for every request and which can be local too. If you want to avoid accessing it from Javascript code and probably leak it with XHR, then add it to a httpOnly cookie, though if you do so, then you need a CSRF token too. So I think all of the security issues are solveable with JWT too.
We need stateless communication between the REST client and the REST service, so if your frontend has a server side REST client, which uses for example JWT or any other method with Auhorization header, then it is perfectly fine from statelessness constraint perspective to do server side sessions with your frontend. As of the constraint itself, statelessness is needed for massive services with countless users global scale where handling server side sessions is an issue on its own, so better to move the stuff to the clients. These are typically social media services, search engines, global webshops, etc. If you have a limited user number, then you probably don't need this feature. Though using server side sessions between REST client and service would violate the statelessness constraint, which means you would not have a REST service. I don't think this is an issue. I mean it would be still a service, just not a REST service, it would work, would not scale as well as a REST service, but if this is what you need and it is simpler for you to implement it securely, then go on.
You can use API keys if you have some sort of revoke mechanism for those too. And keep in mind that API keys are server side stuff, so for mobile clients and in-browser application they are not good for identification, because they can be easily stolen by the users, so don't access your service directly from those with API keys just through a server. Another way is checking IP and using SSL to identify the clients, which is similar to using API keys, just more standard and the secret does not go through the communication channel. It really depends on your needs. If you have 3rd party clients, then you'll need OAuth too and let the users decide if they trust them.
Not sure if this helps.
By far the best thing you can do is adopt OAuth2. It has all the necessary components solve your problem and has ton of implementations.
The issue with JWT is that lots of people get it wrong. inf3rno does a good job accidentally pointing out many of the issues.
I'm currently working on a mobile app that is built primarily with HTML and css, then run with phonegap. Part of the app requires that the user logs in and sync data with a backend. I want it done in such a way that once the user is logged in on their device they will remain logged in until they manually log out; they should only have to enter their information once. I've found some decent information when working with native code, but not so much that applies to my situation.
Right now, I'm not sure how to properly do this in a way that is secure. My first idea was to handle the login normally, then pass back a secret code that is stored both in local storage on the device, as well as in the database under the user that was authenticated with it. On subsequent requests it would pass this and allow access to the user that had a matching secret code. My question is whether this is secure enough to be practical?
I've also done a bit of research and it appears JWT is similar to what I'm looking for? My two concerns for this approach are:
How do I maintain the persistent login with this method.
What prevents someone from spoofing a connection? From what I know there's a secret string that is passed with each request to verify it. But, since the code in my app would be visible to someone who knew how to access it what is to prevent them from learning what the secret is and spoofing a connection?
I assume my questions with JWT are due to me misunderstanding some fundamentals of how it works. If it satisfies what I'm looking to do I'd much rather use a more standardized process like JWT as opposed to writing my own solution.
Am I on the right track with what I'm thinking above or am I way off base?
Your idea is correct and this is how it's usually done. It is a combination of cookie and session concepts. A 'session' is started on the server once the user logs in. The session is identified by a string (e.g. md5 format) and passed back to the client. The string is saved in a cookie on the client, and since cookie info is sent in each HTTP request, the server can assign that request to the session, thus considering your user as logged in. The signout process later basically consists of removing your cookie, and / or sending a request to the server to remove the session object.
In most HTTP server side frameworks there is an API used for sessions, so you don't have to reinvent the wheel. And yes, it is secure enough, as you don't usually base your security on this layer of transport, but rather on a lower layer by introducing https.
I have a JavaScript application.
It's built with jQuery.
It uses $.get() to pull JSON data from a server, and uses the data to load a puzzle.
I want to distribute the JavaScript application to clients, and make it easy for them to install.
I'd like it to simply give them a JavaScript block they can drop into their page, and it will interact with my API.
I'm not passing sensitive data, any my API is protecting the database from SQL injection, etc.
I just want to try to prevent unauthorized use of my API, and I can't think of a way to do that with JavaScript, since anyone with a DOM inspector can scrape any credentials from any variables or can monitor any server traffic POST or GET data...
Would it be possible to authenticate the referrer on the other side?
I know that's not bulletproof, but it's not sensitive data. I just want to reduce the unauthorized use as much as possible..
Any ideas?
note: I know obfuscating an API key or something is futile, I'm wondering what other controls I could put in place other than a traditional key to identify the caller to the API.. I have full control over the API itself so I could do anything on that side of things...
JavaScript authentication has holes
With JavaScript, just about any authentication system is going to have holes, simply because the code runs directly in the browser and can be seen by anyone (as can the network calls). So there are a couple of things you can try, depending on your situation.
IP whitelisting
If you are distributing this application to a small subset of clients, and you know exactly where they will be accessing it from, you could use IP whitelisting. This really is the only way to completely secure the API. However this method is very cumbersome, since with every new client you have to update the API whitelist, and considering what you're talking about here probably not what you're looking for (but I mention it just because it is a possibility).
Access tokens
Another method is access tokens. This is a common method used by sites such as Facebook. There are two methods to do this. One is to just give each client a secret key. You can have the same secret key for everyone, but this is not very secure. Having a different secret key for everyone allows you to not only track usage, but also revoke access privs if necessary.
The first method for access tokens is to just give it inside the JS client. However this means that anyone who looks at the source will be able to access your key, and make requests using it.
The second method is to have the secret key stored somewhere on the SERVER of the website where your client runs. This server can then make a server-to-server call using that key to obtain a temporary session token. People will still be able to access the temporary session token via the front-end, but they will have to access this site first in order to get it (this allows you to pass off responsibility for handling this to the website operator) and the token will eventually expire. However this means there needs to be some server-side code, and the app won't just be a drag and drop thing.
For the method given above you can also look into things like OAuth, to avoid re-inventing the wheel.
Whitelist hard-cap
Another possible thing using IPs is to set a hard-cap on either how often or how much per day a specific IP can hit the whitelist. Though you may run into problems with users who REALLY like the puzzles, this will prevent some of the potential abuse.
I could do with some help on my REST API. I'm writing a Node.js app which is using Express, MongoDB and has Backbone.js on the client side. I've spent the last two days trying to work out all of this and not having much luck. I've already checked out:
Securing a REST API
Securing my REST API with OAuth while still allowing authentication via third party OAuth providers (using DotNetOpenAuth)
http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/
http://tesoriere.com/2011/10/10/node.js-getting-oauth-up-and-working-using-express.js-and-railway.js/
I want to keep my backend and frontend as separate as possible so I thought about using a carefully designed REST API would be good. My thinking is that if I ever get round to developing an iPhone app (or something else like that), it could use the API to access data.
BUT, I want this to be secure. A user has logged into my web app and I want to ensure my API is secure. I read about OAuth, OAuth 2.0, OpenID, Hmac, hashes etc... I want to avoid using external logging in (Facebook/Twitter/etc) I want the registering and logging in to be on my app/server.
...but I'm still confused here. Maybe it's late at night or my brain is just fried, but I could really do with some steps on what to do here. What are the steps for me to create a secure API?
Any help, any information, any examples, steps or anything would be great. Please help!
In order of increasing security / complexity:
Basic HTTP Auth
Many API libraries will let you build this in (Piston in Django for example) or you can let your webserver handle it. Both Nginx and Apache can use server directives to secure a site with a simple b64encoded password. It's not the most secure thing in the world but it is at least a username and password!
If you're using Nginx you can add a section to your host config like so:
auth_basic "Restricted";
auth_basic_user_file /path/to/htpasswd;
(Put it in your location / block)
Docs: http://wiki.nginx.org/HttpAuthBasicModule
You'll need to get the python script to generate that password and put the output into a file: http://trac.edgewall.org/browser/trunk/contrib/htpasswd.py?format=txt
The location of the file doesn't matter too much as long as Nginx has access to it.
HTTPS
Secure the connection from your server to the app, this is the most basic and will prevent man in the middle attacks.
You can do this with Nginx, the docs for it are very comprehensive: http://wiki.nginx.org/HttpSslModule
A self-signed certificate for this would be fine (and free!).
API Keys
These could be in any format you like but they give you the benefit of revoking access should you need to. Possibly not the perfect solution for you if you're developing both ends of the connection. They tend to be used when you have third parties using the API, eg Github.
OAuth
OAuth 2.0 is the one to go with here. While I don't know the underlying workings of the spec it's the defacto standard for most authentication now (Twitter, Facebook, Google, etc.) and there are a ton of libraries and docs to help you get those implemented. That being said, it's usually used to authenticate a user by asking a third party service for the authentication.
Given that you doing the development both ends it would probably be enough to put your API behind Basic HTTP Auth and serve it over HTTPS, especially if you don't want to waste time messing around with OAuth.
Here's a different way of thinking about it:
Let's suppose for a moment that you're not using an API. Your user logs into the app, providing some credentials, and you give a cookie or similar token of some sort to the user, which you use to identify that user has logged in. The user then requests a page containing restricted information (or creating/modifying/deleting it), so you check that this token to ensure that the user is allowed to view that information.
Now, it sounds to me that the only thing you're changing here is the way that information is delivered. Instead of delivering the information as rendered HTML, you're returning the information as JSON and rendering it on the client side. Your AJAX requests to the server will carry that same logged-in token as before, so I suggest just checking that token, and restricting the information down to 'just what the user is allowed to know' in the same way.
Your API is now as secure as your login is - if anyone was to know the token necessary for accessing the api, they would also be logged into the site and have access to all the information anyway. Best bit is, if you've already implemented login, you've not really had to do any more work.
The point of systems such as OAuth is to provide this 'logging in' method, usually from a third party application and as a developer. This would potentially be a good solution for an iPhone app or similar, but that's in the future. Nothing wrong with the API accepting more than one authentication method!
The answers so far do a great job of explaining, but don't give any actual steps. I came across this blog post that goes into great detail about how to create and manage tokens securely with Node + Passport.
http://aleksandrov.ws/2013/09/12/restful-api-with-nodejs-plus-mongodb/
Tips valid for securing any web application
If you want to secure your application, then you should definitely start by using HTTPS instead of HTTP, this ensures a creating secure channel between you & the users that will prevent sniffing the data sent back & forth to the users & will help keep the data exchanged confidential.
You can use JWTs (JSON Web Tokens) to secure RESTful APIs, this has many benefits when compared to the server-side sessions, the benefits are mainly:
1- More scalable, as your API servers will not have to maintain sessions for each user (which can be a big burden when you have many sessions)
2- JWTs are self contained & have the claims which define the user role for example & what he can access & issued at date & expiry date (after which JWT won't be valid)
3- Easier to handle across load-balancers & if you have multiple API servers as you won't have to share session data nor configure server to route the session to same server, whenever a request with a JWT hit any server it can be authenticated & authorized
4- Less pressure on your DB as well as you won't have to constantly store & retrieve session id & data for each request
5- The JWTs can't be tampered with if you use a strong key to sign the JWT, so you can trust the claims in the JWT that is sent with the request without having to check the user session & whether he is authorized or not, you can just check the JWT & then you are all set to know who & what this user can do.
Node.js specific libraries to implement JWTs:
Many libraries provide easy ways to create & validate JWTs, for example: in node.js one of the most popular is jsonwebtoken, also for validating the JWTs you can use the same library or use express-jwt or koa-jwt (if you are using express/koa)
Since REST APIs generally aims to keep the server stateless, so JWTs are more compatible with that concept as each request is sent with Authorization token that is self contained (JWT) without the server having to keep track of user session compared to sessions which make the server stateful so that it remembers the user & his role, however, sessions are also widely used & have their pros, which you can search for if you want.
One important thing to note is that you have to securely deliver the JWT to the client using HTTPS & save it in a secure place (for example in local storage).
You can learn more about JWTs from this link
I need something like a cookie, but I specifically don't want it going back to the server. I call it a "client side session cookie" but any reasonable mechanism would be great.
Basically, I want to store some data encrypted on the server, and have the user type a password into the browser. The browser decrypts the data with the password (or creates and encrypts the data with the password) and the server stores only encrypted data. To keep the data secure on the server, the server should not store and should never receive the password. Ideally there should be a cookie session expiration to clean up.
Of course I need it be available on multiple pages as the user walks through the web site.
The best I can come up with is some sort of iframe mechanism to store the data in javascript variables, but that is ugly. Does anyone have any ideas how to implement something like this?
FWIW, the platform is ASP.NET, but I don't suppose that matters. It needs to support a broad range of browsers, including mobile.
In response to one answer below, let me clarify. My question is not how to achieve the crypto, that isn't a problem. The question is where to store the password so that it is persistent from page to page, but not beyond a session, and in such a way that the server doesn't see it.
You could use JavaScript's localStorage object. The Dive Into HTML5 ebook has an excellent chapter on it. I think the chapter also mentions some possible work-arounds for browsers which to don't support localStorage.
For what you are looking for I would say that javascript is the best you could do.
You can retrieve the encrypted data onto the server and decrypt it using javascript on the client side. No transmission of password, no secret for the user.
It depends which encryption algorithm you are using but there is libraries for that (for example Stanford Javascript Crypto Library)
(but I don't understand why are you talking about cookies)
If you are interested in the storage aspect rather than the cryptography aspect, perhaps you might consider Thomas Frank's session variables