[AngularJS] Common Pitfalls
AngularJS makes it very easy for developers to get in to some dangerous territory. Here's some common things that I see when I assess websites using AngularJS, regardless of the backend:
- Lack of server-side session validation
- Lack of server-side input validation
- Decoupling the frontend from the backend and forgetting things like output encoding
Lack of server-side session validation
The near-universal pitfall I see is that the frontend handles all of the session checking and routing, but I can just call the backend endpoints and be anybody I want to be. AngularJS also has this cookie thing it does with defining the user permissions in the cookie. Don't do that. I can manipulate that cookie and send it to the server.
To avoid this, do your session checks server-side.
Lack of server-side input validation
Another common pitfall I see is that AngularJS gives a lot of nice tools to developers to do things like routing, input validation, all in a nice, rich UI. However, those input validations aren't done server-side.
To avoid this, enforce validation checks on both sides.
Decoupling frontend and backend
As mentioned, AngularJS gives nice things to developers. However, when the backend and frontend are decoupled for things like UI generation, routing, it is easy for developers to forget where the data is coming from and forget to properly output encode. AngularJS does do some things to help you, and newer versions target output encoding specifically, but ensure that you do it correctly.
[Spring] Common Pitfalls
For the most part, the advice I give is independent of any framework chosen. However, the backend is much larger, and I could write a book. So instead, I'll try to limit it a bit, especially given the question.
Ensure the framework is properly configured. Frameworks like Spring come with out-of-the-box with developer-friendly tools. In the case of Spring, be sure to read up on the production-ready endpoints, for example.
Maintain your patches. No framework is without bugs, and Spring is no exception, having experienced significant security vulnerabilities in the past. Keep your pom/gradle versions up-to-date and you'll be fine.
Review deployment practices. While this is probably starting to get outside the bounds of your question, I want to bring it up because it is part of the learning process.
Encryption
With that all said, now the encryption. Unless you are doing something where the user should be the only one with knowledge of the key, doing encryption in JavaScript is highly discourage.
With user passwords specifically, industry standard, and recommended approach, is TLS. Anybody between the browser and your server will not see or be able to manipulate the data. TLS certificates are free these days, so there's really no good reason not to if it is on the internet. Without knowledge of what kind of data you want to encrypt, I can only give you some common pitfalls of doing something like this in the browser:
- Key generation, expiry, storage, and revocation
- Ciphertext storage
- Encryption algorithm
Keys
Putting aside for the moment your explanation of wanting to use the user password, encryption requires key management. You need to handle generation, storage, expiry, and revocation. This means that you need to have sufficient entropy to generate the key, decide how to handle the key once it is generated, how to handle the key when it approaches expiry and once it has expired, and when the user decides they want to change their key.
In your case, this actually becomes a little more difficult, because now you have to build functionality that'll rotate the keys when they change their password. Otherwise they'll lose access to their old data.
Ciphertext storage
Now that you have the key management, how and where do you store the ciphertext? This becomes a question that matters more for the data you want to encrypt.
Encryption algorithm
Inevitably, you'll need to chose how you want to encrypt the data. Do you use symmetric or asymmetric keys (your stated use case is symmetric)? Now you need to choose algorithm and mode of operation. And randomly generating an IV.
Conclusion
Engineering a solution that can handle encryption on the frontend safely is hard. Really hard. A lot more difficult than handling it on the backend. There are legitimate reasons for doing the encryption on the frontend, but since this is a learning project, I'd encourage you to start on the backend and then work towards the frontend.
There's a lot in this area that I haven't covered and can't cover here for space reasons, and without knowing much more about your objective. In my professional line of work, questions I'd typically start with include:
- What data are you trying to protect?
- Who are you trying to protect it from?
- Are you prepared to handle the unique difficulties on the frontend?
This isn't to discourage you, as there are legitimate reasons for doing this encryption on the frontend. But it is hard to get right, and using the user's password has additional complexities that need to be solved for, some of which I mentioned above.