As promised, I am posting the code for all the examples in the article about Drupal and the Internet of Things. Since I figured this could be also a good excuse to actually examplify different approaches to securing these communication channels, I decided to do different strategies for each code example. So here is the disclaimer. These posts (and maybe especially this one) would not necessarily contain the best-practices of establishing a communication channel from your "thing" to your Drupal site. But this is one example, and depending on the use-case, who knows, this might be easiest and most practical for you.
So, the first example we will look at is how to turn on and off your Drupal site with a TV remote control. If you did not read the previous article, or if you did not see the example video, here it is:
Overview of technology and communication flow
This is basically what is happening:
- I click the on/off button on my TV remote.
- A Tessel microcontroller reads the IR signal
- The IR signal is analyzed to see if it indeed is the "on/off" button
- A request is sent to my Drupal site
- The Drupal site has enabled a module that defines an endpoint for toggling the site maintenance mode on and off
- The Drupal site is toggled either on or off (depending on the previous state).
See any potential problems? Good. Let's start at the beginning
Receiving IR and communicating with Drupal
OK, so this is a Drupal blog, and not a microcontroller or javascript blog. I won't go through this in detail here, but the full commented source code is at github. If you want to use it, you would need a tessel board though. If you have that, and want to give it a go, the easiest way to get started is probably to read through the tests. Let's just sum it up in a couple of bullet points, real quick:
- All IR signals are collected by the Tessel. Fun fact: There will be indications of IR signals even when you are not pressing the remote.
- IR signals from the same button are rarely completely identical, so some fuzzing is needed in the identification of a button press
- Figuring out the "signature" of your "off-button" might require some research.
- Configure the code to pass along the config for your site, so that when we know we want to toggle maintenance mode (the correct button is pressed), we send a request to the Drupal site.
Receiving a request to toggle maintenance mode
Now to the obvious problem. If you exposed a URL that would turn the site on and off, what is to stop any random person from just toggling your site status just for the kicks? Here is the part where I want to talk about different methods of authentication. Let us compare this to the actual administration form where you can toggle the maintenance mode. What is to stop people from just using that? Access control. You have to actually log in and have the correct permission (administer site configuration) to be able to see that page. Now, logging in with a micro controller is of course possible, but it is slightly more impractical than for a human. So let's explore our options. In 3 posts, this being the first. Since this is the first one, we will start with the least flexible. But perhaps the most lo-fi and most low-barrier entry. We are going to still use the permission system.
Re-using your browser login from the IR receiver
These paragraphs are included in case someone reading this needs background info about this part. If this seems very obvious, please skip ahead 2 paragraphs
Web apps these days do not require log-ins on each page (that would be very impractical), but actually uses a cookie to indicate you are still trusted to be the same user as when you logged in. So, for example, when I am writing this, it is because I have a session cookie stored in my browser, and this indicates I am authorised to post nodes on this site. So when I request a page, the cookie is passed along with it. We can also do the same passing of a cookie on a micro controller.
Sending fully authenticated requests without a browser
So to figure out how to still be authenticated as an admin user you can use your browser dev tools of your choice. Open a browser where you are logged in as a user allowed to put the site into maintenance mode. Now open your browser dev-tools (for example with Cmd-Alt-I in Chrome on a Mac). In the dev tools there will be a network tab. Keep this active while loading a page you want to get the session cookie from. You can now inspect one of the requests and see what headers your browser passed on to the server. One of these things is the header Cookie. It will include something along the lines of this (it starts with SESS):
SESS51337Tr0lloll110l00l1=acbdef123abc1337H4XX
Since I am a fan of animated gifs, here is the same explanation illustrated:
This is the session cookie for you session as an authenticated user on your site. Since we now know this, we can request the path for the toggle functionality from our microcontroller, passing this cookie along as the header, and toggle the site as we were just accessing it through the browser.
The maintenance_mode_ir module
As promised, I also posted the Drupal part of the code. It is a module for Drupal 8, and can be found on github
So what is happening in that module? It is a very basic module actually mostly generated by the super awesome Drupal console. To again sum it up in bullet points:
- It defines a route in maintenance_mode_ir.routing.yml (example.com/maintenance_mode_ir)
- The route requires the permission "administer site configuration"
- The route controller checks the StateInterface for the current state of maintenance mode, toggles it and returns a JSON response about the new state
- The route (and so the toggling) will never be accessible for anonymous users (unless you give the anonymous users the permission "administer site configuration", in which case you probably have other issues anyway)
- There are also tests to make sure this works as expected
When do you want to use this, and what is the considerations and compromises
Now, your first thought might be: would it not be even simpler to just expose a route where requests would turn the site on and off? We wouldn't need to bother with finding the session cookie, passing that along and so on? Legitimate question and of course true in the sense that it is simpler. But this is really the core of any communications taking place between your "things" and Drupal (or any other backend) - you want to make sure they are secured in some way. Of course being able to toggle the maintenance mode is probably not something you would want to expose anyway, but you should also use some sort of authentication if it only was a monitoring of temperature. Securing it through the access control in Drupal gives you a battle tested foundation for doing this.
Limitations and considerations
This method has some limitations. Say for example you are storing your sessions in a typical cache storage (like redis). Your session will expire at some point. Or, if you are using no persistence for redis, it will just be dropped as soon as redis restarts. Maybe you are limited by your php session lifetime settings. Or maybe you just accidentally log out of the session where you "found" the cookie. Many things can make this authenticated request stop working. But if all you are doing is hooking up a remote control reader to make a video and put on your blog, this will work.
Another thing to consider is the connection of your "thing". Is your site served over a non-secure connection and you are sending requests with your "thing" connected through a public wifi? You might want to reconsider your tactics. Also, keep in mind that if your session is compromised, it is not only the toggling of maintenance mode that is compromised, but the actual administrator user. This might not be the case if we were to use another form of authentication.
Now, the next paragraph presented to you will actually be the comments section. The section where you are encouraged to comment on inconsistencies, forgotten security concerns or praise about well chosen gif animations. Let me just first remind you of the disclaimer in the first paragraph, and the fact that this a serie of posts exploring different forms of device authentications. I would say the main takeaway from this first article is that exposing different aspects of your Drupal site to "the physical world", be it remote controlled maintenance mode or temperature logging, requires you to think about how you want to protect these exposed endpoints. So please do that, enjoy this complementary animated gif (in the category "maintenance"), and then feel free to comment.
dustinw•Thursday, May 7th 2015 (over 9 years ago)
Great example ... but I think it would be better to use the Basic Auth module to secure your route then use sessions ... then you don't need to worry about the session expiring.
Either way you need would need to protect your site with SSL if the requests were going over the public internet.
https://www.drupal.org/docu...
Dustin@PI
eiriksm•Thursday, May 7th 2015 (over 9 years ago)
Hello, and thanks for commenting.
I agree with you 100%. And since you brought it up, here is a spoiler alert: This will be used in part 3 of this series :)
Thanks again for commenting!
Alec Hill•Saturday, May 9th 2015 (over 9 years ago)
Wow this is cool. Thank you so much for sharing this. Super excited about your next posts and trying this stuff out one day myself!
eiriksm•Saturday, May 9th 2015 (over 9 years ago)
Hi Alec!
Thanks for commenting and your encouraging words. That made my day!