Authorize objects?

67 views
Skip to first unread message

Rob Nagler

unread,
Aug 18, 2015, 7:23:24 AM8/18/15
to Crossbar
I've been trying to understand how you would authorize a user for a particular object. It seems that only verbs can be checked with application logic.

The problem is that user X may have privileges to call A on object P but not object Q. 

I see how I could possibly hack this in the callee by requesting details.caller and then get the session details which would give the authid, which then could be looked up against a permissions db.
(Unfortunately, this doubles the crossbar call overhead.) However, this seems really awkward as each callee would have to do this manually. There's no hook for this in crossbar. Ideally, authorize would also get the arguments to the call so that an application could have a standard argument in kwargs for say "uri object". An alternative would be to allow dynamic uri registering/routing, which I don't see that crossbar allows.

Thanks,
Rob

Alexander Gödde

unread,
Aug 21, 2015, 7:22:17 AM8/21/15
to Crossbar
Hi Rob!

I'm having trouble understanding your usage scenario. Could you be a bit more specific about what you want to do?

Regards,

Alex

Rob Nagler

unread,
Aug 21, 2015, 9:10:11 AM8/21/15
to Crossbar
Good Morning, Alex,

Sorry I wasn't clear.

Alice is authorized to call read_account() on account id 123. Bob is authorized to read_account() on account 456. 

How can Crossbar ensure that Alice does not read_account() on 456 in WAMP? 

I understand that I can write this code myself as follows:

1) the caller passes disclose_me
2) the callee adds "details" to args read_account
3) read_account validates that details.caller is not None
4) read_account calls wamp.session.get with details.caller
5) read_account tests if (session.authid, account_id) is authorized

This is both a lot of boilerplate on every call and incurs another round trip (4) to the dealer.

All applications I write work this way on every call.

Rob

Tobias Oberstein

unread,
Aug 21, 2015, 9:34:08 AM8/21/15
to cross...@googlegroups.com
Hi Rob,

Am 21.08.2015 um 15:10 schrieb Rob Nagler:
> Good Morning, Alex,
>
> Sorry I wasn't clear.
>
> Alice is authorized to call read_account() on account id 123. Bob is
> authorized to read_account() on account 456.

This is going beyond dynamic authorization which works on the basis of
URI and WAMP action.

What you describe necessarily means looking into the application payload.

Essentially, it is application payload based authorization.

On the other hand: why not make the account ID part of the URI?

>
> How can Crossbar ensure that Alice does not read_account() on 456 in WAMP?

It doesn't and it won't. It would be against a fundamental design
paradigm we adhere strictly to: WAMP routers MUST NOT contain
application logic.

>
> I understand that I can write this code myself as follows:
>
> 1) the caller passes disclose_me
> 2) the callee adds "details" to args read_account
> 3) read_account validates that details.caller is not None
> 4) read_account calls wamp.session.get with details.caller
> 5) read_account tests if (session.authid, account_id) is authorized
>
> This is both a lot of boilerplate on every call and incurs another round
> trip (4) to the dealer.

That's how it works.

I am open to discuss ways to remove the additional roundtrip in (4) - in
fact, that was once working without that roundtrip, in that CB would
provide all the details to the invoked procedure: not only session ID,
but auth role and all that.

However, the downside of that is a lot of additional info (which doesn't
change) on each and every call.

As indicated above, we won't extend CB to do app payload based
authorization - in fact, that's not in the WAMP spec, and I'd be against
adding it there in the first place also.

>
> All applications I write work this way on every call.
>
> Rob

Cheers,
/Tobias

>
> --
> You received this message because you are subscribed to the Google
> Groups "Crossbar" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to crossbario+...@googlegroups.com
> <mailto:crossbario+...@googlegroups.com>.
> To post to this group, send email to cross...@googlegroups.com
> <mailto:cross...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/crossbario/c0adc510-1723-4c17-9b4a-a8ae93e57b9d%40googlegroups.com
> <https://groups.google.com/d/msgid/crossbario/c0adc510-1723-4c17-9b4a-a8ae93e57b9d%40googlegroups.com?utm_medium=email&utm_source=footer>.
> For more options, visit https://groups.google.com/d/optout.

Rob Nagler

unread,
Aug 21, 2015, 10:49:22 AM8/21/15
to Crossbar
Howdy Tobias,

Thanks for the quick response.

> What you describe necessarily means looking into the application payload. 

One could argue ad infinitum about the difference between "application" and "framework". I have a friend that says that anything about socket.write is application payload. WAMP is an application messaging protocol so it's goal, I believe, is to do things that all web applications need to do. The scenario I described is in every non-trivial application.

It seems to me authorization of verbs independent of the objects they operate on leads to security holes like the Citibank URI hack:


> On the other hand: why not make the account ID part of the URI? 

This moves around the code, but doesn't change the number of roundtrips per call or the amount of code the application programmer has to write.

This brings up other questions:

* Does the authorizer have access to the callee's args?
* How can the authorizer pass state to the callee, e.g. the already parsed URI?

Thanks,
Rob

Andrew Eddie

unread,
Aug 26, 2015, 9:54:04 PM8/26/15
to Crossbar
On Saturday, 22 August 2015 00:49:22 UTC+10, Rob Nagler wrote:
* Does the authorizer have access to the callee's args?

If you mean the dynamic authorisation end-point, no, it doesn't. For an RPC, you need to do the authorisation check in the end-point being called (I don't use dynamic authorisation now at all), but that also requires that the client is calling it with { disclose_me: true }. It's [relatively] easy to then run the uri, authid, selected arguments or kwargs (and perhaps the authrole) through any sort of authorisation strategy pattern (after you've looked up the session meta).

In pseudocode, my pattern kinda looks like this:

var myAction = action_making_factory();

session.register(function (args, kwargs, detail) {
  // Caller must have `disclose_me` option set to `true`.
  session.call('wamp.session.get', details.caller)
    .then(function (sessionMeta) {
      // Done with WAMP stuff. Hand over control to my framework.
      return myAction.authorise(sessionMeta, args, kwargs, details)
        .then(function () {
          // Authorisation passed, now do what we gotta do.
          return action.invoke(sessionMeta, args, kwargs, details);
        });
    })
    .catch(function (err) {
      // Catch authorisation or other errors here.
      session.log(err);
      throw err;
    });
});


Regards,
Andrew Eddie

Rob Nagler

unread,
Aug 27, 2015, 12:51:57 AM8/27/15
to Crossbar
Hi Andrew,

Thanks for the pseudo-code. It's quite complicated, unfortunately.

I'll give my $.02 on why this approach is problematic below. I hope this is helpful...

When the application programmer hand codes authorization, security holes pop up in unexpected places. For example, the code "throw err" above is problematic: It exposes an internal problem with authorization. Crossbar returns such exceptions literally to the client, e.g.

add err: {"error":"wamp.error.authorization_failed","args":["failed to authorize session for calling procedure 'com.example.add': ApplicationError('wamp.error.runtime_error', args = ('DETAILS OF THE INTERNAL EXCEPTION EXPOSED HERE',), kwargs = {})"],"kwargs":{}}

Another issue is that increasing the call overhead worsens denial of service attacks. It is much better if the front-end (Crossbar) denies the service. The more that that application has to do, the more likely an attacker will find ways to penetrate the system.

In general, the default authorization should be "no", not "yes". Without integrated authentication/authorization policies built into the framework, you end up having to ensure that all endpoints assert the validity of the user's role against allowed roles, even if that role is "anonymous". As I understand Crossbar, it means I have to write code which traps all requests. That basically requires a centralized dispatcher through which all requests pass. That's a lot of duplicate effort on the part of all the developers who might want to use Crossbar.

Rob

Andrew Eddie

unread,
Aug 27, 2015, 5:15:52 AM8/27/15
to cross...@googlegroups.com
On 27 August 2015 at 14:51, Rob Nagler <> wrote:
> Hi Andrew,
>
> Thanks for the pseudo-code. It's quite complicated, unfortunately.

It depends on what you are trying to achieve. If you don't want to use
dynamic authorisation, these are the steps you can include:

1. You must register the procedure to be called.
2. If you want information about the caller, you must call the session
meta end-point.
3. You must have your business logic authorise the request.
4. You must handle the request and provide a response.

> When the application programmer hand codes authorization, security holes pop
> up in unexpected places. For example, the code "throw err" above is
> problematic: It exposes an internal problem with authorization. Crossbar
> returns such exceptions literally to the client, e.g.
>
> add err: {"error":"wamp.error.authorization_failed","args":["failed to
> authorize session for calling procedure 'com.example.add':
> ApplicationError('wamp.error.runtime_error', args = ('DETAILS OF THE
> INTERNAL EXCEPTION EXPOSED HERE',), kwargs = {})"],"kwargs":{}}

That's a fair comment, except that the snippet was not intended to
show all of that sort of thing. I dumb the error down before returning
it.

> Another issue is that increasing the call overhead worsens denial of service
> attacks. It is much better if the front-end (Crossbar) denies the service.

Perhaps, but that would require you to compile a plugin or something
into Crossbar itself to be able to do all that.

> The more that that application has to do, the more likely an attacker will
> find ways to penetrate the system.

I don't think that's a reasonable case to make because shifting code
from one place to another doesn't necessarily make it more secure. You
might be lucky, you might not.

> In general, the default authorization should be "no", not "yes".

It is (see Static Authorisation in the docs).

> Without
> integrated authentication/authorization policies built into the framework,

Into the Crossbar framework??

> you end up having to ensure that all endpoints assert the validity of the
> user's role against allowed roles, even if that role is "anonymous".
> As I understand Crossbar, it means I have to write code which traps all requests.
> That basically requires a centralized dispatcher through which all requests
> pass. That's a lot of duplicate effort on the part of all the developers who
> might want to use Crossbar.

I'm not totally clear on what you are suggesting to do, but you
wouldn't do that.

Regards,
Andrew Eddie

Tobias Oberstein

unread,
Aug 27, 2015, 5:41:16 AM8/27/15
to Crossbar

> Does the authorizer have access to the callee's args?

No


> How can the authorizer pass state to the callee, e.g. the already parsed URI?

It can't

Rob Nagler

unread,
Aug 27, 2015, 10:40:27 AM8/27/15
to Crossbar
On Thursday, August 27, 2015 at 3:15:52 AM UTC-6, Andrew Eddie wrote:
That's a fair comment, except that the snippet was not intended to
show all of that sort of thing. I dumb the error down before returning
it.

Sorry for misunderstanding your intent.

 
I don't think that's a reasonable case to make because shifting code
from one place to another doesn't necessarily make it more secure. You
might be lucky, you might not.

I'm not discussing shifting code, but sharing and reusing a common and necessary implementation of authorization across all practical distributed applications.
 

> In general, the default authorization should be "no", not "yes".

It is (see Static Authorisation in the docs).

Subject-verb authorization is insufficient for any practical application.
 

> Without
> integrated authentication/authorization policies built into the framework,

Into the Crossbar framework??

Security needs to be written into the framework, not bolted on.
 

> you end up having to ensure that all endpoints assert the validity of the
> user's role against allowed roles, even if that role is "anonymous".
> As I understand Crossbar, it means I have to write code which traps all requests.
> That basically requires a centralized dispatcher through which all requests
> pass. That's a lot of duplicate effort on the part of all the developers who
> might want to use Crossbar.

I'm not totally clear on what you are suggesting to do, but you
wouldn't do that.

This is where we disagree. The creators of Unix designed authentication and subject-verb-object authorization into the kernel in 1970. Windows, OTOH, did not have a security model at its core and has been struggling ever since.

It seems reasonable to expect at least this level of security in frameworks in 2015. Verb-only security is no security at all. The framework has to restrict which file to write to, not just allowing the user to write to any file. 

When I first read about Crossbar/WAMP, I wrote an internal memo saying I think I finally found a reasonable framework. It doesn't do much, but it does quite a bit more than many frameworks out there. Without subject-verb-object authorization, it is losing its appeal. 

Rob

Tobias Oberstein

unread,
Aug 27, 2015, 11:07:26 AM8/27/15
to cross...@googlegroups.com
> does quite a bit more than many frameworks out there. Without
> subject-verb-object authorization, it is losing its appeal.

WAMP does subject-verb-object-based authorization:

subject: caller/publisher/.. session that originates the action
verb: WAMP action (one of 4)
object: The URI the originator want to act on

Dynamic authorizers get all 3 bits of info.

Cheers,
/Tobias

Tobias Oberstein

unread,
Aug 27, 2015, 11:18:02 AM8/27/15
to cross...@googlegroups.com
> Security needs to be written into the framework, not bolted on.
>
>
> > you end up having to ensure that all endpoints assert the
> validity of the
> > user's role against allowed roles, even if that role is "anonymous".
> > As I understand Crossbar, it means I have to write code which
> traps all requests.
> > That basically requires a centralized dispatcher through which
> all requests
> > pass. That's a lot of duplicate effort on the part of all the
> developers who
> > might want to use Crossbar.

I don't know what above would mean exactly, but fact is, you can have
subject-verb-object based authorization in CB both statically defined
(which means you don't have to write any code, but just "rules"), or you
can have a dynamic authorizer, which is code written by you which is
called by CB to authorize a WAMP action. You can do any kind of
authorization in such dynamic authorizers.

Dynamic authorizers can be written in any WAMP support language, and can
talk over any CB supported transport.

E.g. you can have your authorizer be a Java piece of code, while the
rest of your system is in X.

If you write a dynamic authorizer in Python/Twisted, then it can be run
inside the same process as a CB router. It'll be just a regular function
call.

If it runs out-of-process, you can still have it over Unix domain
socket, which means the overhead and additional roundtrip is very small.

Actual authorization code is NOT framework code, as it depends on app
design. Hence, authorization code must either by generic (the static
auth. stuff in CB) or app specific, and hence must be (at least)
logically seperated from any router/framework code.

This last paragraph summarizes a fundamental design principle of WAMP:
separation from app specific code .. routers must not container app logic.

Cheers,
/Tobias

>
> I'm not totally clear on what you are suggesting to do, but you
> wouldn't do that.
>
>
> This is where we disagree. The creators of Unix designed authentication
> and subject-verb-object authorization into the kernel in 1970. Windows,
> OTOH, did not have a security model at its core and has been struggling
> ever since.
>
> It seems reasonable to expect at least this level of security in
> frameworks in 2015. Verb-only security is no security at all. The
> framework has to restrict which file to write to, not just allowing the
> user to write to any file.
>
> When I first read about Crossbar/WAMP, I wrote an internal memo saying I
> think I finally found a reasonable framework. It doesn't do much, but it
> does quite a bit more than many frameworks out there. Without
> subject-verb-object authorization, it is losing its appeal.
>
> Rob
>
> --
> You received this message because you are subscribed to the Google
> Groups "Crossbar" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to crossbario+...@googlegroups.com
> <mailto:crossbario+...@googlegroups.com>.
> To post to this group, send email to cross...@googlegroups.com
> <mailto:cross...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/crossbario/920bcf9e-ca62-47b5-ae96-bd785a49af04%40googlegroups.com
> <https://groups.google.com/d/msgid/crossbario/920bcf9e-ca62-47b5-ae96-bd785a49af04%40googlegroups.com?utm_medium=email&utm_source=footer>.

Rob Nagler

unread,
Aug 27, 2015, 11:56:13 AM8/27/15
to Crossbar
WAMP does subject-verb-object-based authorization:

subject: caller/publisher/.. session that originates the action
verb: WAMP action (one of 4)
object: The URI the originator want to act on

Dynamic authorizers get all 3 bits of info.


I get it now. Thanks.

Rob

Reply all
Reply to author
Forward
0 new messages