Part 1, Comments App: Overview
I started this blog with this nice Jekyll-Theme and wanted to host it myself rather than hosting it on github pages. But what I missed so far was a comments section. I initially searched for already implemented solutions and found following:
- Paid comments services like Disqus1
- Some projects with comments over github-issues
- Some open-source apps. But unfortunately, they weren’t maintained anymore and I was not comfortable with the technology they used.
The first two variants I didn’t like, because of the costs and / or I don’t own the data.So I thought just do it yourself… and if so do it exactly as you like and do not try to rebuild something. And last but not least make it fun to build and use.
I will make a little series out of it, if interested check out the following posts as well:
- Part 1, Comments App: Overview
- Part 2, Comments App: Proof of Work
- Part 3, Comments App: Admin and Reply
- Part 4, Comments App: Integration
- Test the Comments App
I try to summarize the general thoughts. Please let me know in the comments down below, if more details are desired.
This app will provide an API and an exemplary integration to provide a comments section to a simple static website. I developed it for two jekyll blogs, but it is easily integrated in any blog.
The cool thing about this app is, that users do not need to register to any services. They can just post comments and decide how anonymous they want to be by choosing their username. For security reasons I implemented some protection in form of hash quizes (similar to the proof of work concept with bitcoin) and simple ip blocking on certain conditions. More about that later …
You can get the latest image from docker-hub: https://hub.docker.com/r/toubivankenoubi/comments
Everything is open-source and I invite everybody to contribute: https://github.com/coffeeflash/Comments
Here a little preview, but of course I invite you to comment this very blog post down below and test it yourself. Or if you just want to write some nonsense to simply test it; Test the Comments App.
Before I started or a little after I wrote down some requirements:
- The user should not have to register somewhere. Not on the blog-website itself, neither on external services like google, facebook, github, etc.
- The service should have an easy api, which can be integrated with some simple ajax requests. The app should be easily deployable.
- To show the existent comments, related to a page, is a public api call, without any authentication.
- Posting comments should be protected as good as possible. Following attacks are considered:
- Code injections of any sort
First ideas to cover these requirements:
- Easy, just do not implement username/password-like authentication… For security implications, see 4.
- I am used to building spring boot apps, which is supporting this requirement. For an easy deploy, I will provide up-to-date container images on a registry.
- Public api endpoint
- That’s the point, where it gets interesting:
- DOS: Ip blocking after a certain burst of requests (Might be unfair for users, which access the website over the same ip-address). Let me konow if you have a better idea.
- DDOS (and DOS): to post a comment, one has to solve a hash puzzle, which needs a couple of seconds to solve (depends on the client device, which could also be a little unfair…).
- Covered by Spring Boot and (hopefully) proper implementation, additionally only allow following special characters:
"(", ")" ,"[" ,"]" ,";" ,",", "!", "?", ":", ".", "-"
With this call a client (e.g. a blog post) gets comments. It needs two things to identify the comments.
The–> removed, client provides the source only.
refererneeds to be declared in the request header (not default in Postamn, if one is testing the api…)
sourceas a request parameter. For example the title or the url of a blog post.
The comments-service provides a certain number of random quiz strings with a certain security level
(# of leading bytes to be 0), which the client has to hash in exactly that way.
As an alternative to give the client an id of the quiz, map the quiz to the referrer. –>
not a good way, if users come from the same ip-address…
a random quiz string looks like: OfMNU4sZ80CNMbctZU2t0sMLIccAkrUh
The quiz gets stored in memory for a certain amount of time (e.g. 30 seconds), depending on the complexity of the hash puzzle. The storage key is the quiz string.
The client provides following in his request-body:
- quiz-id (aka storage key for the service to find it in the memory) and a solution (calculated nonce’s)
- identifier to match the comment to the blog-post (url of the post).
- a username and finally the comment itself.
Following environment variables can be set to fit your needs the best as possible:
environment: IP_BLOCK_TIME: 900 QUIZ_COUNT: 5 QUIZ_VALIDITY_SECONDS: 120 QUIZ_COMPLEXITY: 2 ADMIN_NAME: the_bloggers_name SPRING_DATA_MONGODB_HOST: mongo SPRING_DATA_MONGODB_DATABASE: comments SPRING_DATA_MONGODB_AUTHENTICATION_DATABASE: admin SPRING_DATA_MONGODB_USERNAME: root SPRING_DATA_MONGODB_PASSWORD: pleaseChangeMe SPRING_SECURITY_USER_NAME: user SPRING_SECURITY_USER_PASSWORD: PleaseChangeMe
QUIZ_COMPLEXITY is the number of zero bytes needed to solve the quiz. I strongly recommend leave it 2. 3 takes
much longer in this single threaded client scenario. If you want to make it a bit harder, just increase the
If you increase
QUIZ_COUNT, you should also test if the time suffices on your target client
SPRING_SECURITY_USER_PASSWORD are for the http basic authentication,
ADMIN_NAME is just the blogger’s name, which can be shown with the reply text.
See also Part 3, Comments App: Admin and Reply for the values not discussed here, which are needed for the administration interface.
reply function, should appear underneath a comment. Only reply on comment as an admin / blogger, not further nesting…–> implemented administrator interface (needed for reply function)–> implemented fine tune quiz complexity (bit-wise instead byte-wise)–> solved with multiple quizes.
- allow other databases (mariadb, postgres eventually…)
- provide easier integration possibilities in blogs.