-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rotation of bound client keys #105
Comments
The easiest way for a client to rotate its keys is to handle a URL in the Another option would be to introduce the client key management URI (similar to Token Management URI) which accepts an object with similar properties to what "DPoP proof JWT" has and where the goal of the AS to make sure that that the client does have key material. Upsides
These are my thoughts. |
Another item that is a bit specific is 7.1.1 (key reference). Since "dereferencing this value are out of scope for this specification", so is rotation. I guess we assume there's some out of band KMS for that. |
I may also add yet another item for section "10.1. Introspecting a Token"
|
I'm more in favor of a defined API that the client can use to update its keys as well as anything else it needs to, a la RFC7592. Features that rely on the AS to fetch the latest values are susceptible to a number of problems:
The last point is really important: we need to be careful we don't make the same limiting assumptions that OAuth2 does in terms of client registration. This has been one of the driving limiting factors that GNAP is trying to address at a fundamental level, and we have to be careful it doesn't creep back in. |
I think it'll be important to introduce something soon -- otherwise components are likely to become brittle by treating a client instance's keys (or key thumbprints, or other derived artifacts) as persistent client instance identifiers. For example, imagine a resource server that expects access tokens conveying RARs like: {
type: "file-management",
actions: ["create-folder", "add-files-to-created-folders"],
locations: ["https://rs.example.org/data"]
} Well, the RS can see this RAR and allow a client to create some folders -- but how does it track which folders were created by a given client instance, so that it can allow the correct client instances to add files to (only) their own folders? The natural/only thing today is to use the introspection API's (Now you could argue that this style of RAR modeling is broken, but I think it's actually quite common and expressive. Compare for example with Google Drive OAuth permissions for add-ons like "Can read documents it's installed in" -- you don't say which documents at the time of approval, and the system needs to track installs relative to this client and authorization). |
(RAR) requests should go to the AS because that’s where they will be
processed into access tokens. If the request happens to go to the RS first,
it’s a failure of data minimization. Discovery style (AS or RS-first) may
not be determined by GNAP but GNAP can make sure that this privacy issue is
adequately considered in the spec.
- Adrian
…On Mon, Sep 27, 2021 at 11:51 PM Josh Mandel ***@***.***> wrote:
I think it'll be important to introduce something soon -- otherwise
components are likely to become brittle by treating a client instance's
keys (or key thumbprints, or other derived artifacts) *as* persistent
client instance identifiers. For example, imagine a resource server that
expects access tokens conveying RARs like:
{
type: "file-management",
actions: ["create-folder", "add-files-to-created-folders"],
locations: ["https://rs.example.org/data"]}
Well, the RS can see this RAR and allow a client to create some folders --
but how does it track which folders were created by a given client
instance, so that it can allow the correct client instances to add files to
(only) their own folders? The natural/only thing today is to use the
introspection API's key as a (pseudo)-identifier for the client,
correlating these across requests. But that'll become unreliable when
client instances can rotate their own keys, and we'll need a way to reflect
in the data model something like a "client instance identifier"
(independent of keys) or a "client instance's original key" property or
what-have-you.
(Now you could argue that this style of RAR modeling is broken, but I
think it's actually quite common and expressive. Compare for example with
Google Drive OAuth permissions for add-ons like "Can read documents it's
installed in" -- you don't say which documents at the time of approval, and
the system needs to track installs relative to this client and
authorization).
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#105 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AABB4YKNJQGBR77HEJSV2LTUEE3VTANCNFSM4TUYOKZQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
I think you've misunderstood my point @agropper -- I'm not suggesting requests would be sent to the resource server. Rather, as GNAP specifies: an access token (issued by the authorization server) is sent by the client to the resource server, and the RS introspects this token to learn what Resource Access Rights the token conveys. I'm pointing out here that the RS |
@jmandel Sorry for the confusion. I've been tutored by capabilities gurus to be suspicious of any identity-related access controls and I consider client identity to be part of that design. That's not to say that GNAP must normatively forbid client credentials, of course. When clients need pre-registration and rotation is important, couldn't client instances be identified by DIDs just like anything else? |
Client instances could be identified in all kinds of ways; my point is that currently (at least, if I'm reading the spec correctly -- and it's entirely possible I'm just missing something) GNAP doesn't model this information in an explicit RS-facing data element. |
Client instances *could* be identified in all kinds of ways; my point is
that currently (at least, if I'm reading the spec correctly -- and it's
entirely possible I'm just missing something) GNAP doesn't model this
information in an explicit RS-facing data element.
I leave it to others to answer how the spec models client information.
My concern is metadata the RS persists as a result of a RO and AS
relationship. RS persisting client identifiers or information as part of
the RO and AS relationship limits the RO's ability to delegate to agents
that they choose and I would like to keep that out of the core spec as much
as possible. The RS can avoid any client information issues in one of two
ways: (a) it can issue capabilities to the RO that the RO can pass to any
AS, or (b) the RO can register an AS they choose with the RS and then the
RS can use an AS introspection endpoint to expose client information to the
AS before acting on the token.
Are you suggesting that GNAP is unable to do (b)?
… —
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#105 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AABB4YIC2PIVMPEO4KP5B2TUEHXOLANCNFSM4TUYOKZQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
The point I've trying to make from my initial comment (and it seems I'm failing to communicate clearly -- sorry!) is that GNAP can and should provide a way to do (b). It's as "simple" as deciding this is a problem worth addressing, and standardizing a solution (or else deciding it's out of scope and leaving it to extension space. (I should note that even under (b), the RS absolutely needs to persist |
@jmandel You are correct that there is not a persistent client instance identifier that's exposed throughout the system, and that's been a deliberate design decision. While there are many kinds of software for which persistent identifiers make sense, we've seen with SPAs and mobile apps in OAuth that client_id gets in the way in a lot of places and doesn't end up telling you what you might think it does. Also note that the key bound to an access token might vary over time more than the client's "registered" key. We don't want to assume this will all be the same all the time, OAuth has already shown us that not to be the case. To the scenario you presented, it sounds like a requirement of the API you're protecting that there be some kind of authorization identifier that persists over time. After all, isn't it more than just the client software -- it's also who approved the software and for what purpose. This gets close to a grant identifier (like in #146) but exposing that to an RS sounds wrong. Still, I question whether the RS actually needs to know that information all the time. And if it does, then it's up to the AS to provide an RS-facing identifier for the software, user, grant, or whatever else, either in the introspection response or the token itself. The AS would be able to map this identifier across any kind of key rotation, since it would be able to trace the history of key usage and rotation for a client instance over time. Importantly, the result of this might be an identifier that the client instance itself never sees, since it's part of the internal agreement between the RS and AS. To have something like that we'd need to expand the model of what a token represents here with an AS-to-RS-identifier for the client instance. |
Agreed with your assessment @jricher that a grant identifier solves the problem just fine, and may be invisible to the client itself. My point here on this issue that that if we don't surface something like this in the standard protocol, RSs will (incorrectly) try to use client instance keys for this purpose, and that'll break even worse once those keys can be rotated. So I'm just calling out that #105 is linked to #146 in perhaps a non-obvious way. |
@jmandel that subtle connection's a fair point, especially when the client instance is using some-other-key for the access token. GNAP is built to enable (and perhaps even encourage) diversity of keys, especially for client software that can securely generate a key locally, so we'd expect much client software to use different keys over time. Rotating would tie those together at the AS. What I'm wondering is if we should actually put some warnings in the RS document against the RS using the client's key as a a stable identifier at all, and instead rely on things returned from the AS for all of these reasons. |
Yeah, I'd love to see 1) an explicit warning against using a client's key for this purpose and 2) an explicit field introduced in the introspection response (and eventually, incorporated into self-contained token formats) to allow the AS to communicate a stable grant identifier to the RS. |
We've got two types of bound keys:
The keys for an access token could be a simple pass-through pointer to the client instance's key, and this will probably be the default style of implementation. We can to solve these problems separately, but probably using the same key-presentation mechanisms for rotating the key material itself. We could have a client-management API as an extension that allows rotation of the client instance's key itself, and a key-rotation mechanism available as part of token rotation. The token rotation will be part of core. |
This should be in the same extension as discussed in #103 |
§8 Binding Keys: Editor's note:
We are going to need a way for a client to rotate its keys securely, even while an ongoing grant is in effect.
The text was updated successfully, but these errors were encountered: