{grape} authorization
Asked Answered
M

3

12

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?

Martimartial answered 19/2, 2013 at 19:56 Comment(0)
D
8

This may be a little too late, but anyway. I'd recommend you use Pundit for authorization, it's deadly simple. To use it in your Grape API endpoints, you would need to include Pundit helpers:

class API < Grape::API
  format :json

  helpers Pundit
  helpers do
    def current_user
      resource_owner
    end
  end

  mount FoosAPI
end

Now in you API endpoints, you should be able to use authorize foo, action? as you would always do in Rails controllers:

class FoosAPI < Grape::API
  get ':id' do
    foo = Foo.find(params[:id])
    authorize foo, :show?
    present foo, with: FooEntity
  end
end

Hope it helps!

Dough answered 26/6, 2015 at 3:56 Comment(2)
Hey bud thanks, just one thing the second param of the authorize method is actually a symbol authorize :foo, :show? The first param can be a symbol, name of the class or an instance of the classNoemi
@JGonzalezD: Nice catch, fixed it. Thanks!Dough
F
1

I thought I can give short comment on this, but the field is to short, sorry if it will not be right answer but:

You mentioned sorcery - I think it is authentication system and got nothing to do with an authorization. (I do not know sorcery gem implementation - just repeating statement from documentation and assuming that description enumerates such systems it replaces and it is valid definition). I guess it is just mistake.

Fundamental question you should ask yourself is...

How much role-based system do you develop? I think if this is only matter of public/private/admin roles probably you should consider just moving it to different APIs.

That can be cumbersome in some circumstances but worth a try for not complicated none additive roles. Simple mount in grape will solve the problem OOTB.

Real problem is if you think about some expandable/dynamic role system or you want to be just DRY. That can be painful ;-). I think Rayan's Bytes cancan gem implementation should help you understand how such problem can be solved on higher abstract level. For particular (without higher abstraction - such as dynamic roles) implementation it should be fine to just use currently given helpers from grape and delegate their responsibilities to model (basic usage).

helpers do
  def current_user
    @current_user ||= User.authorize!(env)
  end

  def authenticate!
    error!('401 Unauthorized', 401) unless current_user
  end
end

so all the story is about how to implement User.authorize!(env) and I believe that should be done in your model and depends strictly on your needs.

Frohman answered 21/2, 2013 at 19:31 Comment(0)
S
1

I don't know whether my answer is in time for you. I recently have the same problem with the Grape and authorization in a Rails4 project. And after trying, I found out a way for this. In my project, I'm using the pundit for authorization, it asks me to create a policy folder, and create the authorize rules for each Model, each rule is a Ruby class, something like this(from pundit Github page)

class PostPolicy < ApplicationPolicy
  def update?
    user.admin? or not record.published?
  end
end

then in the Grape API, I just use this class for the authorization, code like this:

desc "hide a post"
post :hide do
  authenticate!
  error!( "user unauthorized for this" ) unless PostPolicy.new(current_user, @post).hide_post?
  @post.update hidden: true
  { hidden: @post.hidden }
end

the authenticate! and current_user helpers are customized helpers. By this way, I can reuse the authorize rules created when developing website parts.

This works for me. Hope the Pundit way can solve your problems for Grape authorization

Smithereens answered 17/11, 2014 at 16:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.