Grape authorization

882 views
Skip to first unread message

Joshua Weaver

unread,
Feb 19, 2013, 3:02:27 PM2/19/13
to ruby-...@googlegroups.com

I'm attempting to create a restful, json api in ruby - so I'm using grape (https://github.com/intridea/grape) inside of Rack. I'm not using Rails for this project, so cancan, sorcery, etc... don't seem to be the best options. Plus, I'd hate to mix in a bunch of imperative logic into grape's declarative DSL.

While grape has built in authentication support, I do not see anything about authorization. It seems like this would be a common enough use case that this road would have been traveled before, but after some pretty thorough digging in google and the grape codebase itself I have turned up nothing.

Has anyone implemented something like this for their project in grape? What did you use?

Daniel Doubrovkine

unread,
Feb 19, 2013, 5:08:35 PM2/19/13
to ruby-...@googlegroups.com
We're using CanCan here without any kind of resourceful authorization logic at API level.

--
You received this message because you are subscribed to the Google Groups "Grape Framework Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-grape+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--

dB. | Moscow - Geneva - Seattle - New York
dblock.org - @dblockdotorg

Joshua Weaver

unread,
Feb 19, 2013, 6:09:06 PM2/19/13
to ruby-...@googlegroups.com
Where do you put your authorization logic? How do you communicate that back up through the API?
If you request OPTIONS on a resource, do you get write operations (e.g. PUT) only to send a 403 when a put is attempted and fails authorization later?
_josh

Michael Bleigh

unread,
Feb 19, 2013, 6:31:17 PM2/19/13
to ruby-...@googlegroups.com
I would love to see an extension to Grape with some resource-level authorization code (in general I would love to see Grape become much more modular).

In Divshot we have very simple authorization levels so I've just done this:

class MainAPI < Grape::API
  mount PublicAPI # publicly accessible resources

  helpers do
    def current_user
      # ...
    end

    def admin?
      # ...
    end
  end

  before{ error "Must be logged in.", 401 unless current_user }

  mount UserProtectedAPI

  before{ error "Must be admin.", 401 unless admin? }

  mount AdminProtectedAPI  
end

Simplified, but that's the general idea.

Daniel Doubrovkine

unread,
Feb 19, 2013, 8:12:22 PM2/19/13
to ruby-...@googlegroups.com
We basically do http://code.dblock.org/grape-api-authentication-w-devise for authentication, then explicitly check for authorization via a helper method on user. I am not saying "it's awesome" :)

      put ":id" do
        authenticated_user
        artwork = Artwork.find(params[:id])
        error!('Artwork Not Found', 404) unless artwork
        error!('Forbidden', 403) unless current_user.has_authorization_to?(:update, artwork)
        ...
        artwork.update_with_validation!(params)
        artwork.as_json({properties: :all})
      end

has_authorization_to? is 

  def has_authorization_to?(action, model_or_instance)
    Permissions.new(self).can? action.to_sym, model_or_instance
  end

and Permissions is CanCan:

class Permissions
  include CanCan::Ability

  def initialize(user)
    ...
  end
end

haven't done anything with OPTIONS

Daniel Doubrovkine

unread,
Feb 19, 2013, 8:14:50 PM2/19/13
to ruby-...@googlegroups.com
In my experience the kind of division between endpoints that can or cannot be accessed by a certain type of user is oversimplifying the real world and won't get much use. And it gets much, much harder with caching.

Joshua Weaver

unread,
Feb 20, 2013, 11:17:09 AM2/20/13
to ruby-...@googlegroups.com
Thanks for the information; it's helpful. I'm considering the possibility of either writing an authorization framework for grape, or just going with Grape in Rails and using one of the many Rails authz frameworks at this point.

I'm not sure if it warrants another thread, but I'm curious if there is an idiomatic way to get a route from an entity - for example, I have endpoint for sites, and each site contains many users. I'd like to list those user resources in the site, but I don't want to hardcode a path that could change depending on version, schema changes, etc...

Daniel Doubrovkine

unread,
Feb 20, 2013, 1:19:18 PM2/20/13
to ruby-...@googlegroups.com
`API.routes` is the entire collection of routes. And `route` from within the API can give you the current route.

See "Describing and Inspecting the API" in the README for details.
Reply all
Reply to author
Forward
0 new messages