0

I have a Rails 4 application. I use devise for authentication and opro for providing oauth2 with my API. All requests are authorized with pundit policies and until now, this setup was totally fine.

Currently, my authorization is always done on a per-user basis. This makes sense, as usually every request is done on behalf of a particular user who is either authenticated in a session or by providing the oauth-token.

The new challenge is: I have certain API-consumers (let me call them devices from now on), whose requests cannot be seen as requests from a particular user. One is an Asterisk Server that can exchange information with the API, another is a GPS Tracking Box that continuously pushes trackpoints to the API.

Thus, I need to authorize certain API-operations on a per-device basis, meaning there is not necessarily a current_user available. Having no current_user however screws up my authorization concept.

I have already considered several approaches to the problem:

  • creating dedicated users for each device and authorizing them to do the specific action
    • pro: does not screw up my authorization scheme
    • contra: would mean to rethink the User-Model, as currently I only have "natural users" that require name, birthday, email, etc
  • creating dedicated controllers with adapted authorization scheme
    • pro: high flexibility
    • contra:
      • authentication for devices required
      • extra API endpoints required, does not feel very DRY

I am searching for a best-practice approach for such a situation. I believe this is not an extra-ordinary problem and there must be good solutions for this out there.

Peter Sorowka
  • 1,036
  • 9
  • 20

1 Answers1

0

You need a separate layer that does the authorization check as well as global attributes called caller_id and caller_type (these are just examples).

You then want to implement a logic e.g.:

  • if caller_type == device and caller_id == ... then
  • if caller_type == user and caller_id == ... then

To do that you can just custom-code your own little class. Alternatively you could use XACML to define your authorization logic. See this blog post which applies XACML to servlets. The same principle could be done for your Rails application.

HTH, David.

David Brossard
  • 13,584
  • 6
  • 55
  • 88
  • 1
    thank you for your suggestions, but let me ask a few details. I considered XACML a while ago, but I felt there was no good rails implementation yet. I therefore implemented authorization with the Pundit gem and this works fine. Concerning the 'separate layer' you mention, do you mean something like a polymorphic user model, e.g. having a generic `User` model and more specific `NaturalUser` and `DeviceUser` and then make my authorization on the generic base class? Or do you suggest adding middleware? – Peter Sorowka Jul 04 '14 at 09:09
  • Regarding the separate layer, I meant separating authZ code from business logic. IF you use the pundit gem, then you are already doing that. Using a generic User class that is then extended makes a lot of sense IMHO. I'm not aware of any RoR XACML implementation but that doesn't matter if you have the means to invoke the XACML engine from Ruby, right? Axiomatics - the vendor I work for - provides an API so that you can call the XACML engine from multiple languages including Ruby. – David Brossard Jul 08 '14 at 14:01