
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts: I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home. So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other. ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes And finally what the token includes: RPTResult - the sets that the resulting token includes on output The one direct relationship seems to be that: ROPolicy = subset(RSReg) Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above. It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words: RPTResult = subset(ROPolicy) That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green. This also means that RSReg is also a limiting set, due to transitive subset operations: RPTResult = subset(RSReg) We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of: Requested = union(ClientReq, RSTicket) We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like: Requested = union(ClientReg, ClientReq, RSTicket) This could also be done conditionally, like the case where the client didn’t specifically request anything: if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) } Or if the client or ticket didn’t request anything: if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg } So my proposed implementation would be something like this horrible pseudocode: if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> } << the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket) << if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg } << finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >> RPTResult = union( intersection(Requested, ROPolicy), PrevRPT) I’ve tested a little bit of this with the following python truth table code: from truths import Truths print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT']) This seems to match up to expectations on a quick inspection, but I’m potentially missing something. Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality. — Justin

Humongously useful, thank you! Comments on three parts: ==== Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book. ==== Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message): 1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting (Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.) You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope. Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game? ==== Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pièce+de+résistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pièce%20de%20résistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy. *Eve Maler*Cell +1 425.345.6756 | Skype: xmlgrrl | Twitter: @xmlgrrl On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union( intersection(Requested, ROPolicy), PrevRPT)
I’ve tested a little bit of this with the following python truth table code:
from truths import Truths
print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT'])
This seems to match up to expectations on a quick inspection, but I’m potentially missing something.
Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality.
— Justin
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma

Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set. Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors. Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :) This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones. To wit, a token starts with: rsid_1: { foo, bar }, rsid_2: { baz, qux } And a new request in the context of rsid_3 adds in { foo, batman } and we end up with: rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman } That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like: rsid_1: { foo, bar, batman }, rsid_2: { baz, qux } Or it *could* come out with a token that looks like: rsid_1: { foo, batman } And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally. -- Justin On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. /(Client can bring no RPT and ask for one -- not a concern)/ 1. /(AS can issue a new RPT A -- not a concern)/ 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would /upgrade/ that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and /downgrading/ other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu <mailto:jricher@mit.edu>> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union( intersection(Requested, ROPolicy), PrevRPT)
I’ve tested a little bit of this with the following python truth table code:
from truths import Truths
print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT'])
This seems to match up to expectations on a quick inspection, but I’m potentially missing something.
Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality.
— Justin
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org <mailto:WG-UMA@kantarainitiative.org> http://kantarainitiative.org/mailman/listinfo/wg-uma <http://kantarainitiative.org/mailman/listinfo/wg-uma>

This seems well thought out, thanks Justin. I've got just one concern: I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it. I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view". This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response. Cheers James On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union( intersection(Requested, ROPolicy), PrevRPT)
I’ve tested a little bit of this with the following python truth table code:
from truths import Truths
print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT'])
This seems to match up to expectations on a quick inspection, but I’m potentially missing something.
Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality.
— Justin
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma

Hi James, I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph). Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s). I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA. Thanks, George On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union( intersection(Requested, ROPolicy), PrevRPT)
I’ve tested a little bit of this with the following python truth table code:
from truths import Truths
print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT'])
This seems to match up to expectations on a quick inspection, but I’m potentially missing something.
Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality.
— Justin
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544

Hi George, I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth. Cheers James On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union( intersection(Requested, ROPolicy), PrevRPT)
I’ve tested a little bit of this with the following python truth table code:
from truths import Truths
print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT'])
This seems to match up to expectations on a quick inspection, but I’m potentially missing something.
Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality.
— Justin
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>

Hi James, I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT. So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:) Thanks, George On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers James
On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union( intersection(Requested, ROPolicy), PrevRPT)
I’ve tested a little bit of this with the following python truth table code:
from truths import Truths
print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT'])
This seems to match up to expectations on a quick inspection, but I’m potentially missing something.
Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality.
— Justin
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544

Like I said, I'm talking about scope values requested by the client, *not* by the RS in the permission ticket. J. On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers James
On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union( intersection(Requested, ROPolicy), PrevRPT)
I’ve tested a little bit of this with the following python truth table code:
from truths import Truths
print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT'])
This seems to match up to expectations on a quick inspection, but I’m potentially missing something.
Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality.
— Justin
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>

So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that? Thanks, George On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Like I said, I'm talking about scope values requested by the client, *not* by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers James
On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union( intersection(Requested, ROPolicy), PrevRPT)
I’ve tested a little bit of this with the following python truth table code:
from truths import Truths
print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT'])
This seems to match up to expectations on a quick inspection, but I’m potentially missing something.
Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality.
— Justin
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544

Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that. So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting. Cheers James On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com> wrote:
So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Like I said, I'm talking about scope values requested by the client, *not* by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com
wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers James
On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union( intersection(Requested, ROPolicy), PrevRPT)
I’ve tested a little bit of this with the following python truth table code:
from truths import Truths
print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT'])
This seems to match up to expectations on a quick inspection, but I’m potentially missing something.
Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality.
— Justin
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>

I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time. Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket. On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that.
So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting.
Cheers James
On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com> wrote:
So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Like I said, I'm talking about scope values requested by the client, *not* by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers James
On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union(
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544

Interesting thought — so are you suggesting that: Requested = union(intersection(ClientReg, ClientReq), RSTicket) That would let ClientReg be a limiting set but wouldn’t leave out the RS requesting more scopes (or policies granting more scopes) than the client itself asked for. I could live with that interpretation. — Justin
On Jan 10, 2017, at 12:01 PM, George Fletcher <george.fletcher@teamaol.com> wrote:
I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time.
Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket.
On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote: Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that.
So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting.
Cheers James
On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote: So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote: Like I said, I'm talking about scope values requested by the client, not by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote: Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote: Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers James
On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote: Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote: This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry (https://tools.ietf.org/html/rfc7591#section-4 <https://tools.ietf.org/html/rfc7591#section-4>) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu <mailto:jricher@mit.edu>> wrote: Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely:
RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message): (Client can bring no RPT and ask for one -- not a concern) (AS can issue a new RPT A -- not a concern) Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do AS is allowed to reissue the existing RPT A (same RPT string), having added the relevant permissions to it AS can issue a new RPT B (different RPT string), having added the relevant permissions to it AS can invalidate the old RPT A that the client brought it upon this action AS can retain the validity of the old RPT A that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting (Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would upgrade that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and downgrading other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
Eve Maler Cell +1 425.345.6756 <tel:(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu <mailto:jricher@mit.edu>> wrote: I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
<Mail Attachment.png>
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union(
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544

Yes, though I'd feel better with James weighing in to make sure I understood his idea correctly:) On Tue, Jan 10, 2017 at 2:08 PM Justin Richer <jricher@mit.edu> wrote:
Interesting thought — so are you suggesting that:
Requested = union(intersection(ClientReg, ClientReq), RSTicket)
That would let ClientReg be a limiting set but wouldn’t leave out the RS requesting more scopes (or policies granting more scopes) than the client itself asked for.
I could live with that interpretation.
— Justin
On Jan 10, 2017, at 12:01 PM, George Fletcher <george.fletcher@teamaol.com> wrote:
I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time.
Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket.
On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that.
So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting.
Cheers James
On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com> wrote:
So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Like I said, I'm talking about scope values requested by the client, *not* by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers James
On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
<Mail Attachment.png>
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544

Well, in fact I was suggesting: Requested = union(intersection(ClientReg, ClientReq), RSTicket, ClientRegisteredDefaults) But I can live with ClientRegisteredDefaults being an off-spec AS extension, so yes :) Cheers James On 10 January 2017 at 19:16, George Fletcher <george.fletcher@teamaol.com> wrote:
Yes, though I'd feel better with James weighing in to make sure I understood his idea correctly:)
On Tue, Jan 10, 2017 at 2:08 PM Justin Richer <jricher@mit.edu> wrote:
Interesting thought — so are you suggesting that:
Requested = union(intersection(ClientReg, ClientReq), RSTicket)
That would let ClientReg be a limiting set but wouldn’t leave out the RS requesting more scopes (or policies granting more scopes) than the client itself asked for.
I could live with that interpretation.
— Justin
On Jan 10, 2017, at 12:01 PM, George Fletcher < george.fletcher@teamaol.com> wrote:
I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time.
Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket.
On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that.
So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting.
Cheers James
On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com
wrote:
So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Like I said, I'm talking about scope values requested by the client, *not* by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com
wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers James
On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
<Mail Attachment.png>
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>

I have to admit you guys have now gone beyond my ability to follow. :-) If someone could summarize in English pseudo-spec language, and a simple example, I would be very very grateful. I would like any discussion of this tomorrow to to be efficient, because there's lots of other stuff to discuss too. *Eve Maler*Cell +1 425.345.6756 | Skype: xmlgrrl | Twitter: @xmlgrrl On Tue, Jan 10, 2017 at 2:02 PM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Well, in fact I was suggesting:
Requested = union(intersection(ClientReg, ClientReq), RSTicket, ClientRegisteredDefaults)
But I can live with ClientRegisteredDefaults being an off-spec AS extension, so yes :)
Cheers James
On 10 January 2017 at 19:16, George Fletcher <george.fletcher@teamaol.com> wrote:
Yes, though I'd feel better with James weighing in to make sure I understood his idea correctly:)
On Tue, Jan 10, 2017 at 2:08 PM Justin Richer <jricher@mit.edu> wrote:
Interesting thought — so are you suggesting that:
Requested = union(intersection(ClientReg, ClientReq), RSTicket)
That would let ClientReg be a limiting set but wouldn’t leave out the RS requesting more scopes (or policies granting more scopes) than the client itself asked for.
I could live with that interpretation.
— Justin
On Jan 10, 2017, at 12:01 PM, George Fletcher < george.fletcher@teamaol.com> wrote:
I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time.
Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket.
On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that.
So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting.
Cheers James
On 10 January 2017 at 16:32, George Fletcher < george.fletcher@teamaol.com> wrote:
So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Like I said, I'm talking about scope values requested by the client, *not* by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher < george.fletcher@teamaol.com> wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers James
On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com
wrote:
Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
Per the first point: But the AS still has to deal with its own internal processing of "which scopes the RO said were OK if the RqP did certain things good enough" which might not be the same set of scopes requested. This is effectively the set of scopes that result from processing the set of claims supplied by the RqP and client. We *have* to include this in the calculation even though the details of how that's specified by the RO or how the processing engine translates claims to scopes is out of band for us since the *results* of that calculation are bound to show up somehow. And it remains to me to be a clearly limiting set.
Per the second point: It's a separate question whether to reissue the old RPT or reuse its value. No matter what happens there, the question is: what do we do with the scopes associated with the *input* RPT if present? I say we *allow* the AS to add them to the resulting RPT (whether it's now or reissued or whatever, we don't care) but don't *require* the AS to do that. So my pseudocode below is valid but not strictly required as a template for implementors.
Per the third point: the scopes here are nearly all already associated with a resource, apart from ClientReg which tends to be generic in implementations I've seen to date. Namely: RSTicket - ticket is associated with a specific resource set ID on ticket request ROPolicy - policy is associated with a specific resource set ID on creation at AS ClientReq - these are submitted along with a ticket which is associated with a specific resource set ID RSReg - these are associated with a specific resource set by tautological definition :)
This leaves us two: ClientReg - these would tend to be generic, crossing resource sets (likely pertaining to a specific kind of API the client knows how to deal with and not an instance of the same) PrevRPT - these might cross a bunch of different resource sets, but at this point the internal permissions structure might be such that they're associated with the token in a way that doesn't overlap the new ones.
To wit, a token starts with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }
And a new request in the context of rsid_3 adds in { foo, batman } and we end up with:
rsid_1: { foo, bar }, rsid_2: { baz, qux }, rsid_3: { foo, batman }
That's pretty clearly new stuff. The real trick comes when you get a new request with that first token in the context of rsid_1 again with { foo, batman } being requested/approved. This is the "token step up" function that's been in UMA since forever, and I argue that this *could* come out with a token looking like:
rsid_1: { foo, bar, batman }, rsid_2: { baz, qux }
Or it *could* come out with a token that looks like:
rsid_1: { foo, batman }
And it's up to the AS to figure out which it wants to do. Again, note: Whether this permissions set is associated with the same token value string as the input RPT is subject to the logic in your message repeated below, and that's a separate question entirely and ought to be decided orthogonally.
-- Justin
On 1/8/2017 1:51 AM, Eve Maler wrote:
Humongously useful, thank you! Comments on three parts:
====
Policy conditions are out of scope for UMA, so the AS could be configured with all kinds of stuff that is out of scope for what UMA cares about, but since "the AS only knows what the RS told it" as far as UMA goes, RSReg definitely counts as a reasonable limiting factor in my book.
====
Regarding the question of whether the AS honors previous RPTs (K, L): I suspect this is a bit more complex, partially because any RPT could cover more than one resource already, so L is a possibility at any time. The "previous RPT" case would happen when the client chooses to bring a failed RPT to the token endpoint and asks for an RPT that won't fail. The AS has a choice too (as I put it in a recent message):
1. *(Client can bring no RPT and ask for one -- not a concern)* 1. *(AS can issue a new RPT A -- not a concern)* 2. Client can bring RPT A that doesn't have a permission for what it wants to do and ask for an RPT that works for what it wants to do 1. *AS is allowed to reissue the existing RPT A* (same RPT string), having added the relevant permissions to it 2. *AS can issue a new RPT B* (different RPT string), having added the relevant permissions to it 1. *AS can invalidate the old RPT A* that the client brought it upon this action 2. *AS can retain the validity of the old RPT A* that the client brought it and any of its permission(s) -- presumably ones that are still good and that the client didn't just try to exercise but found wanting
(Justin, you suggested that if the AS issues a new token, we say "the AS SHOULD revoke the existing RPT, if possible" and "the client MUST discard its previous RPT" on the reasoning that this matches OAuth refresh token guidance, which I like.)
You can see I was presuming that reissuing an existing RPT would *upgrade* that token. If it contained totally orthogonal resources and scopes relative to the current request, it could still be upgraded with a relevant resource and scope.
Is it also possible that the AS's TTL strategy and/or the RO's other changes in policy might also dictate "cleaning house", so to speak, and *downgrading* other permissions while it's upgrading the permission of interest? Or is this not fair game?
====
Regarding the pièce de résistance (French, meaning "piece of resistance" <https://books.google.com/books?id=8nx8v2FVZ24C&pg=PA147&lpg=PA147&dq=dave+barry+pi%C3%A8ce+de+r%C3%A9sistance&source=bl&ots=lr_9wRH338&sig=HnlVkPEvc425BdAJMonwNlL3w_I&hl=en&sa=X&ved=0ahUKEwihkqKm-rHRAhUB5WMKHYRXD9EQ6AEIHDAA#v=onepage&q=dave%20barry%20pi%C3%A8ce%20de%20r%C3%A9sistance&f=false>), the pseudocode, it seems to be pretty complete and logical, and I like that it preserves George's rationale of client registration as a round-trip-saving exercise. The only thing I can't find in it (and this whole discussion, really) is some statement of how scopes match to resources, given that identical scopes may appear on multiple resources. I'm hoping that doesn't have to have to be so much a complication as a matching strategy.
*Eve Maler *Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Fri, Jan 6, 2017 at 2:56 PM, Justin Richer <jricher@mit.edu> wrote:
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
<Mail Attachment.png>
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma

So here is my attempt at a simple example: Lets assume that Alice is using photos.example.com (RS) to manage her photos and copmonkey.example.com (UMA AS) to protect her photos. Bob wants to access Alice's landscape photo album ( photos.example.com/photos/alice/landscape). Bob uses the myPhotos app (Client). scopes registered by myPhotos at AS registration time ClientReg = (view, download, print) ClientRegisteredDefaults = (view) [Note, I don't believe the OAuth2 dynamic client registration allows for registering defaults, but I'm including it because it's part of this thread.] scopes registered by photos.example.com for Alice's landscape photos resource set RSReg = (view, share, download, print) [resource set id = 1234] Alice defines policy for the registered scopes for her landscape photos view = promise not to steal share = promise not to steal download = family members only print = NOT ALLOWED ROPolicy = (view, share, download) Bob's myPhotos app attempts to access photos.example.com/photos/alice/landscape and receives back a permission ticket that identifies scopes (view, share). The app presents the permission ticket to the token endpoint along with scopes (print, resale). RSTicket = (view, share) ClientReq = (print, resale) [I'm going to ignore the PrevRPT because I think is has some issues unless defined in a very particular way.] So, now that all the sets are defined we can apply the set math: Requested = union(intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) Requested = union(intersection((print,resale),(view,download,print)),(view,share),(view)) Requested = (view,share,print) Evaluating the policy defined for the registered resource set id:1234, Alice and prohibited the use of the print scope. So the ROPolicy is limited to (view,share,download). To determine which claims Bob must meet, we have to determine which scopes are in play for resource set id:1234 Scopes = intersection(Requested, ROPolicy) Scopes = intersection((view,share,print),(view,share,download)) Scopes = (view,share) Bob meets the necessary claims for scopes (view,share) as defined by the Alice's policy for the 'view' and 'share' scopes on her landscape photos. Bob's myPhotos app is granted an RPT that allows for (view,share) for resource set id:1234 RPTResult = RSID_1234(view,share) Please check the math! :) To try an simplify the steps, for each /token call with uma grant 1. Determine the set of requested scopes 1. Requested = union( intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) 2. Determine the set of scopes allowed by the Resource Owner 1. Evaluate the policy for the identified resource set(s) and determine if any of the registered scopes are not allowed 2. ROPolicy = list of scopes allowed by RO 3. Determine the set of scopes for which RqP must meet claims in order to receive an RPT 1. Scopes = intersection (Requested,ROPolicy) 4. Determine the set of claims necessary for Scopes as they pertain to the specified resource set(s) 1. Claims = union(resource_set_claims(rsid,scopes)) 5. Request RqP to meet Claims 6. Assuming RqP meets Claims, issue RPT Thanks, George P.S. Note that I think in step 3 we really want two sets of scopes. RequiredScopes and AdditionalScopes as it's possible for the RqP to meet the claims of the scopes in the RSTicket but not the possible additional scopes. This would look like... RequiredScopes = intersection(RSTicket,ROPolicy) AdditionalScopes = intersection(difference(Requested,RSTicket),ROPolicy) On Wed, Jan 11, 2017 at 7:31 PM Eve Maler <eve@xmlgrrl.com> wrote:
I have to admit you guys have now gone beyond my ability to follow. :-) If someone could summarize in English pseudo-spec language, and a simple example, I would be very very grateful. I would like any discussion of this tomorrow to to be efficient, because there's lots of other stuff to discuss too.
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 10, 2017 at 2:02 PM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Well, in fact I was suggesting:
Requested = union(intersection(ClientReg, ClientReq), RSTicket, ClientRegisteredDefaults)
But I can live with ClientRegisteredDefaults being an off-spec AS extension, so yes :)
Cheers James
On 10 January 2017 at 19:16, George Fletcher <george.fletcher@teamaol.com> wrote:
Yes, though I'd feel better with James weighing in to make sure I understood his idea correctly:)
On Tue, Jan 10, 2017 at 2:08 PM Justin Richer <jricher@mit.edu> wrote:
Interesting thought — so are you suggesting that:
Requested = union(intersection(ClientReg, ClientReq), RSTicket)
That would let ClientReg be a limiting set but wouldn’t leave out the RS requesting more scopes (or policies granting more scopes) than the client itself asked for.
I could live with that interpretation.
— Justin
On Jan 10, 2017, at 12:01 PM, George Fletcher <george.fletcher@teamaol.com> wrote:
I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time.
Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket.
On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that.
So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting.
Cheers James
On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com> wrote:
So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Like I said, I'm talking about scope values requested by the client, *not* by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers James
On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry ( https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu> wrote:
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544

Great writeup! I agree with all of this except the PS: I don't see (and didn't intend) the ROPolicy to represent the single policy on the resource, as I believe there will be multiple policies that may apply. So ROPolicy is intended to represent "the scopes defined in the RO's policy where said policy has been fulfilled by the RqP" -- so it's really "scopes the RqP qualifies for based on RO's policy". In other words, it's post-calculation of the policy, not pre-calculation. Therefore treating it as a single set (not split into required/extra) is appropriate. I think that the required/extra split is interesting, but only to the extent that the AS wants to differentiate to the RqP what they need to prove in order to move forward. That's an internal policy engine detail, and I honestly think that in the wild we're not going to see a ton of that. At the end of the day, the scopes are going to be approved or not, and therefore in the set or not. -- Justin On 1/12/2017 8:24 AM, George Fletcher wrote:
So here is my attempt at a simple example:
Lets assume that Alice is using photos.example.com <http://photos.example.com> (RS) to manage her photos and copmonkey.example.com <http://copmonkey.example.com> (UMA AS) to protect her photos. Bob wants to access Alice's landscape photo album (photos.example.com/photos/alice/landscape <http://photos.example.com/photos/alice/landscape>). Bob uses the myPhotos app (Client).
scopes registered by myPhotos at AS registration time ClientReg = (view, download, print) ClientRegisteredDefaults = (view) [Note, I don't believe the OAuth2 dynamic client registration allows for registering defaults, but I'm including it because it's part of this thread.]
scopes registered by photos.example.com <http://photos.example.com> for Alice's landscape photos resource set RSReg = (view, share, download, print) [resource set id = 1234]
Alice defines policy for the registered scopes for her landscape photos view = promise not to steal share = promise not to steal download = family members only print = NOT ALLOWED
ROPolicy = (view, share, download)
Bob's myPhotos app attempts to access photos.example.com/photos/alice/landscape <http://photos.example.com/photos/alice/landscape> and receives back a permission ticket that identifies scopes (view, share). The app presents the permission ticket to the token endpoint along with scopes (print, resale).
RSTicket = (view, share) ClientReq = (print, resale)
[I'm going to ignore the PrevRPT because I think is has some issues unless defined in a very particular way.]
So, now that all the sets are defined we can apply the set math:
Requested = union(intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) Requested = union(intersection((print,resale),(view,download,print)),(view,share),(view)) Requested = (view,share,print)
Evaluating the policy defined for the registered resource set id:1234, Alice and prohibited the use of the print scope. So the ROPolicy is limited to (view,share,download).
To determine which claims Bob must meet, we have to determine which scopes are in play for resource set id:1234
Scopes = intersection(Requested, ROPolicy) Scopes = intersection((view,share,print),(view,share,download)) Scopes = (view,share)
Bob meets the necessary claims for scopes (view,share) as defined by the Alice's policy for the 'view' and 'share' scopes on her landscape photos. Bob's myPhotos app is granted an RPT that allows for (view,share) for resource set id:1234
RPTResult = RSID_1234(view,share)
Please check the math! :)
To try an simplify the steps, for each /token call with uma grant
1. Determine the set of requested scopes 1. Requested = union( intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) 2. Determine the set of scopes allowed by the Resource Owner 1. Evaluate the policy for the identified resource set(s) and determine if any of the registered scopes are not allowed 2. ROPolicy = list of scopes allowed by RO 3. Determine the set of scopes for which RqP must meet claims in order to receive an RPT 1. Scopes = intersection (Requested,ROPolicy) 4. Determine the set of claims necessary for Scopes as they pertain to the specified resource set(s) 1. Claims = union(resource_set_claims(rsid,scopes)) 5. Request RqP to meet Claims 6. Assuming RqP meets Claims, issue RPT
Thanks, George
P.S. Note that I think in step 3 we really want two sets of scopes. RequiredScopes and AdditionalScopes as it's possible for the RqP to meet the claims of the scopes in the RSTicket but not the possible additional scopes. This would look like... RequiredScopes = intersection(RSTicket,ROPolicy) AdditionalScopes = intersection(difference(Requested,RSTicket),ROPolicy)
On Wed, Jan 11, 2017 at 7:31 PM Eve Maler <eve@xmlgrrl.com <mailto:eve@xmlgrrl.com>> wrote:
I have to admit you guys have now gone beyond my ability to follow. :-) If someone could summarize in English pseudo-spec language, and a simple example, I would be very very grateful. I would like any discussion of this tomorrow to to be efficient, because there's lots of other stuff to discuss too.
*Eve Maler *Cell +1 425.345.6756 <tel:%28425%29%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 10, 2017 at 2:02 PM, James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote:
Well, in fact I was suggesting:
Requested = union(intersection(ClientReg, ClientReq), RSTicket, ClientRegisteredDefaults)
But I can live with ClientRegisteredDefaults being an off-spec AS extension, so yes :)
Cheers James
On 10 January 2017 at 19:16, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote:
Yes, though I'd feel better with James weighing in to make sure I understood his idea correctly:)
On Tue, Jan 10, 2017 at 2:08 PM Justin Richer <jricher@mit.edu <mailto:jricher@mit.edu>> wrote:
Interesting thought — so are you suggesting that:
Requested = union(intersection(ClientReg, ClientReq), RSTicket)
That would let ClientReg be a limiting set but wouldn’t leave out the RS requesting more scopes (or policies granting more scopes) than the client itself asked for.
I could live with that interpretation.
— Justin
On Jan 10, 2017, at 12:01 PM, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote:
I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time.
Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket.
On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote:
Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that.
So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting.
Cheers James
On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote:
So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote:
Like I said, I'm talking about scope values requested by the client, /not/ by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers James
On 9 January 2017 at 22:51, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote:
Hi James,
I may have misunderstood, but I don't think with UMA there is anyway to say a client can only ask for scopes within this "set". (referencing your last paragraph).
Because of the dynamic nature of scopes and permissions tickets, a key capability of a client within UMA is the ability to get access to a resource that requires a scope the client has never even "seen" before. The key to be able to get authorized for this new scope is the ability to mean the ROPolicy for the requested resource. If the client/RqP can meet the required policy, then the RPT is granted the associated scope(s).
I can envision an AS defining a "black list" of scopes that a particular client could NEVER be authorized for, but this seems AS specific and out of scope for UMA.
Thanks, George
On Mon, Jan 9, 2017 at 4:06 AM James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote:
This seems well thought out, thanks Justin. I've got just one concern:
I'm uneasy about using the client registered scopes as 'default scopes' in the case of UMA, when RFC7591 states that registered scopes represent "scope values that the client can use when requesting access tokens" - as you stated in Thursday's call. I'm particularly concerned about how any of this plays out when the client is trying to be both a vanilla OAuth (or OpenID Connect) client as well as an UMA client. If the client registers for scopes "openid profile view edit", then they must explicitly request openid and profile scope values in the token request in order to get an access token that contains those scopes, but if they present a permission ticket as well, we're saying they view and edit will automatically get evaluated/added without the client knowing about it.
I would prefer that we submit an extra 'default_scope' attribute to the OAuth Dynamic Client Registration Metadata Registry (https://tools.ietf.org/html/rfc7591#section-4) to disambiguate from the existing 'scope' field. The client could then register with scope "openid profile edit" and default_scope of "view".
This also has an extra advantage of being able to use the registered scope field to block requests for scope values that have not been registered for the client - i.e. client registers for scope A, has a permission ticket for scope B, but requests scope C in the token request, which should then result in an 'invalid_scope' response.
Cheers James
On 8 January 2017 at 21:05, Justin Richer <jricher@mit.edu <mailto:jricher@mit.edu>> wrote:
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma

Thanks Justin, OK, I see the difference in how we perceive ROPolicy and your perspective probably tweaks my write-up a little. Not sure yet whether I agree :-) If the ROPolicy is the set of scopes the RqP has already met, how can it be a limiting factor? The RqP has to have the mechanism to provide new claims to meet to "new" scopes? I also do not believe that there is a 1:1 relationship between scope name and claims required to meet that scope (see my other email from yesterday outside this thread). There is a 1:1 relationship between the resource_set_id:scope tuple and the claims required to meet that scope. Thanks, George On Thu, Jan 12, 2017 at 9:47 AM Justin Richer <jricher@mit.edu> wrote:
Great writeup! I agree with all of this except the PS:
I don't see (and didn't intend) the ROPolicy to represent the single policy on the resource, as I believe there will be multiple policies that may apply. So ROPolicy is intended to represent "the scopes defined in the RO's policy where said policy has been fulfilled by the RqP" -- so it's really "scopes the RqP qualifies for based on RO's policy". In other words, it's post-calculation of the policy, not pre-calculation. Therefore treating it as a single set (not split into required/extra) is appropriate.
I think that the required/extra split is interesting, but only to the extent that the AS wants to differentiate to the RqP what they need to prove in order to move forward. That's an internal policy engine detail, and I honestly think that in the wild we're not going to see a ton of that. At the end of the day, the scopes are going to be approved or not, and therefore in the set or not.
-- Justin
On 1/12/2017 8:24 AM, George Fletcher wrote:
So here is my attempt at a simple example:
Lets assume that Alice is using photos.example.com (RS) to manage her photos and copmonkey.example.com (UMA AS) to protect her photos. Bob wants to access Alice's landscape photo album ( photos.example.com/photos/alice/landscape). Bob uses the myPhotos app (Client).
scopes registered by myPhotos at AS registration time ClientReg = (view, download, print) ClientRegisteredDefaults = (view) [Note, I don't believe the OAuth2 dynamic client registration allows for registering defaults, but I'm including it because it's part of this thread.]
scopes registered by photos.example.com for Alice's landscape photos resource set RSReg = (view, share, download, print) [resource set id = 1234]
Alice defines policy for the registered scopes for her landscape photos view = promise not to steal share = promise not to steal download = family members only print = NOT ALLOWED
ROPolicy = (view, share, download)
Bob's myPhotos app attempts to access photos.example.com/photos/alice/landscape and receives back a permission ticket that identifies scopes (view, share). The app presents the permission ticket to the token endpoint along with scopes (print, resale).
RSTicket = (view, share) ClientReq = (print, resale)
[I'm going to ignore the PrevRPT because I think is has some issues unless defined in a very particular way.]
So, now that all the sets are defined we can apply the set math:
Requested = union(intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) Requested = union(intersection((print,resale),(view,download,print)),(view,share),(view)) Requested = (view,share,print)
Evaluating the policy defined for the registered resource set id:1234, Alice and prohibited the use of the print scope. So the ROPolicy is limited to (view,share,download).
To determine which claims Bob must meet, we have to determine which scopes are in play for resource set id:1234
Scopes = intersection(Requested, ROPolicy) Scopes = intersection((view,share,print),(view,share,download)) Scopes = (view,share)
Bob meets the necessary claims for scopes (view,share) as defined by the Alice's policy for the 'view' and 'share' scopes on her landscape photos. Bob's myPhotos app is granted an RPT that allows for (view,share) for resource set id:1234
RPTResult = RSID_1234(view,share)
Please check the math! :)
To try an simplify the steps, for each /token call with uma grant
1. Determine the set of requested scopes 1. Requested = union( intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) 2. Determine the set of scopes allowed by the Resource Owner 1. Evaluate the policy for the identified resource set(s) and determine if any of the registered scopes are not allowed 2. ROPolicy = list of scopes allowed by RO 3. Determine the set of scopes for which RqP must meet claims in order to receive an RPT 1. Scopes = intersection (Requested,ROPolicy) 4. Determine the set of claims necessary for Scopes as they pertain to the specified resource set(s) 1. Claims = union(resource_set_claims(rsid,scopes)) 5. Request RqP to meet Claims 6. Assuming RqP meets Claims, issue RPT
Thanks, George
P.S. Note that I think in step 3 we really want two sets of scopes. RequiredScopes and AdditionalScopes as it's possible for the RqP to meet the claims of the scopes in the RSTicket but not the possible additional scopes. This would look like... RequiredScopes = intersection(RSTicket,ROPolicy) AdditionalScopes = intersection(difference(Requested,RSTicket),ROPolicy)
On Wed, Jan 11, 2017 at 7:31 PM Eve Maler <eve@xmlgrrl.com> wrote:
I have to admit you guys have now gone beyond my ability to follow. :-) If someone could summarize in English pseudo-spec language, and a simple example, I would be very very grateful. I would like any discussion of this tomorrow to to be efficient, because there's lots of other stuff to discuss too.
*Eve Maler *Cell +1 425.345.6756 <%28425%29%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 10, 2017 at 2:02 PM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Well, in fact I was suggesting:
Requested = union(intersection(ClientReg, ClientReq), RSTicket, ClientRegisteredDefaults)
But I can live with ClientRegisteredDefaults being an off-spec AS extension, so yes :)
Cheers James
On 10 January 2017 at 19:16, George Fletcher <george.fletcher@teamaol.com> wrote:
Yes, though I'd feel better with James weighing in to make sure I understood his idea correctly:)
On Tue, Jan 10, 2017 at 2:08 PM Justin Richer <jricher@mit.edu> wrote:
Interesting thought — so are you suggesting that:
Requested = union(intersection(ClientReg, ClientReq), RSTicket)
That would let ClientReg be a limiting set but wouldn’t leave out the RS requesting more scopes (or policies granting more scopes) than the client itself asked for.
I could live with that interpretation.
— Justin
On Jan 10, 2017, at 12:01 PM, George Fletcher <george.fletcher@teamaol.com> wrote:
I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time.
Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket.
On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that.
So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting.
Cheers James
On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com> wrote:
So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Like I said, I'm talking about scope values requested by the client, *not* by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544

I think you may still be thinking of this in a different part of the process than I am. For me, the whole set math discussion takes place *after* all the claims have been submitted, *after* the AS decides to make a token, *after* any redirects and ticket processing. This is answering the AS's question: "I've decided to make an RPT, what do I put into it?" So ROPolicy is the set of scopes defined in whichever policy of the RO on that resource has been fulfilled by the claims that the RqP/client have presented throughout the process up to this point. The RqP is not going to be presenting any more claims or meeting new scopes or anything anymore. All of that has been decided and is over at this point. So it's a limiting factor in the set math *because* you can't grant any new scopes that aren't approved by the RO's policies (and fulfilled by the RqP). The RqP and client already had their chance to request scopes (ClientReq) and provide claims, and this represents the *results* of that process. If they haven't presented the right claims to get a scope they wanted, then they don't get that scope. If there's not a policy that allows the scope they wanted in the first place, they don't get that scope because they can't provide claims to fulfill a policy (which doesn't exist) to provide that scope. I agree about the relationships via scopes and claims and resources, didn't intend to imply a different model. Everything in this is contextual to the resource except for ClientReg and PrevRPT, and even PrevRPT's scopes will almost certainly be contextual to resources as well. -- Justin On 1/12/2017 10:07 AM, George Fletcher wrote:
Thanks Justin,
OK, I see the difference in how we perceive ROPolicy and your perspective probably tweaks my write-up a little. Not sure yet whether I agree :-)
If the ROPolicy is the set of scopes the RqP has already met, how can it be a limiting factor? The RqP has to have the mechanism to provide new claims to meet to "new" scopes?
I also do not believe that there is a 1:1 relationship between scope name and claims required to meet that scope (see my other email from yesterday outside this thread). There is a 1:1 relationship between the resource_set_id:scope tuple and the claims required to meet that scope.
Thanks, George
On Thu, Jan 12, 2017 at 9:47 AM Justin Richer <jricher@mit.edu <mailto:jricher@mit.edu>> wrote:
Great writeup! I agree with all of this except the PS:
I don't see (and didn't intend) the ROPolicy to represent the single policy on the resource, as I believe there will be multiple policies that may apply. So ROPolicy is intended to represent "the scopes defined in the RO's policy where said policy has been fulfilled by the RqP" -- so it's really "scopes the RqP qualifies for based on RO's policy". In other words, it's post-calculation of the policy, not pre-calculation. Therefore treating it as a single set (not split into required/extra) is appropriate.
I think that the required/extra split is interesting, but only to the extent that the AS wants to differentiate to the RqP what they need to prove in order to move forward. That's an internal policy engine detail, and I honestly think that in the wild we're not going to see a ton of that. At the end of the day, the scopes are going to be approved or not, and therefore in the set or not.
-- Justin
On 1/12/2017 8:24 AM, George Fletcher wrote:
So here is my attempt at a simple example:
Lets assume that Alice is using photos.example.com <http://photos.example.com> (RS) to manage her photos and copmonkey.example.com <http://copmonkey.example.com> (UMA AS) to protect her photos. Bob wants to access Alice's landscape photo album (photos.example.com/photos/alice/landscape <http://photos.example.com/photos/alice/landscape>). Bob uses the myPhotos app (Client).
scopes registered by myPhotos at AS registration time ClientReg = (view, download, print) ClientRegisteredDefaults = (view) [Note, I don't believe the OAuth2 dynamic client registration allows for registering defaults, but I'm including it because it's part of this thread.]
scopes registered by photos.example.com <http://photos.example.com> for Alice's landscape photos resource set RSReg = (view, share, download, print) [resource set id = 1234]
Alice defines policy for the registered scopes for her landscape photos view = promise not to steal share = promise not to steal download = family members only print = NOT ALLOWED
ROPolicy = (view, share, download)
Bob's myPhotos app attempts to access photos.example.com/photos/alice/landscape <http://photos.example.com/photos/alice/landscape> and receives back a permission ticket that identifies scopes (view, share). The app presents the permission ticket to the token endpoint along with scopes (print, resale).
RSTicket = (view, share) ClientReq = (print, resale)
[I'm going to ignore the PrevRPT because I think is has some issues unless defined in a very particular way.]
So, now that all the sets are defined we can apply the set math:
Requested = union(intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) Requested = union(intersection((print,resale),(view,download,print)),(view,share),(view)) Requested = (view,share,print)
Evaluating the policy defined for the registered resource set id:1234, Alice and prohibited the use of the print scope. So the ROPolicy is limited to (view,share,download).
To determine which claims Bob must meet, we have to determine which scopes are in play for resource set id:1234
Scopes = intersection(Requested, ROPolicy) Scopes = intersection((view,share,print),(view,share,download)) Scopes = (view,share)
Bob meets the necessary claims for scopes (view,share) as defined by the Alice's policy for the 'view' and 'share' scopes on her landscape photos. Bob's myPhotos app is granted an RPT that allows for (view,share) for resource set id:1234
RPTResult = RSID_1234(view,share)
Please check the math! :)
To try an simplify the steps, for each /token call with uma grant
1. Determine the set of requested scopes 1. Requested = union( intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) 2. Determine the set of scopes allowed by the Resource Owner 1. Evaluate the policy for the identified resource set(s) and determine if any of the registered scopes are not allowed 2. ROPolicy = list of scopes allowed by RO 3. Determine the set of scopes for which RqP must meet claims in order to receive an RPT 1. Scopes = intersection (Requested,ROPolicy) 4. Determine the set of claims necessary for Scopes as they pertain to the specified resource set(s) 1. Claims = union(resource_set_claims(rsid,scopes)) 5. Request RqP to meet Claims 6. Assuming RqP meets Claims, issue RPT
Thanks, George
P.S. Note that I think in step 3 we really want two sets of scopes. RequiredScopes and AdditionalScopes as it's possible for the RqP to meet the claims of the scopes in the RSTicket but not the possible additional scopes. This would look like... RequiredScopes = intersection(RSTicket,ROPolicy) AdditionalScopes = intersection(difference(Requested,RSTicket),ROPolicy)
On Wed, Jan 11, 2017 at 7:31 PM Eve Maler <eve@xmlgrrl.com <mailto:eve@xmlgrrl.com>> wrote:
I have to admit you guys have now gone beyond my ability to follow. :-) If someone could summarize in English pseudo-spec language, and a simple example, I would be very very grateful. I would like any discussion of this tomorrow to to be efficient, because there's lots of other stuff to discuss too.
*Eve Maler *Cell +1 425.345.6756 <tel:%28425%29%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 10, 2017 at 2:02 PM, James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote:
Well, in fact I was suggesting:
Requested = union(intersection(ClientReg, ClientReq), RSTicket, ClientRegisteredDefaults)
But I can live with ClientRegisteredDefaults being an off-spec AS extension, so yes :)
Cheers James
On 10 January 2017 at 19:16, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote:
Yes, though I'd feel better with James weighing in to make sure I understood his idea correctly:)
On Tue, Jan 10, 2017 at 2:08 PM Justin Richer <jricher@mit.edu <mailto:jricher@mit.edu>> wrote:
Interesting thought — so are you suggesting that:
Requested = union(intersection(ClientReg, ClientReq), RSTicket)
That would let ClientReg be a limiting set but wouldn’t leave out the RS requesting more scopes (or policies granting more scopes) than the client itself asked for.
I could live with that interpretation.
— Justin
On Jan 10, 2017, at 12:01 PM, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote:
I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time.
Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket.
On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote:
Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that.
So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting.
Cheers James
On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote:
So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote:
Like I said, I'm talking about scope values requested by the client, /not/ by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com <mailto:george.fletcher@teamaol.com>> wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts <james.phillpotts@forgerock.com <mailto:james.phillpotts@forgerock.com>> wrote:
Hi George,
I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth.
Cheers
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544

+1, as AS policy for the specific grant, and then apply context based algorithms to generate each marginal (next if different context) union. From: wg-uma-bounces@kantarainitiative.org [mailto:wg-uma-bounces@kantarainitiative.org] On Behalf Of Justin Richer Sent: Friday, January 13, 2017 8:13 AM To: George Fletcher; Eve Maler; James Phillpotts Cc: wg-uma@kantarainitiative.org UMA Subject: Re: [WG-UMA] Set Math Discussion I think you may still be thinking of this in a different part of the process than I am. For me, the whole set math discussion takes place *after* all the claims have been submitted, *after* the AS decides to make a token, *after* any redirects and ticket processing. This is answering the AS's question: "I've decided to make an RPT, what do I put into it?" So ROPolicy is the set of scopes defined in whichever policy of the RO on that resource has been fulfilled by the claims that the RqP/client have presented throughout the process up to this point. The RqP is not going to be presenting any more claims or meeting new scopes or anything anymore. All of that has been decided and is over at this point. So it's a limiting factor in the set math *because* you can't grant any new scopes that aren't approved by the RO's policies (and fulfilled by the RqP). The RqP and client already had their chance to request scopes (ClientReq) and provide claims, and this represents the *results* of that process. If they haven't presented the right claims to get a scope they wanted, then they don't get that scope. If there's not a policy that allows the scope they wanted in the first place, they don't get that scope because they can't provide claims to fulfill a policy (which doesn't exist) to provide that scope. I agree about the relationships via scopes and claims and resources, didn't intend to imply a different model. Everything in this is contextual to the resource except for ClientReg and PrevRPT, and even PrevRPT's scopes will almost certainly be contextual to resources as well. -- Justin On 1/12/2017 10:07 AM, George Fletcher wrote: Thanks Justin, OK, I see the difference in how we perceive ROPolicy and your perspective probably tweaks my write-up a little. Not sure yet whether I agree :-) If the ROPolicy is the set of scopes the RqP has already met, how can it be a limiting factor? The RqP has to have the mechanism to provide new claims to meet to "new" scopes? I also do not believe that there is a 1:1 relationship between scope name and claims required to meet that scope (see my other email from yesterday outside this thread). There is a 1:1 relationship between the resource_set_id:scope tuple and the claims required to meet that scope. Thanks, George On Thu, Jan 12, 2017 at 9:47 AM Justin Richer <jricher@mit.edu> wrote: Great writeup! I agree with all of this except the PS: I don't see (and didn't intend) the ROPolicy to represent the single policy on the resource, as I believe there will be multiple policies that may apply. So ROPolicy is intended to represent "the scopes defined in the RO's policy where said policy has been fulfilled by the RqP" -- so it's really "scopes the RqP qualifies for based on RO's policy". In other words, it's post-calculation of the policy, not pre-calculation. Therefore treating it as a single set (not split into required/extra) is appropriate. I think that the required/extra split is interesting, but only to the extent that the AS wants to differentiate to the RqP what they need to prove in order to move forward. That's an internal policy engine detail, and I honestly think that in the wild we're not going to see a ton of that. At the end of the day, the scopes are going to be approved or not, and therefore in the set or not. -- Justin On 1/12/2017 8:24 AM, George Fletcher wrote: So here is my attempt at a simple example: Lets assume that Alice is using photos.example.com (RS) to manage her photos and copmonkey.example.com (UMA AS) to protect her photos. Bob wants to access Alice's landscape photo album (photos.example.com/photos/alice/landscape). Bob uses the myPhotos app (Client). scopes registered by myPhotos at AS registration time ClientReg = (view, download, print) ClientRegisteredDefaults = (view) [Note, I don't believe the OAuth2 dynamic client registration allows for registering defaults, but I'm including it because it's part of this thread.] scopes registered by photos.example.com for Alice's landscape photos resource set RSReg = (view, share, download, print) [resource set id = 1234] Alice defines policy for the registered scopes for her landscape photos view = promise not to steal share = promise not to steal download = family members only print = NOT ALLOWED ROPolicy = (view, share, download) Bob's myPhotos app attempts to access photos.example.com/photos/alice/landscape and receives back a permission ticket that identifies scopes (view, share). The app presents the permission ticket to the token endpoint along with scopes (print, resale). RSTicket = (view, share) ClientReq = (print, resale) [I'm going to ignore the PrevRPT because I think is has some issues unless defined in a very particular way.] So, now that all the sets are defined we can apply the set math: Requested = union(intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) Requested = union(intersection((print,resale),(view,download,print)),(view,share),(view)) Requested = (view,share,print) Evaluating the policy defined for the registered resource set id:1234, Alice and prohibited the use of the print scope. So the ROPolicy is limited to (view,share,download). To determine which claims Bob must meet, we have to determine which scopes are in play for resource set id:1234 Scopes = intersection(Requested, ROPolicy) Scopes = intersection((view,share,print),(view,share,download)) Scopes = (view,share) Bob meets the necessary claims for scopes (view,share) as defined by the Alice's policy for the 'view' and 'share' scopes on her landscape photos. Bob's myPhotos app is granted an RPT that allows for (view,share) for resource set id:1234 RPTResult = RSID_1234(view,share) Please check the math! :) To try an simplify the steps, for each /token call with uma grant 1. Determine the set of requested scopes 1. Requested = union( intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) 2. Determine the set of scopes allowed by the Resource Owner 1. Evaluate the policy for the identified resource set(s) and determine if any of the registered scopes are not allowed 2. ROPolicy = list of scopes allowed by RO 3. Determine the set of scopes for which RqP must meet claims in order to receive an RPT 1. Scopes = intersection (Requested,ROPolicy) 4. Determine the set of claims necessary for Scopes as they pertain to the specified resource set(s) 1. Claims = union(resource_set_claims(rsid,scopes)) 5. Request RqP to meet Claims 6. Assuming RqP meets Claims, issue RPT Thanks, George P.S. Note that I think in step 3 we really want two sets of scopes. RequiredScopes and AdditionalScopes as it's possible for the RqP to meet the claims of the scopes in the RSTicket but not the possible additional scopes. This would look like... RequiredScopes = intersection(RSTicket,ROPolicy) AdditionalScopes = intersection(difference(Requested,RSTicket),ROPolicy) On Wed, Jan 11, 2017 at 7:31 PM Eve Maler <eve@xmlgrrl.com> wrote: I have to admit you guys have now gone beyond my ability to follow. :-) If someone could summarize in English pseudo-spec language, and a simple example, I would be very very grateful. I would like any discussion of this tomorrow to to be efficient, because there's lots of other stuff to discuss too. Eve Maler Cell +1 425.345.6756 <tel:%28425%29%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl On Tue, Jan 10, 2017 at 2:02 PM, James Phillpotts <james.phillpotts@forgerock.com> wrote: Well, in fact I was suggesting: Requested = union(intersection(ClientReg, ClientReq), RSTicket, ClientRegisteredDefaults) But I can live with ClientRegisteredDefaults being an off-spec AS extension, so yes :) Cheers James On 10 January 2017 at 19:16, George Fletcher <george.fletcher@teamaol.com> wrote: Yes, though I'd feel better with James weighing in to make sure I understood his idea correctly:) On Tue, Jan 10, 2017 at 2:08 PM Justin Richer <jricher@mit.edu> wrote: Interesting thought — so are you suggesting that: Requested = union(intersection(ClientReg, ClientReq), RSTicket) That would let ClientReg be a limiting set but wouldn’t leave out the RS requesting more scopes (or policies granting more scopes) than the client itself asked for. I could live with that interpretation. — Justin On Jan 10, 2017, at 12:01 PM, George Fletcher <george.fletcher@teamaol.com> wrote: I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time. Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket. On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts <james.phillpotts@forgerock.com> wrote: Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that. So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting. Cheers James On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com> wrote: So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that? Thanks, George On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts <james.phillpotts@forgerock.com> wrote: Like I said, I'm talking about scope values requested by the client, not by the RS in the permission ticket. J. On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com> wrote: Hi James, I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT. So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:) Thanks, George On Tue, Jan 10, 2017 at 10:45 AM James Phillpotts <james.phillpotts@forgerock.com> wrote: Hi George, I'm not sure I understand you - we're talking here about scope values that the client knows about itself, registers for, and can be requested separately from those that are in the permission ticket. As such, a degree of static-ness can be assumed, in the same way as it is in vanilla OAuth. Cheers -- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544

Yes, I agree with this and what we discussed on the call. Since ROPolicy is the result of all the AS assessment, claims gathering, etc, it is a limited factor in what can be returned. I hope we'll have time to talk about the AS assessment logic, but maybe people want that to be out of scope and let each AS do it however they want:) Thanks, George On Fri, Jan 13, 2017 at 8:12 AM Justin Richer <jricher@mit.edu> wrote:
I think you may still be thinking of this in a different part of the process than I am.
For me, the whole set math discussion takes place *after* all the claims have been submitted, *after* the AS decides to make a token, *after* any redirects and ticket processing. This is answering the AS's question: "I've decided to make an RPT, what do I put into it?"
So ROPolicy is the set of scopes defined in whichever policy of the RO on that resource has been fulfilled by the claims that the RqP/client have presented throughout the process up to this point. The RqP is not going to be presenting any more claims or meeting new scopes or anything anymore. All of that has been decided and is over at this point.
So it's a limiting factor in the set math *because* you can't grant any new scopes that aren't approved by the RO's policies (and fulfilled by the RqP). The RqP and client already had their chance to request scopes (ClientReq) and provide claims, and this represents the *results* of that process. If they haven't presented the right claims to get a scope they wanted, then they don't get that scope. If there's not a policy that allows the scope they wanted in the first place, they don't get that scope because they can't provide claims to fulfill a policy (which doesn't exist) to provide that scope.
I agree about the relationships via scopes and claims and resources, didn't intend to imply a different model. Everything in this is contextual to the resource except for ClientReg and PrevRPT, and even PrevRPT's scopes will almost certainly be contextual to resources as well.
-- Justin
On 1/12/2017 10:07 AM, George Fletcher wrote:
Thanks Justin,
OK, I see the difference in how we perceive ROPolicy and your perspective probably tweaks my write-up a little. Not sure yet whether I agree :-)
If the ROPolicy is the set of scopes the RqP has already met, how can it be a limiting factor? The RqP has to have the mechanism to provide new claims to meet to "new" scopes?
I also do not believe that there is a 1:1 relationship between scope name and claims required to meet that scope (see my other email from yesterday outside this thread). There is a 1:1 relationship between the resource_set_id:scope tuple and the claims required to meet that scope.
Thanks, George
On Thu, Jan 12, 2017 at 9:47 AM Justin Richer <jricher@mit.edu> wrote:
Great writeup! I agree with all of this except the PS:
I don't see (and didn't intend) the ROPolicy to represent the single policy on the resource, as I believe there will be multiple policies that may apply. So ROPolicy is intended to represent "the scopes defined in the RO's policy where said policy has been fulfilled by the RqP" -- so it's really "scopes the RqP qualifies for based on RO's policy". In other words, it's post-calculation of the policy, not pre-calculation. Therefore treating it as a single set (not split into required/extra) is appropriate.
I think that the required/extra split is interesting, but only to the extent that the AS wants to differentiate to the RqP what they need to prove in order to move forward. That's an internal policy engine detail, and I honestly think that in the wild we're not going to see a ton of that. At the end of the day, the scopes are going to be approved or not, and therefore in the set or not.
-- Justin
On 1/12/2017 8:24 AM, George Fletcher wrote:
So here is my attempt at a simple example:
Lets assume that Alice is using photos.example.com (RS) to manage her photos and copmonkey.example.com (UMA AS) to protect her photos. Bob wants to access Alice's landscape photo album ( photos.example.com/photos/alice/landscape). Bob uses the myPhotos app (Client).
scopes registered by myPhotos at AS registration time ClientReg = (view, download, print) ClientRegisteredDefaults = (view) [Note, I don't believe the OAuth2 dynamic client registration allows for registering defaults, but I'm including it because it's part of this thread.]
scopes registered by photos.example.com for Alice's landscape photos resource set RSReg = (view, share, download, print) [resource set id = 1234]
Alice defines policy for the registered scopes for her landscape photos view = promise not to steal share = promise not to steal download = family members only print = NOT ALLOWED
ROPolicy = (view, share, download)
Bob's myPhotos app attempts to access photos.example.com/photos/alice/landscape and receives back a permission ticket that identifies scopes (view, share). The app presents the permission ticket to the token endpoint along with scopes (print, resale).
RSTicket = (view, share) ClientReq = (print, resale)
[I'm going to ignore the PrevRPT because I think is has some issues unless defined in a very particular way.]
So, now that all the sets are defined we can apply the set math:
Requested = union(intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) Requested = union(intersection((print,resale),(view,download,print)),(view,share),(view)) Requested = (view,share,print)
Evaluating the policy defined for the registered resource set id:1234, Alice and prohibited the use of the print scope. So the ROPolicy is limited to (view,share,download).
To determine which claims Bob must meet, we have to determine which scopes are in play for resource set id:1234
Scopes = intersection(Requested, ROPolicy) Scopes = intersection((view,share,print),(view,share,download)) Scopes = (view,share)
Bob meets the necessary claims for scopes (view,share) as defined by the Alice's policy for the 'view' and 'share' scopes on her landscape photos. Bob's myPhotos app is granted an RPT that allows for (view,share) for resource set id:1234
RPTResult = RSID_1234(view,share)
Please check the math! :)
To try an simplify the steps, for each /token call with uma grant
1. Determine the set of requested scopes 1. Requested = union( intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) 2. Determine the set of scopes allowed by the Resource Owner 1. Evaluate the policy for the identified resource set(s) and determine if any of the registered scopes are not allowed 2. ROPolicy = list of scopes allowed by RO 3. Determine the set of scopes for which RqP must meet claims in order to receive an RPT 1. Scopes = intersection (Requested,ROPolicy) 4. Determine the set of claims necessary for Scopes as they pertain to the specified resource set(s) 1. Claims = union(resource_set_claims(rsid,scopes)) 5. Request RqP to meet Claims 6. Assuming RqP meets Claims, issue RPT
Thanks, George
P.S. Note that I think in step 3 we really want two sets of scopes. RequiredScopes and AdditionalScopes as it's possible for the RqP to meet the claims of the scopes in the RSTicket but not the possible additional scopes. This would look like... RequiredScopes = intersection(RSTicket,ROPolicy) AdditionalScopes = intersection(difference(Requested,RSTicket),ROPolicy)
On Wed, Jan 11, 2017 at 7:31 PM Eve Maler <eve@xmlgrrl.com> wrote:
I have to admit you guys have now gone beyond my ability to follow. :-) If someone could summarize in English pseudo-spec language, and a simple example, I would be very very grateful. I would like any discussion of this tomorrow to to be efficient, because there's lots of other stuff to discuss too.
*Eve Maler *Cell +1 425.345.6756 <%28425%29%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 10, 2017 at 2:02 PM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Well, in fact I was suggesting:
Requested = union(intersection(ClientReg, ClientReq), RSTicket, ClientRegisteredDefaults)
But I can live with ClientRegisteredDefaults being an off-spec AS extension, so yes :)
Cheers James
On 10 January 2017 at 19:16, George Fletcher <george.fletcher@teamaol.com> wrote:
Yes, though I'd feel better with James weighing in to make sure I understood his idea correctly:)
On Tue, Jan 10, 2017 at 2:08 PM Justin Richer <jricher@mit.edu> wrote:
Interesting thought — so are you suggesting that:
Requested = union(intersection(ClientReg, ClientReq), RSTicket)
That would let ClientReg be a limiting set but wouldn’t leave out the RS requesting more scopes (or policies granting more scopes) than the client itself asked for.
I could live with that interpretation.
— Justin
On Jan 10, 2017, at 12:01 PM, George Fletcher <george.fletcher@teamaol.com> wrote:
I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time.
Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket.
On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that.
So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting.
Cheers James
On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com> wrote:
So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Like I said, I'm talking about scope values requested by the client, *not* by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com> wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544

It's late in the (Thursday-to-Thursday) week for me to be working on spec text, but I do intend to try some in rev 12 for you to look at tonight. We talked a bit about having the set math "speak for itself" and letting each AS figure out implementation methods. We will have to be clear about *when* each state-change takes place, but I hope we don't have to be too detailed about the how. *Eve Maler*Cell +1 425.345.6756 | Skype: xmlgrrl | Twitter: @xmlgrrl On Fri, Jan 13, 2017 at 6:32 AM, George Fletcher < george.fletcher@teamaol.com> wrote:
Yes, I agree with this and what we discussed on the call. Since ROPolicy is the result of all the AS assessment, claims gathering, etc, it is a limited factor in what can be returned.
I hope we'll have time to talk about the AS assessment logic, but maybe people want that to be out of scope and let each AS do it however they want:)
Thanks, George
On Fri, Jan 13, 2017 at 8:12 AM Justin Richer <jricher@mit.edu> wrote:
I think you may still be thinking of this in a different part of the process than I am.
For me, the whole set math discussion takes place *after* all the claims have been submitted, *after* the AS decides to make a token, *after* any redirects and ticket processing. This is answering the AS's question: "I've decided to make an RPT, what do I put into it?"
So ROPolicy is the set of scopes defined in whichever policy of the RO on that resource has been fulfilled by the claims that the RqP/client have presented throughout the process up to this point. The RqP is not going to be presenting any more claims or meeting new scopes or anything anymore. All of that has been decided and is over at this point.
So it's a limiting factor in the set math *because* you can't grant any new scopes that aren't approved by the RO's policies (and fulfilled by the RqP). The RqP and client already had their chance to request scopes (ClientReq) and provide claims, and this represents the *results* of that process. If they haven't presented the right claims to get a scope they wanted, then they don't get that scope. If there's not a policy that allows the scope they wanted in the first place, they don't get that scope because they can't provide claims to fulfill a policy (which doesn't exist) to provide that scope.
I agree about the relationships via scopes and claims and resources, didn't intend to imply a different model. Everything in this is contextual to the resource except for ClientReg and PrevRPT, and even PrevRPT's scopes will almost certainly be contextual to resources as well.
-- Justin
On 1/12/2017 10:07 AM, George Fletcher wrote:
Thanks Justin,
OK, I see the difference in how we perceive ROPolicy and your perspective probably tweaks my write-up a little. Not sure yet whether I agree :-)
If the ROPolicy is the set of scopes the RqP has already met, how can it be a limiting factor? The RqP has to have the mechanism to provide new claims to meet to "new" scopes?
I also do not believe that there is a 1:1 relationship between scope name and claims required to meet that scope (see my other email from yesterday outside this thread). There is a 1:1 relationship between the resource_set_id:scope tuple and the claims required to meet that scope.
Thanks, George
On Thu, Jan 12, 2017 at 9:47 AM Justin Richer <jricher@mit.edu> wrote:
Great writeup! I agree with all of this except the PS:
I don't see (and didn't intend) the ROPolicy to represent the single policy on the resource, as I believe there will be multiple policies that may apply. So ROPolicy is intended to represent "the scopes defined in the RO's policy where said policy has been fulfilled by the RqP" -- so it's really "scopes the RqP qualifies for based on RO's policy". In other words, it's post-calculation of the policy, not pre-calculation. Therefore treating it as a single set (not split into required/extra) is appropriate.
I think that the required/extra split is interesting, but only to the extent that the AS wants to differentiate to the RqP what they need to prove in order to move forward. That's an internal policy engine detail, and I honestly think that in the wild we're not going to see a ton of that. At the end of the day, the scopes are going to be approved or not, and therefore in the set or not.
-- Justin
On 1/12/2017 8:24 AM, George Fletcher wrote:
So here is my attempt at a simple example:
Lets assume that Alice is using photos.example.com (RS) to manage her photos and copmonkey.example.com (UMA AS) to protect her photos. Bob wants to access Alice's landscape photo album (photos.example.com/photos/ alice/landscape). Bob uses the myPhotos app (Client).
scopes registered by myPhotos at AS registration time ClientReg = (view, download, print) ClientRegisteredDefaults = (view) [Note, I don't believe the OAuth2 dynamic client registration allows for registering defaults, but I'm including it because it's part of this thread.]
scopes registered by photos.example.com for Alice's landscape photos resource set RSReg = (view, share, download, print) [resource set id = 1234]
Alice defines policy for the registered scopes for her landscape photos view = promise not to steal share = promise not to steal download = family members only print = NOT ALLOWED
ROPolicy = (view, share, download)
Bob's myPhotos app attempts to access photos.example.com/photos/ alice/landscape and receives back a permission ticket that identifies scopes (view, share). The app presents the permission ticket to the token endpoint along with scopes (print, resale).
RSTicket = (view, share) ClientReq = (print, resale)
[I'm going to ignore the PrevRPT because I think is has some issues unless defined in a very particular way.]
So, now that all the sets are defined we can apply the set math:
Requested = union(intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) Requested = union(intersection((print,resale),(view,download,print)) ,(view,share),(view)) Requested = (view,share,print)
Evaluating the policy defined for the registered resource set id:1234, Alice and prohibited the use of the print scope. So the ROPolicy is limited to (view,share,download).
To determine which claims Bob must meet, we have to determine which scopes are in play for resource set id:1234
Scopes = intersection(Requested, ROPolicy) Scopes = intersection((view,share,print),(view,share,download)) Scopes = (view,share)
Bob meets the necessary claims for scopes (view,share) as defined by the Alice's policy for the 'view' and 'share' scopes on her landscape photos. Bob's myPhotos app is granted an RPT that allows for (view,share) for resource set id:1234
RPTResult = RSID_1234(view,share)
Please check the math! :)
To try an simplify the steps, for each /token call with uma grant
1. Determine the set of requested scopes 1. Requested = union( intersection(ClientReq,ClientReg), RSTicket, ClientRegisteredDefaults) 2. Determine the set of scopes allowed by the Resource Owner 1. Evaluate the policy for the identified resource set(s) and determine if any of the registered scopes are not allowed 2. ROPolicy = list of scopes allowed by RO 3. Determine the set of scopes for which RqP must meet claims in order to receive an RPT 1. Scopes = intersection (Requested,ROPolicy) 4. Determine the set of claims necessary for Scopes as they pertain to the specified resource set(s) 1. Claims = union(resource_set_claims(rsid,scopes)) 5. Request RqP to meet Claims 6. Assuming RqP meets Claims, issue RPT
Thanks, George
P.S. Note that I think in step 3 we really want two sets of scopes. RequiredScopes and AdditionalScopes as it's possible for the RqP to meet the claims of the scopes in the RSTicket but not the possible additional scopes. This would look like... RequiredScopes = intersection(RSTicket,ROPolicy) AdditionalScopes = intersection(difference( Requested,RSTicket),ROPolicy)
On Wed, Jan 11, 2017 at 7:31 PM Eve Maler <eve@xmlgrrl.com> wrote:
I have to admit you guys have now gone beyond my ability to follow. :-) If someone could summarize in English pseudo-spec language, and a simple example, I would be very very grateful. I would like any discussion of this tomorrow to to be efficient, because there's lots of other stuff to discuss too.
*Eve Maler *Cell +1 425.345.6756 <%28425%29%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 10, 2017 at 2:02 PM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Well, in fact I was suggesting:
Requested = union(intersection(ClientReg, ClientReq), RSTicket, ClientRegisteredDefaults)
But I can live with ClientRegisteredDefaults being an off-spec AS extension, so yes :)
Cheers James
On 10 January 2017 at 19:16, George Fletcher <george.fletcher@teamaol.com
wrote:
Yes, though I'd feel better with James weighing in to make sure I understood his idea correctly:)
On Tue, Jan 10, 2017 at 2:08 PM Justin Richer <jricher@mit.edu> wrote:
Interesting thought — so are you suggesting that:
Requested = union(intersection(ClientReg, ClientReq), RSTicket)
That would let ClientReg be a limiting set but wouldn’t leave out the RS requesting more scopes (or policies granting more scopes) than the client itself asked for.
I could live with that interpretation.
— Justin
On Jan 10, 2017, at 12:01 PM, George Fletcher < george.fletcher@teamaol.com> wrote:
I personally don't have any issues making the client be explicit about it's requests, so I'd prefer to not have a default option at all and just have the client request what it wants at each RPT/Token request. This would then cause the ClientReg set to just be a limiting set on what the client can request at run time.
Note that the AS is free to not allow all the scopes requested in the ClientReg set at registration time, in which case the limiting set gets smaller. If that happens, then the only way the client can get a particular scope needed to access a resource is if that scope is identified by the permission ticket.
On Tue, Jan 10, 2017 at 11:57 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yes, exactly. The RS's permission ticket-requested scope values are incontrovertible. The registered scopes should only apply to whatever the Client is trying to request on top of that.
So my proposal is that the scope value in the client registration should be a restriction for what it can request in that vein (as RFC 7591 specifies it). A separate field, default_scope, could be added for what might get added by default. So I guess I'm suggesting a sort of hybrid of Option 2 and Option 3 from the minutes from last week's meeting.
Cheers James
On 10 January 2017 at 16:32, George Fletcher <george.fletcher@teamaol.com
wrote:
So how do you want to apply the "superset" thinking to the scopes requested by the client at registration time? Are you thinking that the client can only explicitly requests scopes that are within that set? even though the permission ticket my expand the set beyond that?
Thanks, George
On Tue, Jan 10, 2017 at 11:23 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Like I said, I'm talking about scope values requested by the client, *not* by the RS in the permission ticket.
J.
On 10 January 2017 at 16:21, George Fletcher <george.fletcher@teamaol.com
wrote:
Hi James,
I guess what I'm saying is that even if the client registers for scopes A, B, C, and F; that doesn't prohibit the client from in fact requesting for scope K (as identified by the RS as required for the requested resource) when requesting a new RPT.
So in that sense, the list of client registered scopes can not be considered the super set of all scopes the client can request (which is what I thought you were saying in your email; again I probably misunderstood your intent:)
Thanks, George
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 <(703)%20462-3494> Office:+1-703-265-2544 <(703)%20265-2544>

This is incredibly useful. I have a question regarding “ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT” I am wondering whether this should always hold: RPTResult = subset(ROPolicy) If the ROPolicy changed from when the prevRPT was granted, shouldn’t AS revoke the previous RPT? Thanks, --Cigdem From: <wg-uma-bounces@kantarainitiative.org> on behalf of Justin Richer <jricher@mit.edu> Date: Friday, 6 January 2017 at 22:56 To: "wg-uma@kantarainitiative.org UMA" <wg-uma@kantarainitiative.org> Subject: [WG-UMA] Set Math Discussion I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts: [cid:image001.png@01D26A61.C17C81A0] I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home. So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other. ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes And finally what the token includes: RPTResult - the sets that the resulting token includes on output The one direct relationship seems to be that: ROPolicy = subset(RSReg) Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above. It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words: RPTResult = subset(ROPolicy) That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green. This also means that RSReg is also a limiting set, due to transitive subset operations: RPTResult = subset(RSReg) We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of: Requested = union(ClientReq, RSTicket) We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like: Requested = union(ClientReg, ClientReq, RSTicket) This could also be done conditionally, like the case where the client didn’t specifically request anything: if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) } Or if the client or ticket didn’t request anything: if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg } So my proposed implementation would be something like this horrible pseudocode: if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> } << the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket) << if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg } << finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >> RPTResult = union( intersection(Requested, ROPolicy), PrevRPT) I’ve tested a little bit of this with the following python truth table code: from truths import Truths print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT']) This seems to match up to expectations on a quick inspection, but I’m potentially missing something. Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality. — Justin

It’s more the case that the ROPolicy set that’s ensconced in PrevRPT is a *different* set than the ROPolicy that’s being currently evaluated against. In which case, you shouldn’t necessarily revoke things. But if the AS is smart enough to realize that policies have changed and can do something proactive, go for it. — Justin
On Jan 9, 2017, at 5:18 AM, Cigdem Sengul <Cigdem.Sengul@nominet.uk> wrote:
This is incredibly useful.
I have a question regarding “ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT”
I am wondering whether this should always hold: RPTResult = subset(ROPolicy)
If the ROPolicy changed from when the prevRPT was granted, shouldn’t AS revoke the previous RPT?
Thanks, --Cigdem
From: <wg-uma-bounces@kantarainitiative.org <mailto:wg-uma-bounces@kantarainitiative.org>> on behalf of Justin Richer <jricher@mit.edu <mailto:jricher@mit.edu>> Date: Friday, 6 January 2017 at 22:56 To: "wg-uma@kantarainitiative.org <mailto:wg-uma@kantarainitiative.org> UMA" <wg-uma@kantarainitiative.org <mailto:wg-uma@kantarainitiative.org>> Subject: [WG-UMA] Set Math Discussion
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
<image001.png>
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union( intersection(Requested, ROPolicy), PrevRPT)
I’ve tested a little bit of this with the following python truth table code:
from truths import Truths
print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT'])
This seems to match up to expectations on a quick inspection, but I’m potentially missing something.
Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality.
— Justin

For me this is the crux of what we need to figure out. In UMA when a scope is granted, it's granted in the context of a resource. For example, granting a "view" scope to Bob who wants to view my landscape photos (where he promises not to download them; ROPolicy) is different than granting Bob a "view" scope to access my family photos. The ROPolicy for the family photos resource could be membership in the family list (which Bob will never be part of). So, if Bob's client sends the PrevRPT with the "view" scope for "landscape photos" on a request for "family photos", the value of the PrevRPT "view" scope is kind of pointless. The ROPolicy for "family photos" is very different from the ROPolicy for "landscape photos". In this context PrevRPT doesn't provide much value. The ability to reference claims that have already been met for the RqP:client:RO tuple at the AS seems more valuable. Thanks, George On Mon, Jan 9, 2017 at 12:26 PM Justin Richer <jricher@mit.edu> wrote:
It’s more the case that the ROPolicy set that’s ensconced in PrevRPT is a *different* set than the ROPolicy that’s being currently evaluated against. In which case, you shouldn’t necessarily revoke things.
But if the AS is smart enough to realize that policies have changed and can do something proactive, go for it.
— Justin
On Jan 9, 2017, at 5:18 AM, Cigdem Sengul <Cigdem.Sengul@nominet.uk> wrote:
This is incredibly useful.
I have a question regarding “ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT”
I am wondering whether this should always hold: RPTResult = subset(ROPolicy)
If the ROPolicy changed from when the prevRPT was granted, shouldn’t AS revoke the previous RPT?
Thanks, --Cigdem
*From: *<wg-uma-bounces@kantarainitiative.org> on behalf of Justin Richer <jricher@mit.edu> *Date: *Friday, 6 January 2017 at 22:56 *To: *"wg-uma@kantarainitiative.org UMA" <wg-uma@kantarainitiative.org> *Subject: *[WG-UMA] Set Math Discussion
I’ve been working on the set math problem and I’ve been trying to lay out scenarios using this spreadsheet to help me sort my thoughts:
<image001.png>
I’ve left a bit of space in the spreadsheet for additional combinations and use cases I might have missed, so please chime in and we can figure out an algorithm that we can all agree on. I can send out the .xlsx file if people care to play with it at home.
So we’ve got six sets of scopes to deal with here, and they’re somewhat independent of each other.
ClientReg - client registers for these scopes at the RS RSTicket - RS requests a ticket with these scopes ROPolicy - RO sets a policy with these scopes (and it’s fulfilled by the RqP for our purposes) ClientReq - client requests these scopes at the token endpoint RSReg - RS registers these scopes at RS setup time PrevRPT - client presents a previously-held RPT that’s got some other scopes on it and it’s trying to augment that with new scopes
And finally what the token includes:
RPTResult - the sets that the resulting token includes on output
The one direct relationship seems to be that:
ROPolicy = subset(RSReg)
Because otherwise the RO could set scopes on a resource that the resource didn’t register, which doesn’t make sense to me. That’s the error in column “F” above.
It’s clear to me that “ROPolicy” is a limiting set, in that if a scope is NOT in that set, then it is not in the result. In other words:
RPTResult = subset(ROPolicy)
That’s column D, and nearly any other combination without ROPolicy doesn’t let the scope go through, with one exception: if it’s in PrevRPT, it gets carried through no matter what. But in particular, that, I believe, is an AS decision on whether it wants to honor previous RPTs at all. That’s why I’ve coded those K, L in green.
This also means that RSReg is also a limiting set, due to transitive subset operations:
RPTResult = subset(RSReg)
We have both the client and RS request scopes for the token at runtime in their parts, and it makes a lot of sense to combine them. So we get a working set of:
Requested = union(ClientReq, RSTicket)
We have an open question with what to do with column I: if a client hasn’t requested a scope, and a ticket didn’t request a scope, but the client registered for a scope, do we include it or not? We could choose to either ignore it and leave it out entirely; or add it in, and if it passes ROPolicy then we’ll pass it through to the token. These were the options we were discussing on the call on Thursday. Ignoring it here would effectively ignore the client’s registered scopes entirely, which is valid. The alternative would be coded something like:
Requested = union(ClientReg, ClientReq, RSTicket)
This could also be done conditionally, like the case where the client didn’t specifically request anything:
if (empty(ClientReq)) { Requested = union(ClientReg, RSTicket) }
Or if the client or ticket didn’t request anything:
if (empty(ClientReq) && empty(RSTicket)) { Requested = ClientReg }
So my proposed implementation would be something like this horrible pseudocode:
if (ROPolicy is not subset(RSReg)) { throw error and fail <<sanity check>> }
<< the requested set is made up of the client’s request to the token endpoint and the RS’s request during the ticket issuance step>> Requested = union(ClientReq, RSTicket)
<< if nothing’s been requested, maybe the client’s registered for something we can default to >> if (empty(Requested)) { Requested = ClientReg }
<< finally, we take the requested scopes and filter out anything not in a matched policy, and add in anything from a previous RPT if it’s there >>
RPTResult = union( intersection(Requested, ROPolicy), PrevRPT)
I’ve tested a little bit of this with the following python truth table code:
from truths import Truths
print Truths(['ClientReg', 'RSTicket', 'ROPolicy', 'ClientReq', 'RSReg', 'PrevRPT'], ['(((ClientReq or RSTicket) if not (ClientReq or RSTicket) else ClientReg) and ROPolicy) or PrevRPT'])
This seems to match up to expectations on a quick inspection, but I’m potentially missing something.
Hopefully this makes sense, and this reflects my current thinking on this topic. I have almost certainly missed some use cases and might have some cases that don’t reflect reality.
— Justin
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544
participants (1)
-
Cigdem Sengul
-
Eve Maler
-
George Fletcher
-
James Phillpotts
-
Justin Richer
-
Salvatore D'Agostino