Using default Rails authentication with a Grape API
Recently, I was working on a Chrome extension for a web app where I wanted to share the login state between the extension and the web app.
Generally you'd roll with a token-based authentication system or relying on API keys, but neither of those approaches are acceptable if you want to roll out something real quick.
(Sidenote: There's a lot of hype around "stateless" authentication these days, but 1. you likely don't need it, and 2. If you want to be able to revoke a token, say if it gets leaked, you will need to maintain a blacklist, which is, guess what - state.)
To integrate our Grape API with the default cookie/session-based Rails authentication system, we will be using Warden. It is a really nice drop-in authentication middleware which doesn't change your application in any way unless you explicitly do so, and if you're using Devise, you're already using Warden.
We will basically be implementing a Grape helper method to take care of this. This is what my directory structure looks like:
app/controllers/api ├── base.rb └── v1 ├── base.rb ├── lists.rb ├── defaults.rb └── helpers.rb
helpers.rb is where we'll be defining the authentication helper.
module API module V1 module Helpers extend Grape::API::Helpers def current_user warden = env["warden"] @current_user ||= warden.authenticate end end end end
defaults.rb I added the following code:
But you could add it inside
base.rb as well.
Inside of all the files where I'm defining API resources, I include the following code:
module API module V1 class Lists < Grape::API include API::V1::Defaults end end end
And then inside of any route I can simply access
current_user, and as long as the API request included the Rails session cookie,
current_user will be set to the correct user.