Re: [GNAP] generic HTTP resource type

Jamey Sharp <> Tue, 27 July 2021 18:25 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 9BEC93A083C for <>; Tue, 27 Jul 2021 11:25:31 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -2.098
X-Spam-Status: No, score=-2.098 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: (amavisd-new); dkim=pass (1024-bit key)
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id 3dUr2Oft5Iso for <>; Tue, 27 Jul 2021 11:25:26 -0700 (PDT)
Received: from ( [IPv6:2607:f8b0:4864:20::633]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 967113A083B for <>; Tue, 27 Jul 2021 11:25:26 -0700 (PDT)
Received: by with SMTP id t21so16672963plr.13 for <>; Tue, 27 Jul 2021 11:25:26 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=06t0GofS9aA2AUO1gSvrg04jrumc/4rkohVVkGaISU4=; b=RyRIReEZOth2Eg4CN9ug/806D/fnECizmAGJ0UE/TE/eYmUlZE8DDiHIObfshAmRFU /3cHlGq/G6v9RkFw6LPOVsB6LhVAjFf/+R5IgXRlLjE6eXzhhWIBl5x99VaYPCva0MYH CPeTm96LToeujBqTu0ruLcGRZFIsleyv9SI6k=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=06t0GofS9aA2AUO1gSvrg04jrumc/4rkohVVkGaISU4=; b=gCuu45SEus8ZdULKBq1I9kcCFBaFIzVHYFDnfpF65eY3foYFuYhgaeiXv06M2IcII2 +49eN7ADG73F7SyjJSA93qc8ab80r3g9ZK2m8dExb+sPU6x9vMAnCVEmVkxJ4JbhfkoD c5Y+jzS3FpHg+C7Y02Wt9GetCir4NHVQAxll56JSY0DJ36XRVtkW+jH0w0yXJ1WWK/sd gROY59OkyeYMjnK8dULfgzQP+sOUKCTCI4i9t77oMpyg31Gl8VHIAFyi064X3P6DCpRR VvWES6Zq30GBPoqZJX++hbph8/bvy+LdwuWXgrPR52Ny2BpHKPdzxAR3P48LrgwWH20K 6GfQ==
X-Gm-Message-State: AOAM533Z0r01gRMO7yOJaMtpmZbuxxJ2TM+KIM93G4iGvHLaXnviixbU 6+0fqNZscRtmEY1tshROo2ekMw==
X-Google-Smtp-Source: ABdhPJydSdr0FHVxbsLVeVBvJI2qZB8nYKpSGd1m1nklMMmORGAQAK08xd7vFP/kbghgmSIn4H6Egw==
X-Received: by 2002:a17:90b:1097:: with SMTP id gj23mr24016933pjb.65.1627410325090; Tue, 27 Jul 2021 11:25:25 -0700 (PDT)
Received: from eh ( []) by with ESMTPSA id kr6sm1833285pjb.23.2021. (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 11:25:24 -0700 (PDT)
Received: by eh (sSMTP sendmail emulation); Tue, 27 Jul 2021 11:25:23 -0700
Date: Tue, 27 Jul 2021 11:25:23 -0700
From: Jamey Sharp <>
To: Adrian Gropper <>
Cc: GNAP Mailing List <>
Message-ID: <>
References: <YP9bhNFEs3YPw1AD@eh> <>
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
In-Reply-To: <>
X-TUID: 83v4b+X65LVT
Archived-At: <>
Subject: Re: [GNAP] generic HTTP resource type
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: Tue, 27 Jul 2021 18:25:32 -0000

Hi Adrian!

I agree with the general principles you're suggesting, but I don't 
believe my proposal reveals anything new to the RS. A resource server 
has to know what resource the end-user is requesting in order to serve 
that resource.

(The cryptography notions of "private information retrieval" and 
"oblivious RAM" would be an interesting challenge to apply to the web, 
but I'm sure they're well out of scope for this WG. You might enjoy 
reading the research literature on them though.)

My proposal does potentially reveal new information to the AS, and 
that's worth thinking about. There are two cases:

If it's desirable for the AS to reveal to the end-user the set of 
resources to which they've been granted rights—and I think it is—then 
that means the RS must have previously informed the AS about what the 
resource references which the RS uses actually refer to. Otherwise, a 
reference is an opaque string like "WallyWorld" that means nothing to 
either the end-user or the AS. (It certainly doesn't mean anything to 
me: I'm taking that from the original examples in the HTTP Basic auth 
spec, going back to at least 1996.)

Second, I've proposed that the client inform the AS of the specific 
resource and method which the end-user was trying to request. I'm not 
sure whether that's either necessary or desirable; I'm hoping other 
folks will chime in on my questions about whether the client needs to be 
able to indicate that it understands this generic "http" rights type.

I think it's worth noting that the choice of AS is made by the RO/RS, 
not by the end-user. So the safest assumption you can make when 
analyzing the privacy properties of GNAP is that the RS and AS may 
reveal any information they have to each other without the end-user's 
knowledge or consent. That doesn't change the above analysis though, 
since the only things the AS may learn are things the RS already knows.

Finally, here's context I think will help you on HTTP authentication:

An HTTP server can indicate that its response to a resource request 
might change if the client were authenticated. It does so by sending a 
"WWW-Authenticate" response header, containing a list of authentication 
schemes that the server will accept. In the context of GNAP, you can see 
that in "RS-first Method of AS Discovery", currently section 9.1.

If the client chooses to use one of those schemes, then it sends a new 
request containing an "Authorization" header. The contents of that 
header are mostly specified by the selected authentication scheme; for 
GNAP, that's covered in "Securing Requests from the Client Instance", 
"Presenting Access Tokens", which is currently section 7.2.

GNAP departs from older HTTP authentication schemes because in between 
the above two steps, the client goes off and talks to somebody else (the 
AS) for a while. But that side conversation is invisible to the RS, 
which just sees the client send one unauthenticated request and then a 
second request that contains an access token.

If the client already knows that the RS uses a specific GNAP AS, then 
the RS doesn't even get that first unauthenticated request; the first 
time it hears anything from the client is after the conversation with 
the AS is finished. But I'm interested in the case where the client has 
no prior knowledge about the RS, which means it works as I've described 
above, just like any other HTTP auth scheme.

The problem I'm trying to address is that after the first request, the 
HTTP auth spec doesn't say whether the client should use the same 
credentials when requesting resources at other URLs.

If the client does not send credentials on the next request, then it may 
get another "WWW-Authenticate" header back without getting the resource 
it actually wanted, which wastes time as it has to issue the request 
again even if it has a valid access token available.

But proactively authenticating to a different URL can leak information 
to a malicious party, since there may be many unaffiliated ROs at a 
single RS. For the Basic and Bearer schemes, the leaked information is 
full credentials and a complete security compromise. In other schemes, 
revealing that the end-user has credentials for some other resources is 
still a privacy violation, and in addition the leaked information may 
include identity details such as a username.

I briefly discussed in my previous mail how the Basic and Digest schemes 
approach this. Bearer seems to assume the client has prior knowledge 
about which resources a token gives it access to—which is reasonable 
given how OAuth 2.0 has been used, but GNAP's RS-first discovery opens 
up new use cases with new challenges. So I believe this needs to be 
addressed somehow, and I've proposed one possible way to do it.

I hope this clarified my proposal for you!

On Mon, Jul 26, 2021, 7:31 PM Adrian Gropper <> 
> Hi Jamey,
> I don't understand what's being proposed. Mostly this is due to my 
> inexperience with HTTP APIs, but I'm trying to learn.
> In cases of RS-first AS discovery, the end-user might or might not be the 
> RO. If the end-user is not the RO, then, from a data minimization 
> perspective, I do not want the client sharing any request information with 
> the RS. In other words, I do not assume that trusting the RS is the same as 
> trusting the AS. Therefore, an RS-first request should not require any 
> authentication. It should just return a link to the AS associated with that 
> resource.
> A request to the RS by the RO should obviously require authentication.
> A request to the RS that includes an authorization token is not subject to 
> authentication of the end-user. 
> What am I missing?
> Adrian
> On Mon, Jul 26, 2021 at 9:04 PM Jamey Sharp <> wrote:
>> In today's meeting, I asked about applying GNAP as the HTTP 
>> authentication method for arbitrary HTTP resources, such as static 
>> files, in the same way that Basic and Digest auth can be used today. 
>> Justin asked me to share the question here.
>> Because the current draft includes RS-first AS discovery using the 
>> standard WWW-Authenticate response header, it might work for this use 
>> case as-is, but I think it can be improved.
>> First: Am I correct in thinking that two access tokens retrieved from 
>> the same AS, by the same end user, with the same "access" list, should 
>> be indistinguishable to the client? Specifically, if a client receives 
>> two `WWW-Authenticate: GNAP` headers with the same "as_url" and "access" 
>> parameters, can it reuse the access token it got for the first request 
>> on the second request, without consulting the AS again?
>> If so, I think the WWW-Authenticate "access" parameter is equivalent to 
>> the "realm" parameter defined in RFC7235 and used in RFC7617 Basic auth. 
>> (Perhaps for consistency with HTTP auth, it should in fact be called 
>> "realm" when used in that header? RFC7235 even uses "scope" terminilogy 
>> to describe it.)
>> Without additional provisions, which I'm pretty sure are not currently 
>> in GNAP, checking for matching realm/access parameters still requires an 
>> extra unauthenticated request any time the client needs to access a URL 
>> it hasn't visited before, even if the response turns out to indicate 
>> that an earlier access token can be reused.
>> RFC7617 defines somewhat magic rules for when a client can proactively 
>> provide Basic-scheme credentials to a URL where it hasn't previously 
>> seen a WWW-Authenticate header, in order to avoid a round-trip in the 
>> common case where the same credentials are accepted at similar URLs. In 
>> theory, GNAP could specify something similar to make RS-first AS 
>> discovery more efficient, but that level of magic seems dangerous to me.
>> The Digest auth scheme in RFC7616 instead allows the server (in this 
>> context, the RS) to give an explicit list of URL prefixes which accept 
>> the same credentials, in the WWW-Authenticate "domain" parameter. I 
>> think that's a closer fit for GNAP, but rather than making it a header 
>> parameter, I think it's best to fold it into the token's access rights.
>> I propose standardizing a definition of a "type" value for the rights 
>> request that describes HTTP access rights generically, rather than 
>> describing actions appropriate to a specific API. I think that would 
>> make GNAP usable anywhere that Basic or Digest auth are currently used. 
>> It might also enable a wide variety of RESTful APIs and HTTP-based 
>> standards to use GNAP without needing to define custom rights types.
>> Here is a concrete suggestion as a starting point for discussion:
>> "access": [{
>>    "type": "http",
>>    "locations": [""],
>>    "datatypes": ["text/html", "image/*"],
>>    "actions": ["GET", "PUT", "DELETE"]
>> }]
>> A resource request must match all fields to be allowed. If "datatypes" 
>> or "actions" are empty or absent, then all are permitted. (Permitting 
>> nothing is the same as not granting any rights at all.) The "locations" 
>> field is required to be present and non-empty though, and might work 
>> like the "domain" parameter in Digest: "The client can use this list to 
>> determine the set of URIs for which the same authentication information 
>> may be sent: any URI that has a URI in this list as a prefix [...] MAY 
>> be assumed to be in the same protection space."
>> This allows a client to request a limited set of methods or access to a 
>> limited portion of the protection space. It also allows the AS to inform 
>> the client of exactly which requests it may use the access token on, 
>> which may be different than what the client requested.
>> If I'm reading the current draft correctly, if a client sends an opaque 
>> resource reference like `"access": "WallyWorld"`, then the AS may choose 
>> to send back a non-opaque description of the rights granted by the 
>> returned access token, such as the above example for the hypothetical 
>> "http" rights type. Is that right?
>> I suppose the downside of the AS transforming an opaque reference into a 
>> full rights description is that the client can't indicate which rights 
>> types it understands. If a CMS supports a proprietary API for editing 
>> blog posts, but also supports WebDAV for file attachments, it might not 
>> be clear which rights type to use, yeah?
>> So here's an additional proposal: a client wishing to use this generic 
>> HTTP rights type should (must?) explicitly request it in the "access" 
>> rights request (and may also include the resource reference given in the 
>> "access" parameter of the WWW-Authenticate header, if any). It must 
>> specify the exact request URL in the "locations" field, and may also 
>> specify the method it tried to use in "actions". As usual, the AS may 
>> return a token granting rights to a wider range of locations or methods 
>> and is recommended to return the actual granted rights.
>> I hope that's reasonably clear and would love to discuss this further.
>> Jamey
>> -- 
>> TXAuth mailing list