Hi all, Thanks for the reminder to send this email Eve! ;) The paragraph in question is: The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access. I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level? If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it. If per-scope, does this only apply to additional scopes requested by the client? If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource. On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response? This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants *either* view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern). Sorry if this is slightly rambling. Cheers, James
Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested): "Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access." This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts? *Eve Maler*Cell +1 425.345.6756 | Skype: xmlgrrl | Twitter: @xmlgrrl On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi all,
Thanks for the reminder to send this email Eve! ;)
The paragraph in question is:
The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access.
I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants *either* view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
Right, I see. Maybe an example would help?
On 25 January 2017 at 17:35, Eve Maler
Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested):
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi all,
Thanks for the reminder to send this email Eve! ;)
The paragraph in question is:
The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access.
I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants *either* view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ WG-UMA mailing list WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma
Given that the RPT is somewhat equivalent to an OAuth2 access token, the
OAuth2 best practice is to return the set of scopes that were met as part
of the request, and also inform the client of which scopes where granted.
This becomes a little more problematic for the scopes defined by the
permissions_ticket because the client doesn't know what they are. If we
allow the "partial scopes" response, it will be possible for the client to
successfully get an RPT that does not provide it the access it needs to a
particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes
the request to Alice's album and the RS requests the AS to generate a
permission_ticket with view,edit scopes for the resource. Bob's client
presents the permission_ticket to the AS and goes through some claims
negotiation. The result of the set math is that Bob's client gets 'edit'
scope but not 'view'. If the AS issues the RPT with just the 'edit' scope,
the it's unlikely that Bob's client will work as it really wanted 'view'
access.
I'm becoming more convinced that the responsibility for the scopes
necessary to issue the RPT must lie with the RS and NOT the AS. If the RS
is asking for too many scopes up front, then Bob's experience will have a
lot of overhead just to be able to view the photos. On the other hand, if
the RS asks for just the scopes needed and the AS overrides that decision
by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks,
George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts <
james.phillpotts@forgerock.com> wrote:
Right, I see. Maybe an example would help?
On 25 January 2017 at 17:35, Eve Maler
Yep, that does make sense. The problem would be:
10 RS requests resourceA(scope1, scope2)
20 AS issues RPT resourceA(scope1)
30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was
granted? The situation I want to allow is for the RS to be able to say
Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS
being able to return partially matched scopes, which with the current
introspection can allow the problem you describe. If the introspection of
the RPT above instead returned: Granted:resourceA(scope1);
Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows
there is no point is submitting that permission request again.
WDYT?
James
On 25 January 2017 at 17:56, George Fletcher
Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted.
This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Right, I see. Maybe an example would help?
On 25 January 2017 at 17:35, Eve Maler
wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested):
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi all,
Thanks for the reminder to send this email Eve! ;)
The paragraph in question is:
The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access.
I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants *either* view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ 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>
Ahh... good point James. If the permission ticket encompasses multiple resource set ids, then the AS should be able to authorize the different resource set ids separately. I do worry about requiring the AS to return the "denied" resource_set(scope) tuples, because at introspection time that could be very complicated to reconstruct. What about the following? 1. The RS is "authoritative" for requesting the required scopes for any resource_set_id. This means that in order for the RPT to include a resource_set:scope tuple, the client/RqP MUST meet all policy for the scopes in the permission_ticket for that resource_set. 2. If the permission_ticket contains multiple resource_set:scope tuples, the AS MAY authorize a partial set of the tuples so long as all the scopes for that tuple are fully met. This has the effect of encouraging the RS to not request a huge amount of scopes for a given resource_set while not prohibiting the RS from asking for more than is absolutely necessary. This also, should I believe, address the use case James described. For instance, is the RS asks the AS for a permission_ticket for resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the client/RqP supplies claims or goes through claims negotiation, they only can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC). WDYT? On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yep, that does make sense. The problem would be:
10 RS requests resourceA(scope1, scope2) 20 AS issues RPT resourceA(scope1) 30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was granted? The situation I want to allow is for the RS to be able to say Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS being able to return partially matched scopes, which with the current introspection can allow the problem you describe. If the introspection of the RPT above instead returned: Granted:resourceA(scope1); Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows there is no point is submitting that permission request again.
WDYT? James
On 25 January 2017 at 17:56, George Fletcher
wrote: Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted.
This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Right, I see. Maybe an example would help?
On 25 January 2017 at 17:35, Eve Maler
wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested):
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi all,
Thanks for the reminder to send this email Eve! ;)
The paragraph in question is:
The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access.
I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants *either* view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ 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
That's interesting. I'm still not sure it 100% satisfies what I'm thinking
about, as a new RPT that failed to get resourceB would look the same as an
existing RPT for resourceA and resourceC, so the RS would send back to try
and get resourceB if it needed it.
On 26 January 2017 at 14:13, George Fletcher
Ahh... good point James. If the permission ticket encompasses multiple resource set ids, then the AS should be able to authorize the different resource set ids separately.
I do worry about requiring the AS to return the "denied" resource_set(scope) tuples, because at introspection time that could be very complicated to reconstruct.
What about the following?
1. The RS is "authoritative" for requesting the required scopes for any resource_set_id. This means that in order for the RPT to include a resource_set:scope tuple, the client/RqP MUST meet all policy for the scopes in the permission_ticket for that resource_set. 2. If the permission_ticket contains multiple resource_set:scope tuples, the AS MAY authorize a partial set of the tuples so long as all the scopes for that tuple are fully met.
This has the effect of encouraging the RS to not request a huge amount of scopes for a given resource_set while not prohibiting the RS from asking for more than is absolutely necessary.
This also, should I believe, address the use case James described. For instance, is the RS asks the AS for a permission_ticket for resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the client/RqP supplies claims or goes through claims negotiation, they only can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC).
WDYT?
On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yep, that does make sense. The problem would be:
10 RS requests resourceA(scope1, scope2) 20 AS issues RPT resourceA(scope1) 30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was granted? The situation I want to allow is for the RS to be able to say Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS being able to return partially matched scopes, which with the current introspection can allow the problem you describe. If the introspection of the RPT above instead returned: Granted:resourceA(scope1); Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows there is no point is submitting that permission request again.
WDYT? James
On 25 January 2017 at 17:56, George Fletcher
wrote:
Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted.
This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Right, I see. Maybe an example would help?
On 25 January 2017 at 17:35, Eve Maler
wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested):
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi all,
Thanks for the reminder to send this email Eve! ;)
The paragraph in question is:
The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access.
I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants *either* view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ 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>
Good point:) I would rather have the AS return to the client that it issued the RPT but didn't fully meet all requested permissions. The problem, is that the client has no clue as to what a resource_set maps to from a URI perspective. I suppose if the AS returned to the client that it was not able to fully meet the permission_ticket scopes in some "partially_met" flag, then the client can try a resource but knows it's possible it won't work. I think if the client sends a RqP through a claims negotiation flow for access to resourceA, if it has to do the same thing again, it could tell the RqP that access will be denied unless the RqP supplies all the requested claims. Maybe the AS could show this to the user during the interactive claims negotiation? Bob would probably understand Alice's resource name/description of "Alice's calendar". So, if in interactive mode, the AS could tell Bob, "unfortunately you did not meet the policy necessary to access Alice's calendar". That way the user knows that the next client request for "Alice's calendar" will fail. Don't know if that's better? On Thu, Jan 26, 2017 at 10:40 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
That's interesting. I'm still not sure it 100% satisfies what I'm thinking about, as a new RPT that failed to get resourceB would look the same as an existing RPT for resourceA and resourceC, so the RS would send back to try and get resourceB if it needed it.
On 26 January 2017 at 14:13, George Fletcher
wrote: Ahh... good point James. If the permission ticket encompasses multiple resource set ids, then the AS should be able to authorize the different resource set ids separately.
I do worry about requiring the AS to return the "denied" resource_set(scope) tuples, because at introspection time that could be very complicated to reconstruct.
What about the following?
1. The RS is "authoritative" for requesting the required scopes for any resource_set_id. This means that in order for the RPT to include a resource_set:scope tuple, the client/RqP MUST meet all policy for the scopes in the permission_ticket for that resource_set. 2. If the permission_ticket contains multiple resource_set:scope tuples, the AS MAY authorize a partial set of the tuples so long as all the scopes for that tuple are fully met.
This has the effect of encouraging the RS to not request a huge amount of scopes for a given resource_set while not prohibiting the RS from asking for more than is absolutely necessary.
This also, should I believe, address the use case James described. For instance, is the RS asks the AS for a permission_ticket for resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the client/RqP supplies claims or goes through claims negotiation, they only can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC).
WDYT?
On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yep, that does make sense. The problem would be:
10 RS requests resourceA(scope1, scope2) 20 AS issues RPT resourceA(scope1) 30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was granted? The situation I want to allow is for the RS to be able to say Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS being able to return partially matched scopes, which with the current introspection can allow the problem you describe. If the introspection of the RPT above instead returned: Granted:resourceA(scope1); Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows there is no point is submitting that permission request again.
WDYT? James
On 25 January 2017 at 17:56, George Fletcher
wrote: Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted.
This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Right, I see. Maybe an example would help?
On 25 January 2017 at 17:35, Eve Maler
wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested):
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi all,
Thanks for the reminder to send this email Eve! ;)
The paragraph in question is:
The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access.
I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants *either* view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ 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
I’m averse to making the client or RS too smart about cleanup and these half-working conditions. A simpler protocol is more likely to be functional in the long run. If things can fail, they should fail with pretty well defined semantics. In OAuth, you can get a token, and that token can work or not work. This is good enough for the vast majority of situations, and so I’m not in favor of marking things as partially met. It’s adding complexity without benefit that I can clearly see. I’d also like to remind the group of the original argument that I made to add the “Default Deny” language in there, as it’s got very little to do with the current discussion. Basically, imagine this naive implementation: - Each resource set has policies that are fulfilled by claims - The client/RqP present claims to fulfill these required policies - If you fulfill any policies on the resource, you get a token with the associated scopes This is all well and good. However, if you have: - A resource set that has *no* policies set Then you could end up with the following aberrant logic: - Client requests a token for a resource, gather up the set of required claims to access said resource - Required claims is the empty set as no policies are set - Client/RqP present no claims - Empty set satisfies the empty set, client gets issued a token *this* precise bug is what I was trying to guard against with my original proposal. I fear we’ve gone off into the woods now. — Justin
On Jan 26, 2017, at 11:10 AM, George Fletcher
wrote: Good point:) I would rather have the AS return to the client that it issued the RPT but didn't fully meet all requested permissions. The problem, is that the client has no clue as to what a resource_set maps to from a URI perspective. I suppose if the AS returned to the client that it was not able to fully meet the permission_ticket scopes in some "partially_met" flag, then the client can try a resource but knows it's possible it won't work.
I think if the client sends a RqP through a claims negotiation flow for access to resourceA, if it has to do the same thing again, it could tell the RqP that access will be denied unless the RqP supplies all the requested claims. Maybe the AS could show this to the user during the interactive claims negotiation?
Bob would probably understand Alice's resource name/description of "Alice's calendar". So, if in interactive mode, the AS could tell Bob, "unfortunately you did not meet the policy necessary to access Alice's calendar". That way the user knows that the next client request for "Alice's calendar" will fail.
Don't know if that's better?
On Thu, Jan 26, 2017 at 10:40 AM James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: That's interesting. I'm still not sure it 100% satisfies what I'm thinking about, as a new RPT that failed to get resourceB would look the same as an existing RPT for resourceA and resourceC, so the RS would send back to try and get resourceB if it needed it. On 26 January 2017 at 14:13, George Fletcher
mailto:george.fletcher@teamaol.com> wrote: Ahh... good point James. If the permission ticket encompasses multiple resource set ids, then the AS should be able to authorize the different resource set ids separately. I do worry about requiring the AS to return the "denied" resource_set(scope) tuples, because at introspection time that could be very complicated to reconstruct.
What about the following?
1. The RS is "authoritative" for requesting the required scopes for any resource_set_id. This means that in order for the RPT to include a resource_set:scope tuple, the client/RqP MUST meet all policy for the scopes in the permission_ticket for that resource_set. 2. If the permission_ticket contains multiple resource_set:scope tuples, the AS MAY authorize a partial set of the tuples so long as all the scopes for that tuple are fully met.
This has the effect of encouraging the RS to not request a huge amount of scopes for a given resource_set while not prohibiting the RS from asking for more than is absolutely necessary.
This also, should I believe, address the use case James described. For instance, is the RS asks the AS for a permission_ticket for resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the client/RqP supplies claims or goes through claims negotiation, they only can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC).
WDYT?
On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: Yep, that does make sense. The problem would be: 10 RS requests resourceA(scope1, scope2) 20 AS issues RPT resourceA(scope1) 30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was granted? The situation I want to allow is for the RS to be able to say Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS being able to return partially matched scopes, which with the current introspection can allow the problem you describe. If the introspection of the RPT above instead returned: Granted:resourceA(scope1); Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows there is no point is submitting that permission request again.
WDYT? James
On 25 January 2017 at 17:56, George Fletcher
mailto:george.fletcher@teamaol.com> wrote: Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted. This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: Right, I see. Maybe an example would help? On 25 January 2017 at 17:35, Eve Maler
mailto:eve@xmlgrrl.com> wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested): "Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
Eve Maler Cell +1 425.345.6756 tel:(425)%20345-6756 | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: Hi all, Thanks for the reminder to send this email Eve! ;)
The paragraph in question is: The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access. I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants either view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ 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
_______________________________________________ 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 -- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 tel:(703)%20462-3494 Office:+1-703-265-2544 tel:(703)%20265-2544 -- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 tel:(703)%20462-3494 Office:+1-703-265-2544 tel:(703)%20265-2544 -- 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 mailto:WG-UMA@kantarainitiative.org http://kantarainitiative.org/mailman/listinfo/wg-uma http://kantarainitiative.org/mailman/listinfo/wg-uma
I agree that it's best to "think clean"; we do, after all, have design
principles
http://kantarainitiative.org/confluence/display/uma/UMA+Requirements
about simplicity, where to put complexity, etc.
At the conclusion of our last telecon, James took an action item to come up
with a proposal where the AS would provide the last-issued ticket, broken
out with the state it had kept associated with it, as part of the token
introspection object. It would be good to see that, but I also have an idea
to do a deeper analysis in prep for our next call, which I'll try to do
tonight: a map of all the flow options in the C-AS-RS scope dance, what we
want to achieve, and which flows we think are viable for those ends.
====
Specifically regarding default-deny:
In Core rev 13
https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization...,
I did keep some default-deny wording that I felt was defensible even if not
a testable assertion, covering the original corner case of concern. Do you
think this suffices, Justin?
*"Note: While a reasonable approach for most scenarios is to implement the
classic security stance of default-deny ("everything that is not expressly
allowed is forbidden"), corner cases can inadvertently result in
default-permit behavior. For example, it is insufficient simply to assume
that all resources have some non-zero set of claims required for access,
and then accept an empty set of supplied claims as sufficient for access."*
*Eve Maler*Cell +1 425.345.6756 | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 31, 2017 at 3:31 PM, Justin Richer
I’m averse to making the client or RS too smart about cleanup and these half-working conditions. A simpler protocol is more likely to be functional in the long run. If things can fail, they should fail with pretty well defined semantics. In OAuth, you can get a token, and that token can work or not work. This is good enough for the vast majority of situations, and so I’m not in favor of marking things as partially met. It’s adding complexity without benefit that I can clearly see.
I’d also like to remind the group of the original argument that I made to add the “Default Deny” language in there, as it’s got very little to do with the current discussion. Basically, imagine this naive implementation:
- Each resource set has policies that are fulfilled by claims - The client/RqP present claims to fulfill these required policies - If you fulfill any policies on the resource, you get a token with the associated scopes
This is all well and good. However, if you have:
- A resource set that has *no* policies set
Then you could end up with the following aberrant logic:
- Client requests a token for a resource, gather up the set of required claims to access said resource - Required claims is the empty set as no policies are set - Client/RqP present no claims - Empty set satisfies the empty set, client gets issued a token
*this* precise bug is what I was trying to guard against with my original proposal. I fear we’ve gone off into the woods now.
— Justin
On Jan 26, 2017, at 11:10 AM, George Fletcher
wrote: Good point:) I would rather have the AS return to the client that it issued the RPT but didn't fully meet all requested permissions. The problem, is that the client has no clue as to what a resource_set maps to from a URI perspective. I suppose if the AS returned to the client that it was not able to fully meet the permission_ticket scopes in some "partially_met" flag, then the client can try a resource but knows it's possible it won't work.
I think if the client sends a RqP through a claims negotiation flow for access to resourceA, if it has to do the same thing again, it could tell the RqP that access will be denied unless the RqP supplies all the requested claims. Maybe the AS could show this to the user during the interactive claims negotiation?
Bob would probably understand Alice's resource name/description of "Alice's calendar". So, if in interactive mode, the AS could tell Bob, "unfortunately you did not meet the policy necessary to access Alice's calendar". That way the user knows that the next client request for "Alice's calendar" will fail.
Don't know if that's better?
On Thu, Jan 26, 2017 at 10:40 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
That's interesting. I'm still not sure it 100% satisfies what I'm thinking about, as a new RPT that failed to get resourceB would look the same as an existing RPT for resourceA and resourceC, so the RS would send back to try and get resourceB if it needed it.
On 26 January 2017 at 14:13, George Fletcher
wrote:
Ahh... good point James. If the permission ticket encompasses multiple resource set ids, then the AS should be able to authorize the different resource set ids separately.
I do worry about requiring the AS to return the "denied" resource_set(scope) tuples, because at introspection time that could be very complicated to reconstruct.
What about the following?
1. The RS is "authoritative" for requesting the required scopes for any resource_set_id. This means that in order for the RPT to include a resource_set:scope tuple, the client/RqP MUST meet all policy for the scopes in the permission_ticket for that resource_set. 2. If the permission_ticket contains multiple resource_set:scope tuples, the AS MAY authorize a partial set of the tuples so long as all the scopes for that tuple are fully met.
This has the effect of encouraging the RS to not request a huge amount of scopes for a given resource_set while not prohibiting the RS from asking for more than is absolutely necessary.
This also, should I believe, address the use case James described. For instance, is the RS asks the AS for a permission_ticket for resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the client/RqP supplies claims or goes through claims negotiation, they only can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC).
WDYT?
On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yep, that does make sense. The problem would be:
10 RS requests resourceA(scope1, scope2) 20 AS issues RPT resourceA(scope1) 30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was granted? The situation I want to allow is for the RS to be able to say Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS being able to return partially matched scopes, which with the current introspection can allow the problem you describe. If the introspection of the RPT above instead returned: Granted:resourceA(scope1); Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows there is no point is submitting that permission request again.
WDYT? James
On 25 January 2017 at 17:56, George Fletcher
wrote:
Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted.
This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Right, I see. Maybe an example would help?
On 25 January 2017 at 17:35, Eve Maler
wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested):
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts
wrote: Hi all,
Thanks for the reminder to send this email Eve! ;)
The paragraph in question is:
The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access.
I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants *either* view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ 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>
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
I think that language has the right spirit, though something isn’t sitting right with me with the exact phrasing used. I think it’s more a language style clean up more than anything so I’ll take a stab at rephrasing it sometime to see if I can capture that. — Justin
On Jan 31, 2017, at 7:24 PM, Eve Maler
wrote: I agree that it's best to "think clean"; we do, after all, have design principles http://kantarainitiative.org/confluence/display/uma/UMA+Requirements about simplicity, where to put complexity, etc.
At the conclusion of our last telecon, James took an action item to come up with a proposal where the AS would provide the last-issued ticket, broken out with the state it had kept associated with it, as part of the token introspection object. It would be good to see that, but I also have an idea to do a deeper analysis in prep for our next call, which I'll try to do tonight: a map of all the flow options in the C-AS-RS scope dance, what we want to achieve, and which flows we think are viable for those ends.
====
Specifically regarding default-deny:
In Core rev 13 https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization..., I did keep some default-deny wording that I felt was defensible even if not a testable assertion, covering the original corner case of concern. Do you think this suffices, Justin?
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
Eve Maler Cell +1 425.345.6756 | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 31, 2017 at 3:31 PM, Justin Richer
mailto:jricher@mit.edu> wrote: I’m averse to making the client or RS too smart about cleanup and these half-working conditions. A simpler protocol is more likely to be functional in the long run. If things can fail, they should fail with pretty well defined semantics. In OAuth, you can get a token, and that token can work or not work. This is good enough for the vast majority of situations, and so I’m not in favor of marking things as partially met. It’s adding complexity without benefit that I can clearly see. I’d also like to remind the group of the original argument that I made to add the “Default Deny” language in there, as it’s got very little to do with the current discussion. Basically, imagine this naive implementation:
- Each resource set has policies that are fulfilled by claims - The client/RqP present claims to fulfill these required policies - If you fulfill any policies on the resource, you get a token with the associated scopes
This is all well and good. However, if you have:
- A resource set that has *no* policies set
Then you could end up with the following aberrant logic:
- Client requests a token for a resource, gather up the set of required claims to access said resource - Required claims is the empty set as no policies are set - Client/RqP present no claims - Empty set satisfies the empty set, client gets issued a token
*this* precise bug is what I was trying to guard against with my original proposal. I fear we’ve gone off into the woods now.
— Justin
On Jan 26, 2017, at 11:10 AM, George Fletcher
mailto:george.fletcher@teamaol.com> wrote: Good point:) I would rather have the AS return to the client that it issued the RPT but didn't fully meet all requested permissions. The problem, is that the client has no clue as to what a resource_set maps to from a URI perspective. I suppose if the AS returned to the client that it was not able to fully meet the permission_ticket scopes in some "partially_met" flag, then the client can try a resource but knows it's possible it won't work.
I think if the client sends a RqP through a claims negotiation flow for access to resourceA, if it has to do the same thing again, it could tell the RqP that access will be denied unless the RqP supplies all the requested claims. Maybe the AS could show this to the user during the interactive claims negotiation?
Bob would probably understand Alice's resource name/description of "Alice's calendar". So, if in interactive mode, the AS could tell Bob, "unfortunately you did not meet the policy necessary to access Alice's calendar". That way the user knows that the next client request for "Alice's calendar" will fail.
Don't know if that's better?
On Thu, Jan 26, 2017 at 10:40 AM James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: That's interesting. I'm still not sure it 100% satisfies what I'm thinking about, as a new RPT that failed to get resourceB would look the same as an existing RPT for resourceA and resourceC, so the RS would send back to try and get resourceB if it needed it. On 26 January 2017 at 14:13, George Fletcher
mailto:george.fletcher@teamaol.com> wrote: Ahh... good point James. If the permission ticket encompasses multiple resource set ids, then the AS should be able to authorize the different resource set ids separately. I do worry about requiring the AS to return the "denied" resource_set(scope) tuples, because at introspection time that could be very complicated to reconstruct.
What about the following?
1. The RS is "authoritative" for requesting the required scopes for any resource_set_id. This means that in order for the RPT to include a resource_set:scope tuple, the client/RqP MUST meet all policy for the scopes in the permission_ticket for that resource_set. 2. If the permission_ticket contains multiple resource_set:scope tuples, the AS MAY authorize a partial set of the tuples so long as all the scopes for that tuple are fully met.
This has the effect of encouraging the RS to not request a huge amount of scopes for a given resource_set while not prohibiting the RS from asking for more than is absolutely necessary.
This also, should I believe, address the use case James described. For instance, is the RS asks the AS for a permission_ticket for resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the client/RqP supplies claims or goes through claims negotiation, they only can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC).
WDYT?
On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: Yep, that does make sense. The problem would be: 10 RS requests resourceA(scope1, scope2) 20 AS issues RPT resourceA(scope1) 30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was granted? The situation I want to allow is for the RS to be able to say Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS being able to return partially matched scopes, which with the current introspection can allow the problem you describe. If the introspection of the RPT above instead returned: Granted:resourceA(scope1); Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows there is no point is submitting that permission request again.
WDYT? James
On 25 January 2017 at 17:56, George Fletcher
mailto:george.fletcher@teamaol.com> wrote: Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted. This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: Right, I see. Maybe an example would help? On 25 January 2017 at 17:35, Eve Maler
mailto:eve@xmlgrrl.com> wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested): "Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
Eve Maler Cell +1 425.345.6756 tel:(425)%20345-6756 | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: Hi all, Thanks for the reminder to send this email Eve! ;)
The paragraph in question is: The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access. I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants either view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ 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
_______________________________________________ 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 -- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 tel:(703)%20462-3494 Office:+1-703-265-2544 tel:(703)%20265-2544 -- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 tel:(703)%20462-3494 Office:+1-703-265-2544 tel:(703)%20265-2544 -- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 tel:(703)%20462-3494 Office:+1-703-265-2544 tel:(703)%20265-2544_______________________________________________ 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
_______________________________________________ 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
Sorry, I'd been meaning to write up that action but something always came
up. Here we go...
Take this Google Drive link as an example:
https://drive.google.com/drive/folders/0B7eRlQ5s6EfgbFJHU1ZjVFNxelE?usp=shar...
You'll find it's a folder "Test Folder" with 2 files in it, "File1" and
"File2". Each of the 3 resources can be shared in their own right. This is
not a particularly contrived use case - the same type of structure is used
by many websites that support non-UMA resource sharing.
When registering resources at the AS, the relationship between them cannot
be expressed, so when registering a permission ticket for an access attempt
on either of the files, the RS has to register for the same scopes on both
Test Folder and the requested file, expecting either one of them or neither
to have a policy granting the requesting party access.
Here are a few scenarios:
1) Alice shared nothing with Bob, no existing RPT
- The client requests File1
- RS registers ticket for Test Folder and File1
- The Client does not get an RPT
No problem here
2) Alice shared nothing with Bob, Bob has existing RPT at the client for
the RS
- The client requests File1
- RS registers ticket for Test Folder and File1
- The client gets another RPT with the same resources/scope as the
existing one had
- Client presents the RPT to the RS
Here we have a problem - the RS has no context for the RPT, so it has to
rely on the content of the introspection request in order to find out what
it entitles the client to. If the introspection response only contains what
is granted, the RS will register another ticket just as it already did, and
loop. However, if the response were to contain a record of the attempt for
scope on Test Folder and File1, timestamped in the last few seconds, then
the RS would know that there was no other way that access could be shared,
so it would return a Forbidden response.
3) Alice has shared File1 with Bob
- The client approaches the RS for File1
- RS registers ticket for Test Folder and File1
- The client gets an RPT for File1
- Client presents the RPT to the RS
- Client requests File2 with existing RPT
Here is another opportunity for the RS to optimise the UMA flow if the
introspection response contains the denial of Test Folder - for File1 the
RS would have requested Test Folder and File1, Test Folder is not granted
access, if the RS can see this then it knows that for File2 there is no
point in submitting a request for both Test Folder and File2 - only File2.
One of the criticisms of the UMA protocol is that it is (or has the
potential to be) too chatty - this doesn't really change much in UMA2, but
this would be a way to give the RS some extra data that it could use to try
and reduce the chattiness. Also, policy evaluation is not a free (nor even
necessarily, cheap) operation, and if we can reduce the number of
evaluations the AS has to perform.
I'm obviously very happy to be shown how these issues can be mitigated in
other ways.
Cheers
James
On 1 February 2017 at 00:24, Eve Maler
I agree that it's best to "think clean"; we do, after all, have design principles http://kantarainitiative.org/confluence/display/uma/UMA+Requirements about simplicity, where to put complexity, etc.
At the conclusion of our last telecon, James took an action item to come up with a proposal where the AS would provide the last-issued ticket, broken out with the state it had kept associated with it, as part of the token introspection object. It would be good to see that, but I also have an idea to do a deeper analysis in prep for our next call, which I'll try to do tonight: a map of all the flow options in the C-AS-RS scope dance, what we want to achieve, and which flows we think are viable for those ends.
====
Specifically regarding default-deny:
In Core rev 13 https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization..., I did keep some default-deny wording that I felt was defensible even if not a testable assertion, covering the original corner case of concern. Do you think this suffices, Justin?
*"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."*
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 31, 2017 at 3:31 PM, Justin Richer
wrote: I’m averse to making the client or RS too smart about cleanup and these half-working conditions. A simpler protocol is more likely to be functional in the long run. If things can fail, they should fail with pretty well defined semantics. In OAuth, you can get a token, and that token can work or not work. This is good enough for the vast majority of situations, and so I’m not in favor of marking things as partially met. It’s adding complexity without benefit that I can clearly see.
I’d also like to remind the group of the original argument that I made to add the “Default Deny” language in there, as it’s got very little to do with the current discussion. Basically, imagine this naive implementation:
- Each resource set has policies that are fulfilled by claims - The client/RqP present claims to fulfill these required policies - If you fulfill any policies on the resource, you get a token with the associated scopes
This is all well and good. However, if you have:
- A resource set that has *no* policies set
Then you could end up with the following aberrant logic:
- Client requests a token for a resource, gather up the set of required claims to access said resource - Required claims is the empty set as no policies are set - Client/RqP present no claims - Empty set satisfies the empty set, client gets issued a token
*this* precise bug is what I was trying to guard against with my original proposal. I fear we’ve gone off into the woods now.
— Justin
On Jan 26, 2017, at 11:10 AM, George Fletcher < george.fletcher@teamaol.com> wrote:
Good point:) I would rather have the AS return to the client that it issued the RPT but didn't fully meet all requested permissions. The problem, is that the client has no clue as to what a resource_set maps to from a URI perspective. I suppose if the AS returned to the client that it was not able to fully meet the permission_ticket scopes in some "partially_met" flag, then the client can try a resource but knows it's possible it won't work.
I think if the client sends a RqP through a claims negotiation flow for access to resourceA, if it has to do the same thing again, it could tell the RqP that access will be denied unless the RqP supplies all the requested claims. Maybe the AS could show this to the user during the interactive claims negotiation?
Bob would probably understand Alice's resource name/description of "Alice's calendar". So, if in interactive mode, the AS could tell Bob, "unfortunately you did not meet the policy necessary to access Alice's calendar". That way the user knows that the next client request for "Alice's calendar" will fail.
Don't know if that's better?
On Thu, Jan 26, 2017 at 10:40 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
That's interesting. I'm still not sure it 100% satisfies what I'm thinking about, as a new RPT that failed to get resourceB would look the same as an existing RPT for resourceA and resourceC, so the RS would send back to try and get resourceB if it needed it.
On 26 January 2017 at 14:13, George Fletcher
wrote: Ahh... good point James. If the permission ticket encompasses multiple resource set ids, then the AS should be able to authorize the different resource set ids separately.
I do worry about requiring the AS to return the "denied" resource_set(scope) tuples, because at introspection time that could be very complicated to reconstruct.
What about the following?
1. The RS is "authoritative" for requesting the required scopes for any resource_set_id. This means that in order for the RPT to include a resource_set:scope tuple, the client/RqP MUST meet all policy for the scopes in the permission_ticket for that resource_set. 2. If the permission_ticket contains multiple resource_set:scope tuples, the AS MAY authorize a partial set of the tuples so long as all the scopes for that tuple are fully met.
This has the effect of encouraging the RS to not request a huge amount of scopes for a given resource_set while not prohibiting the RS from asking for more than is absolutely necessary.
This also, should I believe, address the use case James described. For instance, is the RS asks the AS for a permission_ticket for resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the client/RqP supplies claims or goes through claims negotiation, they only can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC).
WDYT?
On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yep, that does make sense. The problem would be:
10 RS requests resourceA(scope1, scope2) 20 AS issues RPT resourceA(scope1) 30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was granted? The situation I want to allow is for the RS to be able to say Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS being able to return partially matched scopes, which with the current introspection can allow the problem you describe. If the introspection of the RPT above instead returned: Granted:resourceA(scope1); Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows there is no point is submitting that permission request again.
WDYT? James
On 25 January 2017 at 17:56, George Fletcher
wrote: Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted.
This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Right, I see. Maybe an example would help?
On 25 January 2017 at 17:35, Eve Maler
wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested):
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts
wrote: Hi all,
Thanks for the reminder to send this email Eve! ;)
The paragraph in question is:
The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access.
I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants *either* view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ 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>
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
Thanks, James! To net out your proposal, I believe it is this (please correct if wrong): If the token introspection object response from the AS were to contain a record of the most recent *RequestedScopes*, timestamped in the last few seconds, then the RS would be able to optimize its next action: either return a Forbidden response (as in example #2) or modify its next request for permissions on the client's behalf (as in example #3). Some questions: - In example #2, since the *CandidateGrantedScopes* would have come back null according to our current logic, I think the client's RPT request would have gotten rejected at the AS. How does that change the thinking about optimization? - We had started to think that API publishers (RS's) would want to document and publicize their patterns for permission requests, for behavior predictability when it comes to clients attempting resource access. This proposal lets AS's optimize policy operations by virtue of RS's optimizing what they do next. Do RS's want to/can they do that? And how does this impact clients? - Last night I proposed trying, in some way, to bring clients more into the fold of the resource-primary scope-secondary ecosystem. (Though, admittedly, it was far from a complete proposal.) Would this also be a way for AS-RS communications to get opened up more fully to enable better efficiency? - A thought experiment: In our 2.0 drafts, we added the capability to request multiple permissions in anticipation of the type of use case you give here. The alternative would be the UMA1 method: Only requesting one permission (resource ID) at a time. What would happen then? Thoughts: - If we don't let clients express interest in resource-specific scopes, it seems like everything would be reactive and driven off access attempts because scope requests would be ambiguous a lot of the time. - If we find a way for clients to pre-register for and request resource-specific scopes, then this could be really interesting: Instead of the RS having to guess/interpret a lot, the permission ecosystem could be unambiguous and client-driven... *Eve Maler*Cell +1 425.345.6756 | Skype: xmlgrrl | Twitter: @xmlgrrl On Wed, Feb 1, 2017 at 10:29 AM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Sorry, I'd been meaning to write up that action but something always came up. Here we go...
Take this Google Drive link as an example: https://drive.google. com/drive/folders/0B7eRlQ5s6EfgbFJHU1ZjVFNxelE?usp=sharing
You'll find it's a folder "Test Folder" with 2 files in it, "File1" and "File2". Each of the 3 resources can be shared in their own right. This is not a particularly contrived use case - the same type of structure is used by many websites that support non-UMA resource sharing.
When registering resources at the AS, the relationship between them cannot be expressed, so when registering a permission ticket for an access attempt on either of the files, the RS has to register for the same scopes on both Test Folder and the requested file, expecting either one of them or neither to have a policy granting the requesting party access.
Here are a few scenarios:
1) Alice shared nothing with Bob, no existing RPT
- The client requests File1 - RS registers ticket for Test Folder and File1 - The Client does not get an RPT
No problem here
2) Alice shared nothing with Bob, Bob has existing RPT at the client for the RS
- The client requests File1 - RS registers ticket for Test Folder and File1 - The client gets another RPT with the same resources/scope as the existing one had - Client presents the RPT to the RS
Here we have a problem - the RS has no context for the RPT, so it has to rely on the content of the introspection request in order to find out what it entitles the client to. If the introspection response only contains what is granted, the RS will register another ticket just as it already did, and loop. However, if the response were to contain a record of the attempt for scope on Test Folder and File1, timestamped in the last few seconds, then the RS would know that there was no other way that access could be shared, so it would return a Forbidden response.
3) Alice has shared File1 with Bob
- The client approaches the RS for File1 - RS registers ticket for Test Folder and File1 - The client gets an RPT for File1 - Client presents the RPT to the RS - Client requests File2 with existing RPT
Here is another opportunity for the RS to optimise the UMA flow if the introspection response contains the denial of Test Folder - for File1 the RS would have requested Test Folder and File1, Test Folder is not granted access, if the RS can see this then it knows that for File2 there is no point in submitting a request for both Test Folder and File2 - only File2.
One of the criticisms of the UMA protocol is that it is (or has the potential to be) too chatty - this doesn't really change much in UMA2, but this would be a way to give the RS some extra data that it could use to try and reduce the chattiness. Also, policy evaluation is not a free (nor even necessarily, cheap) operation, and if we can reduce the number of evaluations the AS has to perform.
I'm obviously very happy to be shown how these issues can be mitigated in other ways.
Cheers James
On 1 February 2017 at 00:24, Eve Maler
wrote: I agree that it's best to "think clean"; we do, after all, have design principles http://kantarainitiative.org/confluence/display/uma/UMA+Requirements about simplicity, where to put complexity, etc.
At the conclusion of our last telecon, James took an action item to come up with a proposal where the AS would provide the last-issued ticket, broken out with the state it had kept associated with it, as part of the token introspection object. It would be good to see that, but I also have an idea to do a deeper analysis in prep for our next call, which I'll try to do tonight: a map of all the flow options in the C-AS-RS scope dance, what we want to achieve, and which flows we think are viable for those ends.
====
Specifically regarding default-deny:
In Core rev 13 https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization..., I did keep some default-deny wording that I felt was defensible even if not a testable assertion, covering the original corner case of concern. Do you think this suffices, Justin?
*"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."*
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 31, 2017 at 3:31 PM, Justin Richer
wrote: I’m averse to making the client or RS too smart about cleanup and these half-working conditions. A simpler protocol is more likely to be functional in the long run. If things can fail, they should fail with pretty well defined semantics. In OAuth, you can get a token, and that token can work or not work. This is good enough for the vast majority of situations, and so I’m not in favor of marking things as partially met. It’s adding complexity without benefit that I can clearly see.
I’d also like to remind the group of the original argument that I made to add the “Default Deny” language in there, as it’s got very little to do with the current discussion. Basically, imagine this naive implementation:
- Each resource set has policies that are fulfilled by claims - The client/RqP present claims to fulfill these required policies - If you fulfill any policies on the resource, you get a token with the associated scopes
This is all well and good. However, if you have:
- A resource set that has *no* policies set
Then you could end up with the following aberrant logic:
- Client requests a token for a resource, gather up the set of required claims to access said resource - Required claims is the empty set as no policies are set - Client/RqP present no claims - Empty set satisfies the empty set, client gets issued a token
*this* precise bug is what I was trying to guard against with my original proposal. I fear we’ve gone off into the woods now.
— Justin
On Jan 26, 2017, at 11:10 AM, George Fletcher < george.fletcher@teamaol.com> wrote:
Good point:) I would rather have the AS return to the client that it issued the RPT but didn't fully meet all requested permissions. The problem, is that the client has no clue as to what a resource_set maps to from a URI perspective. I suppose if the AS returned to the client that it was not able to fully meet the permission_ticket scopes in some "partially_met" flag, then the client can try a resource but knows it's possible it won't work.
I think if the client sends a RqP through a claims negotiation flow for access to resourceA, if it has to do the same thing again, it could tell the RqP that access will be denied unless the RqP supplies all the requested claims. Maybe the AS could show this to the user during the interactive claims negotiation?
Bob would probably understand Alice's resource name/description of "Alice's calendar". So, if in interactive mode, the AS could tell Bob, "unfortunately you did not meet the policy necessary to access Alice's calendar". That way the user knows that the next client request for "Alice's calendar" will fail.
Don't know if that's better?
On Thu, Jan 26, 2017 at 10:40 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
That's interesting. I'm still not sure it 100% satisfies what I'm thinking about, as a new RPT that failed to get resourceB would look the same as an existing RPT for resourceA and resourceC, so the RS would send back to try and get resourceB if it needed it.
On 26 January 2017 at 14:13, George Fletcher
wrote: Ahh... good point James. If the permission ticket encompasses multiple resource set ids, then the AS should be able to authorize the different resource set ids separately.
I do worry about requiring the AS to return the "denied" resource_set(scope) tuples, because at introspection time that could be very complicated to reconstruct.
What about the following?
1. The RS is "authoritative" for requesting the required scopes for any resource_set_id. This means that in order for the RPT to include a resource_set:scope tuple, the client/RqP MUST meet all policy for the scopes in the permission_ticket for that resource_set. 2. If the permission_ticket contains multiple resource_set:scope tuples, the AS MAY authorize a partial set of the tuples so long as all the scopes for that tuple are fully met.
This has the effect of encouraging the RS to not request a huge amount of scopes for a given resource_set while not prohibiting the RS from asking for more than is absolutely necessary.
This also, should I believe, address the use case James described. For instance, is the RS asks the AS for a permission_ticket for resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the client/RqP supplies claims or goes through claims negotiation, they only can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC).
WDYT?
On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yep, that does make sense. The problem would be:
10 RS requests resourceA(scope1, scope2) 20 AS issues RPT resourceA(scope1) 30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was granted? The situation I want to allow is for the RS to be able to say Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS being able to return partially matched scopes, which with the current introspection can allow the problem you describe. If the introspection of the RPT above instead returned: Granted:resourceA(scope1); Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows there is no point is submitting that permission request again.
WDYT? James
On 25 January 2017 at 17:56, George Fletcher
wrote: Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted.
This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Right, I see. Maybe an example would help?
On 25 January 2017 at 17:35, Eve Maler
wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested):
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts
wrote: Hi all,
Thanks for the reminder to send this email Eve! ;)
The paragraph in question is:
The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access.
I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants *either* view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ 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>
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
A couple of thoughts/questions.
1. James, what state about the RPT are we asking the AS to remember? It
seems like the AS has to remember all previous allowed/rejected
resource_id:scope:timestamp tuples ever associated with the
RPT/PreviousRPT. Does the AS just return the ones within the last 5 mins?
or all of them?
2. Eve, in your last bullet, I'm not sure we want to make client's
understand the concept of resource_id and it's associated scopes. Is that
what you are suggesting? or did I misunderstand?
3. James, when should the RS decide that it's ok to re-ask for a permission
that has been denied in the past? It seems to me it's possible the original
request was denied because the RqP chose not to provide the necessary
claims. After being denied once, the RqP might be willing to give the claim
but if the RS never asks, the RqP never gets the chance?
Thanks,
George
On Wed, Feb 1, 2017 at 2:49 PM Eve Maler
Thanks, James!
To net out your proposal, I believe it is this (please correct if wrong): If the token introspection object response from the AS were to contain a record of the most recent *RequestedScopes*, timestamped in the last few seconds, then the RS would be able to optimize its next action: either return a Forbidden response (as in example #2) or modify its next request for permissions on the client's behalf (as in example #3).
Some questions:
- In example #2, since the *CandidateGrantedScopes* would have come back null according to our current logic, I think the client's RPT request would have gotten rejected at the AS. How does that change the thinking about optimization? - We had started to think that API publishers (RS's) would want to document and publicize their patterns for permission requests, for behavior predictability when it comes to clients attempting resource access. This proposal lets AS's optimize policy operations by virtue of RS's optimizing what they do next. Do RS's want to/can they do that? And how does this impact clients? - Last night I proposed trying, in some way, to bring clients more into the fold of the resource-primary scope-secondary ecosystem. (Though, admittedly, it was far from a complete proposal.) Would this also be a way for AS-RS communications to get opened up more fully to enable better efficiency? - A thought experiment: In our 2.0 drafts, we added the capability to request multiple permissions in anticipation of the type of use case you give here. The alternative would be the UMA1 method: Only requesting one permission (resource ID) at a time. What would happen then? Thoughts: - If we don't let clients express interest in resource-specific scopes, it seems like everything would be reactive and driven off access attempts because scope requests would be ambiguous a lot of the time. - If we find a way for clients to pre-register for and request resource-specific scopes, then this could be really interesting: Instead of the RS having to guess/interpret a lot, the permission ecosystem could be unambiguous and client-driven...
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Feb 1, 2017 at 10:29 AM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Sorry, I'd been meaning to write up that action but something always came up. Here we go...
Take this Google Drive link as an example: https://drive.google.com/drive/folders/0B7eRlQ5s6EfgbFJHU1ZjVFNxelE?usp=shar...
You'll find it's a folder "Test Folder" with 2 files in it, "File1" and "File2". Each of the 3 resources can be shared in their own right. This is not a particularly contrived use case - the same type of structure is used by many websites that support non-UMA resource sharing.
When registering resources at the AS, the relationship between them cannot be expressed, so when registering a permission ticket for an access attempt on either of the files, the RS has to register for the same scopes on both Test Folder and the requested file, expecting either one of them or neither to have a policy granting the requesting party access.
Here are a few scenarios:
1) Alice shared nothing with Bob, no existing RPT
- The client requests File1 - RS registers ticket for Test Folder and File1 - The Client does not get an RPT
No problem here
2) Alice shared nothing with Bob, Bob has existing RPT at the client for the RS
- The client requests File1 - RS registers ticket for Test Folder and File1 - The client gets another RPT with the same resources/scope as the existing one had - Client presents the RPT to the RS
Here we have a problem - the RS has no context for the RPT, so it has to rely on the content of the introspection request in order to find out what it entitles the client to. If the introspection response only contains what is granted, the RS will register another ticket just as it already did, and loop. However, if the response were to contain a record of the attempt for scope on Test Folder and File1, timestamped in the last few seconds, then the RS would know that there was no other way that access could be shared, so it would return a Forbidden response.
3) Alice has shared File1 with Bob
- The client approaches the RS for File1 - RS registers ticket for Test Folder and File1 - The client gets an RPT for File1 - Client presents the RPT to the RS - Client requests File2 with existing RPT
Here is another opportunity for the RS to optimise the UMA flow if the introspection response contains the denial of Test Folder - for File1 the RS would have requested Test Folder and File1, Test Folder is not granted access, if the RS can see this then it knows that for File2 there is no point in submitting a request for both Test Folder and File2 - only File2.
One of the criticisms of the UMA protocol is that it is (or has the potential to be) too chatty - this doesn't really change much in UMA2, but this would be a way to give the RS some extra data that it could use to try and reduce the chattiness. Also, policy evaluation is not a free (nor even necessarily, cheap) operation, and if we can reduce the number of evaluations the AS has to perform.
I'm obviously very happy to be shown how these issues can be mitigated in other ways.
Cheers James
On 1 February 2017 at 00:24, Eve Maler
wrote: I agree that it's best to "think clean"; we do, after all, have design principles http://kantarainitiative.org/confluence/display/uma/UMA+Requirements about simplicity, where to put complexity, etc.
At the conclusion of our last telecon, James took an action item to come up with a proposal where the AS would provide the last-issued ticket, broken out with the state it had kept associated with it, as part of the token introspection object. It would be good to see that, but I also have an idea to do a deeper analysis in prep for our next call, which I'll try to do tonight: a map of all the flow options in the C-AS-RS scope dance, what we want to achieve, and which flows we think are viable for those ends.
====
Specifically regarding default-deny:
In Core rev 13 https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization..., I did keep some default-deny wording that I felt was defensible even if not a testable assertion, covering the original corner case of concern. Do you think this suffices, Justin?
*"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."*
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 31, 2017 at 3:31 PM, Justin Richer
wrote: I’m averse to making the client or RS too smart about cleanup and these half-working conditions. A simpler protocol is more likely to be functional in the long run. If things can fail, they should fail with pretty well defined semantics. In OAuth, you can get a token, and that token can work or not work. This is good enough for the vast majority of situations, and so I’m not in favor of marking things as partially met. It’s adding complexity without benefit that I can clearly see.
I’d also like to remind the group of the original argument that I made to add the “Default Deny” language in there, as it’s got very little to do with the current discussion. Basically, imagine this naive implementation:
- Each resource set has policies that are fulfilled by claims - The client/RqP present claims to fulfill these required policies - If you fulfill any policies on the resource, you get a token with the associated scopes
This is all well and good. However, if you have:
- A resource set that has *no* policies set
Then you could end up with the following aberrant logic:
- Client requests a token for a resource, gather up the set of required claims to access said resource - Required claims is the empty set as no policies are set - Client/RqP present no claims - Empty set satisfies the empty set, client gets issued a token
*this* precise bug is what I was trying to guard against with my original proposal. I fear we’ve gone off into the woods now.
— Justin
On Jan 26, 2017, at 11:10 AM, George Fletcher
wrote: Good point:) I would rather have the AS return to the client that it issued the RPT but didn't fully meet all requested permissions. The problem, is that the client has no clue as to what a resource_set maps to from a URI perspective. I suppose if the AS returned to the client that it was not able to fully meet the permission_ticket scopes in some "partially_met" flag, then the client can try a resource but knows it's possible it won't work.
I think if the client sends a RqP through a claims negotiation flow for access to resourceA, if it has to do the same thing again, it could tell the RqP that access will be denied unless the RqP supplies all the requested claims. Maybe the AS could show this to the user during the interactive claims negotiation?
Bob would probably understand Alice's resource name/description of "Alice's calendar". So, if in interactive mode, the AS could tell Bob, "unfortunately you did not meet the policy necessary to access Alice's calendar". That way the user knows that the next client request for "Alice's calendar" will fail.
Don't know if that's better?
On Thu, Jan 26, 2017 at 10:40 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
That's interesting. I'm still not sure it 100% satisfies what I'm thinking about, as a new RPT that failed to get resourceB would look the same as an existing RPT for resourceA and resourceC, so the RS would send back to try and get resourceB if it needed it.
On 26 January 2017 at 14:13, George Fletcher
wrote: Ahh... good point James. If the permission ticket encompasses multiple resource set ids, then the AS should be able to authorize the different resource set ids separately.
I do worry about requiring the AS to return the "denied" resource_set(scope) tuples, because at introspection time that could be very complicated to reconstruct.
What about the following?
1. The RS is "authoritative" for requesting the required scopes for any resource_set_id. This means that in order for the RPT to include a resource_set:scope tuple, the client/RqP MUST meet all policy for the scopes in the permission_ticket for that resource_set. 2. If the permission_ticket contains multiple resource_set:scope tuples, the AS MAY authorize a partial set of the tuples so long as all the scopes for that tuple are fully met.
This has the effect of encouraging the RS to not request a huge amount of scopes for a given resource_set while not prohibiting the RS from asking for more than is absolutely necessary.
This also, should I believe, address the use case James described. For instance, is the RS asks the AS for a permission_ticket for resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the client/RqP supplies claims or goes through claims negotiation, they only can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC).
WDYT?
On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yep, that does make sense. The problem would be:
10 RS requests resourceA(scope1, scope2) 20 AS issues RPT resourceA(scope1) 30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was granted? The situation I want to allow is for the RS to be able to say Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS being able to return partially matched scopes, which with the current introspection can allow the problem you describe. If the introspection of the RPT above instead returned: Granted:resourceA(scope1); Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows there is no point is submitting that permission request again.
WDYT? James
On 25 January 2017 at 17:56, George Fletcher
wrote: Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted.
This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Right, I see. Maybe an example would help?
On 25 January 2017 at 17:35, Eve Maler
wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested):
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi all,
Thanks for the reminder to send this email Eve! ;)
The paragraph in question is:
The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access.
I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants *either* view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ 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> _______________________________________________ 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
It’s George’s last bullet that bothers me the most about this approach. What if I decide to not give a service my email address, for instance, and then the thing I’m trying to do doesn’t work? The client should get another opportunity to make it work for me. A “smart” client could easily figure out “hey I just sent you over to get this token and it didn’t work, maybe the user’s being a moron” and prompt me with something to that effect. That would stop the cycle. It does in the plain OAuth world, where we have a similar setup. — Justin
On Feb 1, 2017, at 4:07 PM, George Fletcher
wrote: A couple of thoughts/questions.
1. James, what state about the RPT are we asking the AS to remember? It seems like the AS has to remember all previous allowed/rejected resource_id:scope:timestamp tuples ever associated with the RPT/PreviousRPT. Does the AS just return the ones within the last 5 mins? or all of them?
2. Eve, in your last bullet, I'm not sure we want to make client's understand the concept of resource_id and it's associated scopes. Is that what you are suggesting? or did I misunderstand?
3. James, when should the RS decide that it's ok to re-ask for a permission that has been denied in the past? It seems to me it's possible the original request was denied because the RqP chose not to provide the necessary claims. After being denied once, the RqP might be willing to give the claim but if the RS never asks, the RqP never gets the chance?
Thanks, George
On Wed, Feb 1, 2017 at 2:49 PM Eve Maler
mailto:eve@xmlgrrl.com> wrote: Thanks, James! To net out your proposal, I believe it is this (please correct if wrong): If the token introspection object response from the AS were to contain a record of the most recent RequestedScopes, timestamped in the last few seconds, then the RS would be able to optimize its next action: either return a Forbidden response (as in example #2) or modify its next request for permissions on the client's behalf (as in example #3).
Some questions: In example #2, since the CandidateGrantedScopes would have come back null according to our current logic, I think the client's RPT request would have gotten rejected at the AS. How does that change the thinking about optimization? We had started to think that API publishers (RS's) would want to document and publicize their patterns for permission requests, for behavior predictability when it comes to clients attempting resource access. This proposal lets AS's optimize policy operations by virtue of RS's optimizing what they do next. Do RS's want to/can they do that? And how does this impact clients? Last night I proposed trying, in some way, to bring clients more into the fold of the resource-primary scope-secondary ecosystem. (Though, admittedly, it was far from a complete proposal.) Would this also be a way for AS-RS communications to get opened up more fully to enable better efficiency? A thought experiment: In our 2.0 drafts, we added the capability to request multiple permissions in anticipation of the type of use case you give here. The alternative would be the UMA1 method: Only requesting one permission (resource ID) at a time. What would happen then? Thoughts: If we don't let clients express interest in resource-specific scopes, it seems like everything would be reactive and driven off access attempts because scope requests would be ambiguous a lot of the time. If we find a way for clients to pre-register for and request resource-specific scopes, then this could be really interesting: Instead of the RS having to guess/interpret a lot, the permission ecosystem could be unambiguous and client-driven...
Eve Maler Cell +1 425.345.6756 tel:(425)%20345-6756 | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Feb 1, 2017 at 10:29 AM, James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: Sorry, I'd been meaning to write up that action but something always came up. Here we go... Take this Google Drive link as an example: https://drive.google.com/drive/folders/0B7eRlQ5s6EfgbFJHU1ZjVFNxelE?usp=shar... https://drive.google.com/drive/folders/0B7eRlQ5s6EfgbFJHU1ZjVFNxelE?usp=shar...
You'll find it's a folder "Test Folder" with 2 files in it, "File1" and "File2". Each of the 3 resources can be shared in their own right. This is not a particularly contrived use case - the same type of structure is used by many websites that support non-UMA resource sharing.
When registering resources at the AS, the relationship between them cannot be expressed, so when registering a permission ticket for an access attempt on either of the files, the RS has to register for the same scopes on both Test Folder and the requested file, expecting either one of them or neither to have a policy granting the requesting party access.
Here are a few scenarios:
1) Alice shared nothing with Bob, no existing RPT The client requests File1 RS registers ticket for Test Folder and File1 The Client does not get an RPT No problem here
2) Alice shared nothing with Bob, Bob has existing RPT at the client for the RS The client requests File1 RS registers ticket for Test Folder and File1 The client gets another RPT with the same resources/scope as the existing one had Client presents the RPT to the RS Here we have a problem - the RS has no context for the RPT, so it has to rely on the content of the introspection request in order to find out what it entitles the client to. If the introspection response only contains what is granted, the RS will register another ticket just as it already did, and loop. However, if the response were to contain a record of the attempt for scope on Test Folder and File1, timestamped in the last few seconds, then the RS would know that there was no other way that access could be shared, so it would return a Forbidden response.
3) Alice has shared File1 with Bob The client approaches the RS for File1 RS registers ticket for Test Folder and File1 The client gets an RPT for File1 Client presents the RPT to the RS Client requests File2 with existing RPT Here is another opportunity for the RS to optimise the UMA flow if the introspection response contains the denial of Test Folder - for File1 the RS would have requested Test Folder and File1, Test Folder is not granted access, if the RS can see this then it knows that for File2 there is no point in submitting a request for both Test Folder and File2 - only File2.
One of the criticisms of the UMA protocol is that it is (or has the potential to be) too chatty - this doesn't really change much in UMA2, but this would be a way to give the RS some extra data that it could use to try and reduce the chattiness. Also, policy evaluation is not a free (nor even necessarily, cheap) operation, and if we can reduce the number of evaluations the AS has to perform.
I'm obviously very happy to be shown how these issues can be mitigated in other ways.
Cheers James
On 1 February 2017 at 00:24, Eve Maler
mailto:eve@xmlgrrl.com> wrote: I agree that it's best to "think clean"; we do, after all, have design principles http://kantarainitiative.org/confluence/display/uma/UMA+Requirements about simplicity, where to put complexity, etc. At the conclusion of our last telecon, James took an action item to come up with a proposal where the AS would provide the last-issued ticket, broken out with the state it had kept associated with it, as part of the token introspection object. It would be good to see that, but I also have an idea to do a deeper analysis in prep for our next call, which I'll try to do tonight: a map of all the flow options in the C-AS-RS scope dance, what we want to achieve, and which flows we think are viable for those ends.
====
Specifically regarding default-deny:
In Core rev 13 https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization..., I did keep some default-deny wording that I felt was defensible even if not a testable assertion, covering the original corner case of concern. Do you think this suffices, Justin?
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
Eve Maler Cell +1 425.345.6756 tel:(425)%20345-6756 | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 31, 2017 at 3:31 PM, Justin Richer
mailto:jricher@mit.edu> wrote: I’m averse to making the client or RS too smart about cleanup and these half-working conditions. A simpler protocol is more likely to be functional in the long run. If things can fail, they should fail with pretty well defined semantics. In OAuth, you can get a token, and that token can work or not work. This is good enough for the vast majority of situations, and so I’m not in favor of marking things as partially met. It’s adding complexity without benefit that I can clearly see. I’d also like to remind the group of the original argument that I made to add the “Default Deny” language in there, as it’s got very little to do with the current discussion. Basically, imagine this naive implementation:
- Each resource set has policies that are fulfilled by claims - The client/RqP present claims to fulfill these required policies - If you fulfill any policies on the resource, you get a token with the associated scopes
This is all well and good. However, if you have:
- A resource set that has *no* policies set
Then you could end up with the following aberrant logic:
- Client requests a token for a resource, gather up the set of required claims to access said resource - Required claims is the empty set as no policies are set - Client/RqP present no claims - Empty set satisfies the empty set, client gets issued a token
*this* precise bug is what I was trying to guard against with my original proposal. I fear we’ve gone off into the woods now.
— Justin
On Jan 26, 2017, at 11:10 AM, George Fletcher
mailto:george.fletcher@teamaol.com> wrote: Good point:) I would rather have the AS return to the client that it issued the RPT but didn't fully meet all requested permissions. The problem, is that the client has no clue as to what a resource_set maps to from a URI perspective. I suppose if the AS returned to the client that it was not able to fully meet the permission_ticket scopes in some "partially_met" flag, then the client can try a resource but knows it's possible it won't work.
I think if the client sends a RqP through a claims negotiation flow for access to resourceA, if it has to do the same thing again, it could tell the RqP that access will be denied unless the RqP supplies all the requested claims. Maybe the AS could show this to the user during the interactive claims negotiation?
Bob would probably understand Alice's resource name/description of "Alice's calendar". So, if in interactive mode, the AS could tell Bob, "unfortunately you did not meet the policy necessary to access Alice's calendar". That way the user knows that the next client request for "Alice's calendar" will fail.
Don't know if that's better?
On Thu, Jan 26, 2017 at 10:40 AM James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: That's interesting. I'm still not sure it 100% satisfies what I'm thinking about, as a new RPT that failed to get resourceB would look the same as an existing RPT for resourceA and resourceC, so the RS would send back to try and get resourceB if it needed it. On 26 January 2017 at 14:13, George Fletcher
mailto:george.fletcher@teamaol.com> wrote: Ahh... good point James. If the permission ticket encompasses multiple resource set ids, then the AS should be able to authorize the different resource set ids separately. I do worry about requiring the AS to return the "denied" resource_set(scope) tuples, because at introspection time that could be very complicated to reconstruct.
What about the following?
1. The RS is "authoritative" for requesting the required scopes for any resource_set_id. This means that in order for the RPT to include a resource_set:scope tuple, the client/RqP MUST meet all policy for the scopes in the permission_ticket for that resource_set. 2. If the permission_ticket contains multiple resource_set:scope tuples, the AS MAY authorize a partial set of the tuples so long as all the scopes for that tuple are fully met.
This has the effect of encouraging the RS to not request a huge amount of scopes for a given resource_set while not prohibiting the RS from asking for more than is absolutely necessary.
This also, should I believe, address the use case James described. For instance, is the RS asks the AS for a permission_ticket for resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the client/RqP supplies claims or goes through claims negotiation, they only can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC).
WDYT?
On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: Yep, that does make sense. The problem would be: 10 RS requests resourceA(scope1, scope2) 20 AS issues RPT resourceA(scope1) 30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was granted? The situation I want to allow is for the RS to be able to say Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS being able to return partially matched scopes, which with the current introspection can allow the problem you describe. If the introspection of the RPT above instead returned: Granted:resourceA(scope1); Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows there is no point is submitting that permission request again.
WDYT? James
On 25 January 2017 at 17:56, George Fletcher
mailto:george.fletcher@teamaol.com> wrote: Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted. This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: Right, I see. Maybe an example would help? On 25 January 2017 at 17:35, Eve Maler
mailto:eve@xmlgrrl.com> wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested): "Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
Eve Maler Cell +1 425.345.6756 tel:(425)%20345-6756 | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts
mailto:james.phillpotts@forgerock.com> wrote: Hi all, Thanks for the reminder to send this email Eve! ;)
The paragraph in question is: The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access. I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
On one of the calls I thought someone had mentioned that the RPT should only be granted if all of the scopes requested in the permission ticket were able to be granted, but I think it should be perfectly reasonable to grant a subset - e.g. if ticket requests view, edit for resource A and view for resource B but all that can be granted is view for A, then that is a perfectly reasonable response?
This was partly triggered by Mike's suggestion of patterned URIs, where I was thinking about the RS wants either view on A, view on B or view on C, because it knows that the actual requested URL is covered by all 3 of those registered resource sets (although as per other email, I wouldn't like that to be a pattern).
Sorry if this is slightly rambling.
Cheers, James
_______________________________________________ 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
_______________________________________________ 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 -- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 tel:(703)%20462-3494 Office:+1-703-265-2544 tel:(703)%20265-2544 -- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 tel:(703)%20462-3494 Office:+1-703-265-2544 tel:(703)%20265-2544 -- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 tel:(703)%20462-3494 Office:+1-703-265-2544 tel:(703)%20265-2544_______________________________________________ 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
_______________________________________________ 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
_______________________________________________ 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
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544
re #2:
Here's an example taken from the Salesforce OAuth scopes
https://help.salesforce.com/articleView?id=remoteaccess_oauth_scopes.htm&type=0
documentation:
Clients have to know which scopes are good for which resources, but can
only ask for scopes. The api scope is only good for use with "API"
resources (and oh by the way, also implicitly includes chatter_api scope,
which if it were granted, is only good specifically for the "Chatter" API).
The id scope is only good for use with the "identity URL service". And so
on.
In the case of resources for an API such as FHIR, the scopes are way less
interesting: So far they're just read and write. So if the client asks for
a scope, it's a lot less revealing as to what it would like to do. All it
can really express at the token endpoint is that it wants, say, write
access in addition to its previously attempted read access (implicitly to
the same resource??), not read access to the surrounding EHR in addition to
read access to the specific medication list it was just trying to read.
If it were possible for clients to explicitly (pre-register for and)
request not just scopes but the resources they are associated with, at
least in some circumstances, then certain communications jobs could get a
lot easier. For example, maybe RS's wouldn't have to interpret and guess so
much at the point of requesting permissions; they could do a relatively
straightforward 1:1 translation job because the client could request
exactly what they want at RPT request time. And then if we want, the AS
could tell the RS what the client asked for and failed at in an entire
authorization process, as some adjunct to token introspection.
In the case of APIs with predictable endpoints, I can imagine this being
possible to do outside of/prior to a resource owner context. Admittedly, in
the case of certain other kinds of resources, such as file systems and
other interfaces with dynamic numbers of endpoints, maybe not so much --
everything needs to be registered in a specific resource owner's context
before anything can be known.
*Eve Maler*Cell +1 425.345.6756 | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Feb 1, 2017 at 1:07 PM, George Fletcher wrote: A couple of thoughts/questions. 1. James, what state about the RPT are we asking the AS to remember? It
seems like the AS has to remember all previous allowed/rejected
resource_id:scope:timestamp tuples ever associated with the
RPT/PreviousRPT. Does the AS just return the ones within the last 5 mins?
or all of them? 2. Eve, in your last bullet, I'm not sure we want to make client's
understand the concept of resource_id and it's associated scopes. Is that
what you are suggesting? or did I misunderstand? 3. James, when should the RS decide that it's ok to re-ask for a
permission that has been denied in the past? It seems to me it's possible
the original request was denied because the RqP chose not to provide the
necessary claims. After being denied once, the RqP might be willing to give
the claim but if the RS never asks, the RqP never gets the chance? Thanks,
George On Wed, Feb 1, 2017 at 2:49 PM Eve Maler Thanks, James! To net out your proposal, I believe it is this (please correct if wrong):
If the token introspection object response from the AS were to contain a
record of the most recent *RequestedScopes*, timestamped in the last few
seconds, then the RS would be able to optimize its next action: either
return a Forbidden response (as in example #2) or modify its next request
for permissions on the client's behalf (as in example #3). Some questions: - In example #2, since the *CandidateGrantedScopes* would have come
back null according to our current logic, I think the client's RPT request
would have gotten rejected at the AS. How does that change the thinking
about optimization?
- We had started to think that API publishers (RS's) would want to
document and publicize their patterns for permission requests, for behavior
predictability when it comes to clients attempting resource access. This
proposal lets AS's optimize policy operations by virtue of RS's optimizing
what they do next. Do RS's want to/can they do that? And how does this
impact clients?
- Last night I proposed trying, in some way, to bring clients more
into the fold of the resource-primary scope-secondary ecosystem. (Though,
admittedly, it was far from a complete proposal.) Would this also be a way
for AS-RS communications to get opened up more fully to enable better
efficiency?
- A thought experiment: In our 2.0 drafts, we added the capability to
request multiple permissions in anticipation of the type of use case you
give here. The alternative would be the UMA1 method: Only requesting one
permission (resource ID) at a time. What would happen then? Thoughts:
- If we don't let clients express interest in resource-specific
scopes, it seems like everything would be reactive and driven off access
attempts because scope requests would be ambiguous a lot of the time.
- If we find a way for clients to pre-register for and request
resource-specific scopes, then this could be really interesting: Instead of
the RS having to guess/interpret a lot, the permission ecosystem could be
unambiguous and client-driven... *Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl |
Twitter: @xmlgrrl On Wed, Feb 1, 2017 at 10:29 AM, James Phillpotts <
james.phillpotts@forgerock.com> wrote: Sorry, I'd been meaning to write up that action but something always came
up. Here we go... Take this Google Drive link as an example: https://drive.google.
com/drive/folders/0B7eRlQ5s6EfgbFJHU1ZjVFNxelE?usp=sharing You'll find it's a folder "Test Folder" with 2 files in it, "File1" and
"File2". Each of the 3 resources can be shared in their own right. This is
not a particularly contrived use case - the same type of structure is used
by many websites that support non-UMA resource sharing. When registering resources at the AS, the relationship between them
cannot be expressed, so when registering a permission ticket for an access
attempt on either of the files, the RS has to register for the same scopes
on both Test Folder and the requested file, expecting either one of them or
neither to have a policy granting the requesting party access. Here are a few scenarios: 1) Alice shared nothing with Bob, no existing RPT - The client requests File1
- RS registers ticket for Test Folder and File1
- The Client does not get an RPT No problem here 2) Alice shared nothing with Bob, Bob has existing RPT at the client for
the RS - The client requests File1
- RS registers ticket for Test Folder and File1
- The client gets another RPT with the same resources/scope as the
existing one had
- Client presents the RPT to the RS Here we have a problem - the RS has no context for the RPT, so it has to
rely on the content of the introspection request in order to find out what
it entitles the client to. If the introspection response only contains what
is granted, the RS will register another ticket just as it already did, and
loop. However, if the response were to contain a record of the attempt for
scope on Test Folder and File1, timestamped in the last few seconds, then
the RS would know that there was no other way that access could be shared,
so it would return a Forbidden response. 3) Alice has shared File1 with Bob - The client approaches the RS for File1
- RS registers ticket for Test Folder and File1
- The client gets an RPT for File1
- Client presents the RPT to the RS
- Client requests File2 with existing RPT Here is another opportunity for the RS to optimise the UMA flow if the
introspection response contains the denial of Test Folder - for File1 the
RS would have requested Test Folder and File1, Test Folder is not granted
access, if the RS can see this then it knows that for File2 there is no
point in submitting a request for both Test Folder and File2 - only File2. One of the criticisms of the UMA protocol is that it is (or has the
potential to be) too chatty - this doesn't really change much in UMA2, but
this would be a way to give the RS some extra data that it could use to try
and reduce the chattiness. Also, policy evaluation is not a free (nor even
necessarily, cheap) operation, and if we can reduce the number of
evaluations the AS has to perform. I'm obviously very happy to be shown how these issues can be mitigated in
other ways. Cheers
James On 1 February 2017 at 00:24, Eve Maler I agree that it's best to "think clean"; we do, after all, have design
principles
http://kantarainitiative.org/confluence/display/uma/UMA+Requirements
about simplicity, where to put complexity, etc. At the conclusion of our last telecon, James took an action item to come
up with a proposal where the AS would provide the last-issued ticket,
broken out with the state it had kept associated with it, as part of the
token introspection object. It would be good to see that, but I also have
an idea to do a deeper analysis in prep for our next call, which I'll try
to do tonight: a map of all the flow options in the C-AS-RS scope dance,
what we want to achieve, and which flows we think are viable for those ends. ==== Specifically regarding default-deny: In Core rev 13
https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization...,
I did keep some default-deny wording that I felt was defensible even if not
a testable assertion, covering the original corner case of concern. Do you
think this suffices, Justin? *"Note: While a reasonable approach for most scenarios is to implement
the classic security stance of default-deny ("everything that is not
expressly allowed is forbidden"), corner cases can inadvertently result in
default-permit behavior. For example, it is insufficient simply to assume
that all resources have some non-zero set of claims required for access,
and then accept an empty set of supplied claims as sufficient for access."* *Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl |
Twitter: @xmlgrrl On Tue, Jan 31, 2017 at 3:31 PM, Justin Richer I’m averse to making the client or RS too smart about cleanup and these
half-working conditions. A simpler protocol is more likely to be functional
in the long run. If things can fail, they should fail with pretty well
defined semantics. In OAuth, you can get a token, and that token can work
or not work. This is good enough for the vast majority of situations, and
so I’m not in favor of marking things as partially met. It’s adding
complexity without benefit that I can clearly see. I’d also like to remind the group of the original argument that I made to
add the “Default Deny” language in there, as it’s got very little to do
with the current discussion. Basically, imagine this naive implementation: - Each resource set has policies that are fulfilled by claims
- The client/RqP present claims to fulfill these required policies
- If you fulfill any policies on the resource, you get a token with the
associated scopes This is all well and good. However, if you have: - A resource set that has *no* policies set Then you could end up with the following aberrant logic: - Client requests a token for a resource, gather up the set of required
claims to access said resource
- Required claims is the empty set as no policies are set
- Client/RqP present no claims
- Empty set satisfies the empty set, client gets issued a token *this* precise bug is what I was trying to guard against with my original
proposal. I fear we’ve gone off into the woods now. — Justin On Jan 26, 2017, at 11:10 AM, George Fletcher <
george.fletcher@teamaol.com> wrote: Good point:) I would rather have the AS return to the client that it
issued the RPT but didn't fully meet all requested permissions. The
problem, is that the client has no clue as to what a resource_set maps to
from a URI perspective. I suppose if the AS returned to the client that it
was not able to fully meet the permission_ticket scopes in some
"partially_met" flag, then the client can try a resource but knows it's
possible it won't work. I think if the client sends a RqP through a claims negotiation flow for
access to resourceA, if it has to do the same thing again, it could tell
the RqP that access will be denied unless the RqP supplies all the
requested claims. Maybe the AS could show this to the user during the
interactive claims negotiation? Bob would probably understand Alice's resource name/description of
"Alice's calendar". So, if in interactive mode, the AS could tell Bob,
"unfortunately you did not meet the policy necessary to access Alice's
calendar". That way the user knows that the next client request for
"Alice's calendar" will fail. Don't know if that's better? On Thu, Jan 26, 2017 at 10:40 AM James Phillpotts <
james.phillpotts@forgerock.com> wrote: That's interesting. I'm still not sure it 100% satisfies what I'm
thinking about, as a new RPT that failed to get resourceB would look the
same as an existing RPT for resourceA and resourceC, so the RS would send
back to try and get resourceB if it needed it. On 26 January 2017 at 14:13, George Fletcher wrote: Ahh... good point James. If the permission ticket encompasses multiple
resource set ids, then the AS should be able to authorize the different
resource set ids separately. I do worry about requiring the AS to return the "denied"
resource_set(scope) tuples, because at introspection time that could be
very complicated to reconstruct. What about the following? 1. The RS is "authoritative" for requesting the required scopes for any
resource_set_id. This means that in order for the RPT to include a
resource_set:scope tuple, the client/RqP MUST meet all policy for the
scopes in the permission_ticket for that resource_set.
2. If the permission_ticket contains multiple resource_set:scope tuples,
the AS MAY authorize a partial set of the tuples so long as all the scopes
for that tuple are fully met. This has the effect of encouraging the RS to not request a huge amount of
scopes for a given resource_set while not prohibiting the RS from asking
for more than is absolutely necessary. This also, should I believe, address the use case James described. For
instance, is the RS asks the AS for a permission_ticket for
resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the
client/RqP supplies claims or goes through claims negotiation, they only
can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The
AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC). WDYT? On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts <
james.phillpotts@forgerock.com> wrote: Yep, that does make sense. The problem would be: 10 RS requests resourceA(scope1, scope2)
20 AS issues RPT resourceA(scope1)
30 RS introspects RPT, finds insufficient scope for request, GOTO 10 Maybe what the RS needs to know is what was denied as well as what was
granted? The situation I want to allow is for the RS to be able to say
Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS
being able to return partially matched scopes, which with the current
introspection can allow the problem you describe. If the introspection of
the RPT above instead returned: Granted:resourceA(scope1);
Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows
there is no point is submitting that permission request again. WDYT?
James On 25 January 2017 at 17:56, George Fletcher wrote: Given that the RPT is somewhat equivalent to an OAuth2 access token, the
OAuth2 best practice is to return the set of scopes that were met as part
of the request, and also inform the client of which scopes where granted. This becomes a little more problematic for the scopes defined by the
permissions_ticket because the client doesn't know what they are. If we
allow the "partial scopes" response, it will be possible for the client to
successfully get an RPT that does not provide it the access it needs to a
particular resource. Take the following example: Alice has a photo album that Bob is trying to access. Bob's client makes
the request to Alice's album and the RS requests the AS to generate a
permission_ticket with view,edit scopes for the resource. Bob's client
presents the permission_ticket to the AS and goes through some claims
negotiation. The result of the set math is that Bob's client gets 'edit'
scope but not 'view'. If the AS issues the RPT with just the 'edit' scope,
the it's unlikely that Bob's client will work as it really wanted 'view'
access. I'm becoming more convinced that the responsibility for the scopes
necessary to issue the RPT must lie with the RS and NOT the AS. If the RS
is asking for too many scopes up front, then Bob's experience will have a
lot of overhead just to be able to view the photos. On the other hand, if
the RS asks for just the scopes needed and the AS overrides that decision
by returning less, the overall experience will break. Hopefully that makes sense:) Thanks,
George On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts <
james.phillpotts@forgerock.com> wrote: Right, I see. Maybe an example would help? On 25 January 2017 at 17:35, Eve Maler Hey, I'm always up for a good disquisition ("a long or elaborate essay or
discussion on a particular subject"). :-) In fact, I did try new wording in
rev 13 already based on the fact that with our set math I couldn't make
heads or tails of the MUST wording (note that this comes after the new
agreed wording
https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization...
about the AS having a choice to respond with an RPT or a failure if the
scopes satisfied are less than the scopes requested): "Note: While a reasonable approach for most scenarios is to implement the
classic security stance of default-deny ("everything that is not expressly
allowed is forbidden"), corner cases can inadvertently result in
default-permit behavior. For example, it is insufficient simply to assume
that all resources have some non-zero set of claims required for access,
and then accept an empty set of supplied claims as sufficient for access." This was in order to advise anyone starting to build an AS from scratch
about some of the best practices and subtleties of policy engine and access
control work. Thoughts? *Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl |
Twitter: @xmlgrrl On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts Hi all, Thanks for the reminder to send this email Eve! ;) The paragraph in question is: The authorization server MUST use a default-deny authorization assessment
model in adding permissions to RPTs, that is, "everything that is not
expressly allowed is forbidden" for resources for which resource servers
have requested access permission on behalf of clients. Exercise caution in
implementing default-deny because corner cases can inadvertently result in
default-permit behavior. For example, it is insufficient simply to assume
that all resources have some non-zero set of claims required for access,
and then accept an empty set of supplied claims as sufficient for access. I'm not convinced that this paragraph is really very useful, but that may
be because it isn't clear at what level the 'deny' is relating to in this
context - is it on a per-resource, per-scope, or an RPT level? If per-resource, I think this is a reasonable thing to express, but I'm
not sure the paragraph does a particularly good job of it. If per-scope, does this only apply to additional scopes requested by the
client? If RPT, then I don't think the idea is correct, as the RPT shouldn't be
denied based on the outcome of a particular policy for a particular
resource. On one of the calls I thought someone had mentioned that the RPT should
only be granted if all of the scopes requested in the permission ticket
were able to be granted, but I think it should be perfectly reasonable to
grant a subset - e.g. if ticket requests view, edit for resource A and view
for resource B but all that can be granted is view for A, then that is a
perfectly reasonable response? This was partly triggered by Mike's suggestion of patterned URIs, where I
was thinking about the RS wants *either* view on A, view on B or view on
C, because it knows that the actual requested URL is covered by all 3 of
those registered resource sets (although as per other email, I wouldn't
like that to be a pattern). Sorry if this is slightly rambling. Cheers,
James _______________________________________________
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> -- ... [Message clipped]
To me the Salesforce example is just using scopes to authorize access to
particular subsets of the over all Salesforce API. For me this is
conceptually different than a client needing to know that RS
photos/alice/nature/landscape has scope {view} and
photos/alice/forsale/images has scopes {view,download}.
At the RS API authorization level, scopes make sense and clients can be
smart about applying scopes to particular resources. However, when we move
into user specific resource I think it will get much less clear about how
easy it is for a client "to know" what scopes apply.
Maybe a better question would be whether a RS would ever allow the RO to
define what scopes are registered for a particular resource making the
scope to RS relationship user specific.
Thanks,
George
On Wed, Feb 1, 2017 at 5:07 PM Eve Maler
re #2:
Here's an example taken from the Salesforce OAuth scopes https://help.salesforce.com/articleView?id=remoteaccess_oauth_scopes.htm&type=0 documentation: Clients have to know which scopes are good for which resources, but can only ask for scopes. The api scope is only good for use with "API" resources (and oh by the way, also implicitly includes chatter_api scope, which if it were granted, is only good specifically for the "Chatter" API). The id scope is only good for use with the "identity URL service". And so on.
In the case of resources for an API such as FHIR, the scopes are way less interesting: So far they're just read and write. So if the client asks for a scope, it's a lot less revealing as to what it would like to do. All it can really express at the token endpoint is that it wants, say, write access in addition to its previously attempted read access (implicitly to the same resource??), not read access to the surrounding EHR in addition to read access to the specific medication list it was just trying to read.
If it were possible for clients to explicitly (pre-register for and) request not just scopes but the resources they are associated with, at least in some circumstances, then certain communications jobs could get a lot easier. For example, maybe RS's wouldn't have to interpret and guess so much at the point of requesting permissions; they could do a relatively straightforward 1:1 translation job because the client could request exactly what they want at RPT request time. And then if we want, the AS could tell the RS what the client asked for and failed at in an entire authorization process, as some adjunct to token introspection.
In the case of APIs with predictable endpoints, I can imagine this being possible to do outside of/prior to a resource owner context. Admittedly, in the case of certain other kinds of resources, such as file systems and other interfaces with dynamic numbers of endpoints, maybe not so much -- everything needs to be registered in a specific resource owner's context before anything can be known.
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Feb 1, 2017 at 1:07 PM, George Fletcher < george.fletcher@teamaol.com> wrote:
A couple of thoughts/questions.
1. James, what state about the RPT are we asking the AS to remember? It seems like the AS has to remember all previous allowed/rejected resource_id:scope:timestamp tuples ever associated with the RPT/PreviousRPT. Does the AS just return the ones within the last 5 mins? or all of them?
2. Eve, in your last bullet, I'm not sure we want to make client's understand the concept of resource_id and it's associated scopes. Is that what you are suggesting? or did I misunderstand?
3. James, when should the RS decide that it's ok to re-ask for a permission that has been denied in the past? It seems to me it's possible the original request was denied because the RqP chose not to provide the necessary claims. After being denied once, the RqP might be willing to give the claim but if the RS never asks, the RqP never gets the chance?
Thanks, George
On Wed, Feb 1, 2017 at 2:49 PM Eve Maler
wrote: Thanks, James!
To net out your proposal, I believe it is this (please correct if wrong): If the token introspection object response from the AS were to contain a record of the most recent *RequestedScopes*, timestamped in the last few seconds, then the RS would be able to optimize its next action: either return a Forbidden response (as in example #2) or modify its next request for permissions on the client's behalf (as in example #3).
Some questions:
- In example #2, since the *CandidateGrantedScopes* would have come back null according to our current logic, I think the client's RPT request would have gotten rejected at the AS. How does that change the thinking about optimization? - We had started to think that API publishers (RS's) would want to document and publicize their patterns for permission requests, for behavior predictability when it comes to clients attempting resource access. This proposal lets AS's optimize policy operations by virtue of RS's optimizing what they do next. Do RS's want to/can they do that? And how does this impact clients? - Last night I proposed trying, in some way, to bring clients more into the fold of the resource-primary scope-secondary ecosystem. (Though, admittedly, it was far from a complete proposal.) Would this also be a way for AS-RS communications to get opened up more fully to enable better efficiency? - A thought experiment: In our 2.0 drafts, we added the capability to request multiple permissions in anticipation of the type of use case you give here. The alternative would be the UMA1 method: Only requesting one permission (resource ID) at a time. What would happen then? Thoughts: - If we don't let clients express interest in resource-specific scopes, it seems like everything would be reactive and driven off access attempts because scope requests would be ambiguous a lot of the time. - If we find a way for clients to pre-register for and request resource-specific scopes, then this could be really interesting: Instead of the RS having to guess/interpret a lot, the permission ecosystem could be unambiguous and client-driven...
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Feb 1, 2017 at 10:29 AM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Sorry, I'd been meaning to write up that action but something always came up. Here we go...
Take this Google Drive link as an example: https://drive.google.com/drive/folders/0B7eRlQ5s6EfgbFJHU1ZjVFNxelE?usp=shar...
You'll find it's a folder "Test Folder" with 2 files in it, "File1" and "File2". Each of the 3 resources can be shared in their own right. This is not a particularly contrived use case - the same type of structure is used by many websites that support non-UMA resource sharing.
When registering resources at the AS, the relationship between them cannot be expressed, so when registering a permission ticket for an access attempt on either of the files, the RS has to register for the same scopes on both Test Folder and the requested file, expecting either one of them or neither to have a policy granting the requesting party access.
Here are a few scenarios:
1) Alice shared nothing with Bob, no existing RPT
- The client requests File1 - RS registers ticket for Test Folder and File1 - The Client does not get an RPT
No problem here
2) Alice shared nothing with Bob, Bob has existing RPT at the client for the RS
- The client requests File1 - RS registers ticket for Test Folder and File1 - The client gets another RPT with the same resources/scope as the existing one had - Client presents the RPT to the RS
Here we have a problem - the RS has no context for the RPT, so it has to rely on the content of the introspection request in order to find out what it entitles the client to. If the introspection response only contains what is granted, the RS will register another ticket just as it already did, and loop. However, if the response were to contain a record of the attempt for scope on Test Folder and File1, timestamped in the last few seconds, then the RS would know that there was no other way that access could be shared, so it would return a Forbidden response.
3) Alice has shared File1 with Bob
- The client approaches the RS for File1 - RS registers ticket for Test Folder and File1 - The client gets an RPT for File1 - Client presents the RPT to the RS - Client requests File2 with existing RPT
Here is another opportunity for the RS to optimise the UMA flow if the introspection response contains the denial of Test Folder - for File1 the RS would have requested Test Folder and File1, Test Folder is not granted access, if the RS can see this then it knows that for File2 there is no point in submitting a request for both Test Folder and File2 - only File2.
One of the criticisms of the UMA protocol is that it is (or has the potential to be) too chatty - this doesn't really change much in UMA2, but this would be a way to give the RS some extra data that it could use to try and reduce the chattiness. Also, policy evaluation is not a free (nor even necessarily, cheap) operation, and if we can reduce the number of evaluations the AS has to perform.
I'm obviously very happy to be shown how these issues can be mitigated in other ways.
Cheers James
On 1 February 2017 at 00:24, Eve Maler
wrote: I agree that it's best to "think clean"; we do, after all, have design principles http://kantarainitiative.org/confluence/display/uma/UMA+Requirements about simplicity, where to put complexity, etc.
At the conclusion of our last telecon, James took an action item to come up with a proposal where the AS would provide the last-issued ticket, broken out with the state it had kept associated with it, as part of the token introspection object. It would be good to see that, but I also have an idea to do a deeper analysis in prep for our next call, which I'll try to do tonight: a map of all the flow options in the C-AS-RS scope dance, what we want to achieve, and which flows we think are viable for those ends.
====
Specifically regarding default-deny:
In Core rev 13 https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization..., I did keep some default-deny wording that I felt was defensible even if not a testable assertion, covering the original corner case of concern. Do you think this suffices, Justin?
*"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."*
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Tue, Jan 31, 2017 at 3:31 PM, Justin Richer
wrote: I’m averse to making the client or RS too smart about cleanup and these half-working conditions. A simpler protocol is more likely to be functional in the long run. If things can fail, they should fail with pretty well defined semantics. In OAuth, you can get a token, and that token can work or not work. This is good enough for the vast majority of situations, and so I’m not in favor of marking things as partially met. It’s adding complexity without benefit that I can clearly see.
I’d also like to remind the group of the original argument that I made to add the “Default Deny” language in there, as it’s got very little to do with the current discussion. Basically, imagine this naive implementation:
- Each resource set has policies that are fulfilled by claims - The client/RqP present claims to fulfill these required policies - If you fulfill any policies on the resource, you get a token with the associated scopes
This is all well and good. However, if you have:
- A resource set that has *no* policies set
Then you could end up with the following aberrant logic:
- Client requests a token for a resource, gather up the set of required claims to access said resource - Required claims is the empty set as no policies are set - Client/RqP present no claims - Empty set satisfies the empty set, client gets issued a token
*this* precise bug is what I was trying to guard against with my original proposal. I fear we’ve gone off into the woods now.
— Justin
On Jan 26, 2017, at 11:10 AM, George Fletcher
wrote: Good point:) I would rather have the AS return to the client that it issued the RPT but didn't fully meet all requested permissions. The problem, is that the client has no clue as to what a resource_set maps to from a URI perspective. I suppose if the AS returned to the client that it was not able to fully meet the permission_ticket scopes in some "partially_met" flag, then the client can try a resource but knows it's possible it won't work.
I think if the client sends a RqP through a claims negotiation flow for access to resourceA, if it has to do the same thing again, it could tell the RqP that access will be denied unless the RqP supplies all the requested claims. Maybe the AS could show this to the user during the interactive claims negotiation?
Bob would probably understand Alice's resource name/description of "Alice's calendar". So, if in interactive mode, the AS could tell Bob, "unfortunately you did not meet the policy necessary to access Alice's calendar". That way the user knows that the next client request for "Alice's calendar" will fail.
Don't know if that's better?
On Thu, Jan 26, 2017 at 10:40 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
That's interesting. I'm still not sure it 100% satisfies what I'm thinking about, as a new RPT that failed to get resourceB would look the same as an existing RPT for resourceA and resourceC, so the RS would send back to try and get resourceB if it needed it.
On 26 January 2017 at 14:13, George Fletcher
wrote: Ahh... good point James. If the permission ticket encompasses multiple resource set ids, then the AS should be able to authorize the different resource set ids separately.
I do worry about requiring the AS to return the "denied" resource_set(scope) tuples, because at introspection time that could be very complicated to reconstruct.
What about the following?
1. The RS is "authoritative" for requesting the required scopes for any resource_set_id. This means that in order for the RPT to include a resource_set:scope tuple, the client/RqP MUST meet all policy for the scopes in the permission_ticket for that resource_set. 2. If the permission_ticket contains multiple resource_set:scope tuples, the AS MAY authorize a partial set of the tuples so long as all the scopes for that tuple are fully met.
This has the effect of encouraging the RS to not request a huge amount of scopes for a given resource_set while not prohibiting the RS from asking for more than is absolutely necessary.
This also, should I believe, address the use case James described. For instance, is the RS asks the AS for a permission_ticket for resourceA(scopeA), resourceB(scopeB), resourceC(scopeC). And when the client/RqP supplies claims or goes through claims negotiation, they only can satisfy the RO policy for resourceA(scopeA) and resourceC(scopeC). The AS can then return the RPT with resourceA(scopeA) and resourceC(scopeC).
WDYT?
On Thu, Jan 26, 2017 at 6:42 AM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Yep, that does make sense. The problem would be:
10 RS requests resourceA(scope1, scope2) 20 AS issues RPT resourceA(scope1) 30 RS introspects RPT, finds insufficient scope for request, GOTO 10
Maybe what the RS needs to know is what was denied as well as what was granted? The situation I want to allow is for the RS to be able to say Either(resourceA(scope1), resourceB(scope1) - but that relies on the AS being able to return partially matched scopes, which with the current introspection can allow the problem you describe. If the introspection of the RPT above instead returned: Granted:resourceA(scope1); Denied:resourceA(scope2) then the RS would not GOTO 10 because it knows there is no point is submitting that permission request again.
WDYT? James
On 25 January 2017 at 17:56, George Fletcher
wrote: Given that the RPT is somewhat equivalent to an OAuth2 access token, the OAuth2 best practice is to return the set of scopes that were met as part of the request, and also inform the client of which scopes where granted.
This becomes a little more problematic for the scopes defined by the permissions_ticket because the client doesn't know what they are. If we allow the "partial scopes" response, it will be possible for the client to successfully get an RPT that does not provide it the access it needs to a particular resource.
Take the following example:
Alice has a photo album that Bob is trying to access. Bob's client makes the request to Alice's album and the RS requests the AS to generate a permission_ticket with view,edit scopes for the resource. Bob's client presents the permission_ticket to the AS and goes through some claims negotiation. The result of the set math is that Bob's client gets 'edit' scope but not 'view'. If the AS issues the RPT with just the 'edit' scope, the it's unlikely that Bob's client will work as it really wanted 'view' access.
I'm becoming more convinced that the responsibility for the scopes necessary to issue the RPT must lie with the RS and NOT the AS. If the RS is asking for too many scopes up front, then Bob's experience will have a lot of overhead just to be able to view the photos. On the other hand, if the RS asks for just the scopes needed and the AS overrides that decision by returning less, the overall experience will break.
Hopefully that makes sense:)
Thanks, George
On Wed, Jan 25, 2017 at 12:37 PM James Phillpotts < james.phillpotts@forgerock.com> wrote:
Right, I see. Maybe an example would help?
On 25 January 2017 at 17:35, Eve Maler
wrote: Hey, I'm always up for a good disquisition ("a long or elaborate essay or discussion on a particular subject"). :-) In fact, I did try new wording in rev 13 already based on the fact that with our set math I couldn't make heads or tails of the MUST wording (note that this comes after the new agreed wording https://docs.kantarainitiative.org/uma/ed/uma-core-2.0-13.html#authorization... about the AS having a choice to respond with an RPT or a failure if the scopes satisfied are less than the scopes requested):
"Note: While a reasonable approach for most scenarios is to implement the classic security stance of default-deny ("everything that is not expressly allowed is forbidden"), corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access."
This was in order to advise anyone starting to build an AS from scratch about some of the best practices and subtleties of policy engine and access control work. Thoughts?
*Eve Maler*Cell +1 425.345.6756 <(425)%20345-6756> | Skype: xmlgrrl | Twitter: @xmlgrrl
On Wed, Jan 25, 2017 at 8:32 AM, James Phillpotts < james.phillpotts@forgerock.com> wrote:
Hi all,
Thanks for the reminder to send this email Eve! ;)
The paragraph in question is:
The authorization server MUST use a default-deny authorization assessment model in adding permissions to RPTs, that is, "everything that is not expressly allowed is forbidden" for resources for which resource servers have requested access permission on behalf of clients. Exercise caution in implementing default-deny because corner cases can inadvertently result in default-permit behavior. For example, it is insufficient simply to assume that all resources have some non-zero set of claims required for access, and then accept an empty set of supplied claims as sufficient for access.
I'm not convinced that this paragraph is really very useful, but that may be because it isn't clear at what level the 'deny' is relating to in this context - is it on a per-resource, per-scope, or an RPT level?
If per-resource, I think this is a reasonable thing to express, but I'm not sure the paragraph does a particularly good job of it.
If per-scope, does this only apply to additional scopes requested by the client?
If RPT, then I don't think the idea is correct, as the RPT shouldn't be denied based on the outcome of a particular policy for a particular resource.
-- Distinguished Engineer Identity Services Engineering, AOL Inc. Mobile:+1-703-462-3494 Office:+1-703-265-2544
participants (4)
-
Eve Maler
-
George Fletcher
-
James Phillpotts
-
Justin Richer