Re: [GNAP] Accounting for Resource Owner in RS::AS interactions

Justin Richer <> Wed, 29 September 2021 12:16 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 89B053A14CC for <>; Wed, 29 Sep 2021 05:16:58 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -1.898
X-Spam-Status: No, score=-1.898 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id o-10htaiDw9t for <>; Wed, 29 Sep 2021 05:16:53 -0700 (PDT)
Received: from ( []) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 9E4B43A14F1 for <>; Wed, 29 Sep 2021 05:16:52 -0700 (PDT)
Received: from (W92EXEDGE3.EXCHANGE.MIT.EDU []) by (8.14.7/8.12.4) with ESMTP id 18TCGQqc013956; Wed, 29 Sep 2021 08:16:46 -0400
Received: from ( by ( with Microsoft SMTP Server (TLS) id 15.0.1497.23; Wed, 29 Sep 2021 08:16:26 -0400
Received: from ( by ( with Microsoft SMTP Server (TLS) id 15.0.1497.23; Wed, 29 Sep 2021 08:16:29 -0400
Received: from ([]) by ([]) with mapi id 15.00.1497.023; Wed, 29 Sep 2021 08:16:29 -0400
From: Justin Richer <>
To: Adrian Gropper <>
CC: "" <>, GNAP Mailing List <>
Thread-Topic: [GNAP] Accounting for Resource Owner in RS::AS interactions
Thread-Index: AQHXs8kKpD6zmNxgu0KI6JYI9heXrau5zcsAgABJcID//8EiAIAA174AgAA8uyE=
Date: Wed, 29 Sep 2021 12:16:29 +0000
Message-ID: <>
References: <> <> <> <>, <>
In-Reply-To: <>
Accept-Language: en-US
Content-Language: en-US
x-ms-exchange-transport-fromentityheader: Hosted
x-originating-ip: []
Content-Type: text/plain; charset="Windows-1252"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
Archived-At: <>
Subject: Re: [GNAP] Accounting for Resource Owner in RS::AS interactions
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: GNAP <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Wed, 29 Sep 2021 12:16:59 -0000


Once again, I believe you are conflating the technical roles of the protocol (AS, RS) with the parties that would fulfill those roles. What you describe as the RS entity in your solution is, in reality, an AS/RS pair. What you describe as the RO's chosen AS is what GNAP calls out as an input into the AS. This is why I keep saying that it's the interaction and consent phase of GNAP where things like SSI and policy descriptions and user-to-user delegation come into play. It's a different model from UMA, and I believe it's a model that works much better and fits reality. 

The AS issues tokens that are trusted, the RS trusts and executes those tokens. Giving an unknown party complete security control over your API is terrifying, and we've already seen that what actually happens is that people build in a internal AS to handle that case anyway. It's why we have things like security assertions and token exchange and application gateways. 

Software delegation protocols, like OAuth and GNAP, aren't particularly well suited to the user delegation problem on their own, because you can't have a user present a technical input. You can however make explicit places within the protocol for those inputs to be expressed, and that's what we are trying to do with GNAP. 

You can absolutely build out the model I'm describing in privacy preserving ways, and I will argue that it will have significantly better security properties when compared to letting a user pick their AS. 

So, let the RS dictate who it will listen to tokens from, and allow the AS to get its information about what those tokens are for, and when to issue them, from a variety of places. 

- Justin
From: Adrian Gropper []
Sent: Wednesday, September 29, 2021 12:27 AM
To: Justin Richer
Cc:; GNAP Mailing List
Subject: Re: [GNAP] Accounting for Resource Owner in RS::AS interactions

Josh and Justin,

>From a privacy perspective, your glee over not having the RO specify the AS to the RS is troubling. Why would the RS care about privacy unless mandated in some way? (I'm assuming mandates are out of scope for GNAP :-).

The privacy problem is simply data minimization. As an RO, I should not have to share my policies with the RS because all the RS needs is the access token. If the RS is unwilling (or whatever you mean by "nervous", above) to trust a random AS simply because the RO trusts it, then we're left with capabilities. Imagine a typical RS serving millions of ROs. The policy database would be a gold mine in so many ways. Traffic analysis by the RO might still be a problem and will also need to be considered.

If specifying the AS is not an option, the RO associated with a resource MUST be given a full set of capabilities on demand. The RO can then pass some or all of those to whatever AS they trust with their policies and then that AS can issue attenuated access tokens with or without further delegation rights to any client they choose.

GNAP core must choose either or both arbitrary AS or capabilities and maybe explain "nervous" in a way that people can understand.

- Adrian

On Tue, Sep 28, 2021 at 3:35 PM Justin Richer <<>> wrote:
On Sep 28, 2021, at 3:20 PM, Josh Mandel <<>> wrote:

Thanks Justin -- this whole response is extremely helpful. I particularly appreciate your very clear declaration of scope and intention:

> That was what UMA tried to do with resource set registration, in a way. It was awkward from a technology perspective, and it made RS owners nervous in a lot of ways to have a new AS introduced. I appreciate the ideology, but to this day I don’t believe it’s realistic to implement or deploy.

I agree entirely with this assessment, and I agree that some tighter degree of AS::RS coupling is needed to support real-world system design. Understanding that this UMA-like level of RS::AS flexibility is *not* the design intent for GNAP alleviates several of my concerns in one fell swoop.

To be clear, this is my own take on the goals of GNAP vs. experience with UMA, and the stance I’ve been advocating for here for some time. I think GNAP could allow that, in that GNAP doesn’t :require: a tight coupling per se, but it also doesn’t assume a completely loose coupling or force the protocol through those hoops for all other use cases. UMA tried to do the latter, but just about every UMA deployment I saw didn’t make use of that loose coupling, but you still had to go through the bits of the protocol that were built just in case that happened.

It’s a goal of GNAP to learn from the good and bad of previous protocols, including UMA, and this is one area that I think we can improve.

I should mention that for readers familiar with UMA (or at least... for me) this was not clear from reading GNAP; I came in assuming GNAP intended to cover this space.

I think what might be confusing here is that GNAP does intend to cover the use case space of having a user delegate to another user, and externalizing a lot of the user rights aspects of the ore delegation process too. But instead of doing it through “everyone brings their own AS” type of things, GNAP is trying to do it through “the AS can now be flexible enough to get a lot of different information”. There were some slides on this a while back:

Starting at slide 35 you’ll see diagrams and points of some of the alternatives. I know the meeting is recorded but I”m not sure where that lives if you want to review it.

 - Justin

On Tue, Sep 28, 2021 at 1:57 PM Justin Richer <<>> wrote:
Hi Josh, thanks for bringing up this use case. An AS protecting several different unrelated RS’s is absolutely in scope, as this is a common deployment for OAuth 2 today. If I understand everything you’re asking, currently GNAP would allow everything here, but it doesn’t specify the details of every part of it. I’m going to reply to your scenarios inline below. Apologies in advance for the long email, there’s a lot to unpack here!

On Sep 27, 2021, at 1:56 PM, Josh Mandel <<>> wrote:

Hi All,

I'm interested in exploring how GNAP can/does/might account for the Resource Owner associated with specific protected resources, in scenarios where a single AS is trusted by multiple independent RS's (specifically in scenarios where these RS's don't know or trust one another). Justin suggestd I might reach out here.

My sense is that there are security considerations related to these questions, and perhaps some best practices or even areas where the core spec's data models could be enhanced to support these scenarios. I'm not proposing anything in particular at this stage; just trying to get the lay of the land.

See assumptions and scenarios below.



Assumptions. I'll focus on a very simple API from the RS perspective: a standardized file access API where resource servers would like to make access control decisions based on access tokens whose RARs look something like:

  "type": "file-access",
  "actions": ["read"],
  "location": ["{{URL of one protected file}}"]


Scenario 1. Consider the case where a single RS manages files owned by multiple end users. The RS uses a single AS for all files (but the AS also serves other untrusted RS's). Each RO is allowed to set authorization policies for their own files. In this scenario, how does the AS learn which RO is responsible for setting policies for each file, so it can present Alice with a list of current policies, allow her to review/tweak access, etc?

Setting and updating policies are outside the scope of GNAP core, including any interfaces for doing so.

The policies are controlled at the AS and enforced by the RS. It’s really up to the individual deployments how and where to make that split: an AS could issue tokens that are simply tied to the specific data, the result of processing the security context of the delegation. Or the AS could send over all the context information to the RS to let it make its own decisions entirely, while the AS only has an idea of something existing and not who owns or controls it. Or something in between. And all of these are functionally the same whether you’re introspecting or using structured tokens, so I’m not going to get into the differences here.

Doing this statically would be pretty easy, since the decisions can just be set in code and executed. Doing it dynamically feels a lot harder and more interesting. There are a lot of pieces that need to be fulfilled to even get to this point, and I’ll try to add some thoughts on each:

- How does the AS know who Alice is? In OAuth, it’s assumed that Alice can “log in” to the AS using her account. In GNAP we also allow that but further let Alice have other ways of interacting with the AS, and doesn’t assume that Alice has an “account” at the AS in a traditional sense. Even so, it’s likely in this scenario that the AS will have some set of identifiers that it has bound to Alice, which can be associated with that policy.

- How does the RS know about the AS? GNAP does offer some discovery for the technical connections (, but more important is the question of how the RS decides to trust the AS to protect any given resource. In your scenario this sounds like a configuration time decision, but it might not always be.

(If an AS is confused on this point, there's a risk that Bob can set policies for Alice's files.) It's possible that the Resource Registration API could be extended to model this kind of ownership, if both servers have some interoperable way to communicate user identities. I'm not sure if there are existing patterns to recommend here?

- How does the AS know about what the RS is protecting? GNAP allows the RS to dynamically introduce a new resource set to the AS and get back a reference for it (, and like you, I could see this being expanded with an ability to say “this RO / set of ROs controls this resource set” as part of that registration step. As long as the identifiers aligned, it would let the AS do some enforcement at token issuance time. But that really isn’t meant to set policies, it’s meant to allow an RS to register a set of rights with a simple identifier (like a scope with a random value). Perhaps a different API is actually needed for policy management? And with that in mind, it would only be needed if we wanted the AS to make sure Bob is never prompted for one of Alice’s files at the AS, ever. If you don’t want that information to leak to the AS, you can allow Bob to get an ineffective token for Alice’s file resource, and count on the RS to say “hey you aren’t Alice, go away”. Again, this goes back to where you draw the enforcement lines, which often has more to do with the nature of the API you’re protecting than anything.

- How does the RS know how to associate a specific resource with “Alice”, and not “Bob"? This requires the RS to know who “Alice” is and know that a given file is hers to control. Doing this dynamically feels really difficult

- How do the RS and AS agree that “Alice” is the same person with the same identifiers? It’s obvious that simply trusting a global identifier here won’t solve it on its own — confusion remains trivial, it would just take an RS to apply Bob’s global identifier to Alice’s data, or for Bob to get assigned Alice’s identifier by a bad AS. But GNAP does have a whole notion of “subject identifiers” that are scoped to the AS’s trust domain that can be used here: if the RS refers to Alice by an identifier known to the AS, and it trusts the AS to enforce that binding for Alice, then it will work.

It's also very important for the RS to know, whenever it receives an access token, that the RS is an intended audience for that token. The RAR "locations" aren't enough to accomplish this, unless the AS has a reliable scheme in place to prevent one RS from crafting RARs that refer to resource locations within another RS.  And as the spec says, the AS introspection endpoint needs to ensure that access tokens are "appropriate for presentation at the identified RS". But that's especially challenging when a single access token can include multiple RARs, potentially intended for different RS's (which appears to be allowed by the base spec). And for structured token formats where introspection isn't required, the same questions hold; is there existing work on this?

The ‘locations’ field on its own isn’t enough for this, but it can be a place to hold identifiers for each RS. These need not be URLs to the APIs in question, though in practice I’d expect them to be. It then also begs the question of how the RS identifiers came to be, and if they’re then required for this type of processing.

Scenario 2. Now consider the case where 10 organizations each manage a File Sharing RS. Each RS hosts files for multiple ROs, and the ROs get to choose which AS should be trusted for their own files. In this context, I suppose the workflow that introduces the RS to the AS can be mediated by the RO, so that the RO is logged into both systems when making the introduction, and the RS can essentially register a new client instance with the AS for each RO who decides to establish a connection. This pattern has the advantage that there's no confusion about *who* controls a given resource -- but perhaps there are other, better ways to accomplish this.

That was what UMA tried to do with resource set registration, in a way. It was awkward from a technology perspective, and it made RS owners nervous in a lot of ways to have a new AS introduced. I appreciate the ideology, but to this day I don’t believe it’s realistic to implement or deploy.

I think a better pattern is to allow introduction of “Alice” at the AS level instead of at the RS level. In other words, Alice doesn’t bring her own “AS”, but she could bring her own identity and policy to the AS that protects the RS. That way the RS-AS relationship can be more tightly aligned, but the user capabilities are greatly expanded. It changes the fit of the components from what we might be used to, but I strongly believe there’s a lot of promise in this pattern. And in fact, we see a similar pattern in OAuth 2 today with API Gateways that can be configured to allow federated logins, for example.

Finally, I think there’s an even more interesting scenario: when Alice says that Bob should be able to access her stuff. Who does she tell and who needs to care? There are a lot of ways to slice this, but this jumps to my mind immediately:

 - Alice has a resource A at the RS, which is protected by the AS
 - The AS has a policy that says Alice can authorize client instances to access resource A
 - The AS also has an interface for Alice to set additional policies
 - Alice says to the AS that a user identified as Bob can also access A
 - When either Alice or Bob come to the AS, the AS can figure out from this policy to create an access token that can access A
 - The RS doesn’t need to know about Alice or Bob at all, only whether the token is good for accessing A

 — Justin

TXAuth mailing list<>

TXAuth mailing list<>