Real Time Rails 4: Using Server-Sent Events with Authy OneTouch
Server-Sent Events (SSE) are real-time events sent from a server and received by a browser, perfect for updating the front end when a server receives a webhook. We’re going to look at how to use SSE to implement Authy OneTouch using Rails 4.
Our end result should look a bit like this:
Two-factor authentication usually means copying a bunch of numbers from your phone to the place you’re trying to log in. Authy OneTouch is a more user-friendly version of two-factor authentication. As you can see above, the user just needs to accept the authentication attempt and they are logged in.
On the backend, Authy sends a webhook to the application with the result of the authentication request. The application can then log the user in and choose how it updates the front end. Check out our tutorial on how to get started with Authy OneTouch and Rails for more detail on how it all works.
Real-Time Rails 4?
You might be thinking that Rails 5 is finally bringing real-time action to the Ruby world with Action Cable. If you are then you probably missed that Rails 4 included
ActionController::Live, a means of streaming data from a Rails in real-time. Connect this up to the
EventSource API in browsers and we have a full implementation of Server-Sent Events that we can use to send data from the server to the browser in real-time.
The tutorial for Authy that I mentioned earlier actually implements the OneTouch flow by polling the server for updates. As polling can be inefficient and result in many unnecessary requests to our server let’s replace it with SSE.
To follow this post and implement SSE in Rails you’re going to need a few things:installed
- Ruby and Bundler installed
- PostgreSQL, we’re going to be using the publish-subscribe feature to trigger events
- ngrok, to help us test webhooks to our locally running application
- A Twilio account so that you can get an Authy API key, sign up for free here
- A smartphone with the Authy app so that you can use OneTouch, you can download it for iOS or Android
- A browser other than Internet Explorer/Edge, which doesn’t yet support SSE but can be polyfilled
Once you’ve got all that, we’ll get the tutorial application set up.
The best instructions for running the tutorial are available in the project README. Follow the instructions all the way through until the application is running locally, you have enabled OneTouch on your Authy application and set the webhook endpoint to your ngrok URL.
Once you’ve followed the instructions you should be able to visit your application at http://localhost:3000 and sign up as a new user. Logout and log back in again and you will be presented with the following two-factor authentication flow.
Let’s replace that polling mechanism with Server-Sent Events.
Adding Server-Sent Events
In order to run real-time features like SSE (and Action Cable when Rails 5 is released) it is recommended to use a threaded server, like Puma. The project currently uses Unicorn so we need to update that.
Open up the
Gemfile and change
Updating The Controller
Next, we need to set up a streaming endpoint on our Rails server. Enable streaming capabilities for the existing controller by opening
app/controllers/authy_controller.rb and including the
one_touch_status action, create a
Let’s update this now to push real data from the server to the front end.
Pushing real data with PostgreSQL pub-sub
In the tutorial application when a user approves or denies the authentication request, the Authy webhook hits the
/authy/callback endpoint which runs the
callback action in the
AuthyController. This then updates the user with the status from the parameter of the webhook.
In order to push that status to the client, we’d like to listen for that update whilst we have a live connection open to our streaming endpoint. Because we are using PostgreSQL in this example we can use its publish-subscribe feature. If you are using a different database without pub-sub you could achieve the same result by using something else like Redis to fill the gap.
PostgreSQL uses the keywords
LISTEN to publish and subscribe to events respectively. Active Record doesn’t directly support these keywords, but we can execute them using the database connection anyway.
We’ll add the notification code to the
User model so open up
app/models/user.rb. First, we want to send a notification when the user is saved and their
authy_status has changed.
We can run the notification method every time the user model is saved using an Active Record callback.
checkForOneTouch function with the following:
Rails 4 does Real-Time
Rails 5 and Action Cable might not be released just yet, but Rails 4 can still perform some pretty sweet real-time manoeuvres. This works really well for server based updates as we’ve seen with Authy OneTouch. It would also work for live updating call statuses on a dashboard like Sam showed using Socket.io and React or creating a dashboard for conference events like Dominik did using Socket.io and Angular.
Server-Sent Events just provide one-way real-time events, though. Action Cable will bring two-way real-time streams to Rails for more complicated interactions, like a chat room. Of course, you don’t have to build all that complexity yourself if you use IP Messaging 😉
Do you like the look of SSE in Rails or are you going to be holding out for Action Cable? Let me know in the comments below, give me a shout on Twitter at@philnash or drop me an email at [email protected].