users@jax-rs-spec.java.net

[jax-rs-spec users] Re: Getting full path template after sub-resource locators

From: Ron Dagostino <rndgstn_at_gmail.com>
Date: Tue, 19 Apr 2016 07:16:19 -0400

Hi Adam. We need to know who is authorized to what. Knowing the "what" is necessary but insufficient for our requirement.

Ron

> On Apr 19, 2016, at 3:44 AM, Adam Bien <abien_at_adam-bien.com> wrote:
>
> A list of all URIs / Templates of a WAR would be interesting for discovery purposes.
> Would this partially satisfy your request?
>
>> On 18.04.2016, at 16:34, Ron Dagostino <rndgstn_at_gmail.com> wrote:
>>
>> Unfortunate. Thank you for reviewing it.
>>
>> On Mon, Apr 18, 2016 at 10:08 AM, Marek Potociar <marek.potociar_at_oracle.com> wrote:
>> Hi Ron,
>>
>> I have reviewed this use case and I am afraid it is too narrow-scoped to justify change in the API. We have not seen any other similar requests so far to support the justification behind your use case.
>>
>> Kind regards,
>> Marek
>>
>>> On 17 Feb 2016, at 16:50, Ron Dagostino <rndgstn_at_gmail.com> wrote:
>>>
>>> Thanks for the feedback, Marek. Here is our use case.
>>>
>>> We annotate our resource methods with @RolesAllowed to identify the roles that can invoke them. The listed roles correspond to role names in our role-based access control repository (RBAC), and we make the authz decision in a post-match ContainerRequestFilter. The filter verifies an incoming signed OAuth bearer token and extracts the set of active roles in the token from a claim. The filter then decides to accept or reject the request based on whether or not there is an intersection between the active roles in the token claim and the roles listed in the @RolesAllowed annotation. This works great, but we have an audit/compliance requirement to be able to clearly identify which roles are allowed to invoke which APIs, and we are now deciding how to meet this requirement. Our thought is that the APIs can be identified at runtime by their method and full template path. For example:
>>>
>>> We would be able to identify at runtime the following two facts:
>>>
>>>
>>> FooRole is able to invoke "GET root/foo={value}"
>>> IdsRole is able to invoke "GET root/id1={id1Value}/id2={id2Value}"
>>>
>>>
>>> If we have these code definitions:
>>>
>>>
>>> @Path("root") // resource class
>>> public class Root {
>>> @Path("foo={value}") // sub-resource method
>>> @RolesAllowed("FooRole") // token/RBAC authnz
>>> public String get() {
>>> return "foo";
>>> }
>>>
>>> @Path("id1={id1Value}") // sub-resource locator
>>> public SubResource getSubResource() {
>>> return new SubResource();
>>> }
>>> }
>>>
>>> public class SubResource {
>>> @Path("id2={id2Value}")
>>> @GET // sub-resource method
>>> @RolesAllowed("IdsRole") // token/RBAC authz
>>> public String get() {
>>> return "ids";
>>> }
>>> }
>>>
>>>
>>> It makes sense to report the full template path rather than the URL because every URL is different (root/foo=1, root/foo=abc, etc.) but the full template path is the same for every matching URL (root/foo={value}).
>>>
>>> The current 2.0 API does not support (easily, without re-implementing stage 3 of the matching algorithm) identifying the full path template when sub-resource locators are involved.
>>>
>>> Using the full path template is not the only approach. We could require the use of an additional annotation to explicitly provide an API method identifier, or we could use java.lang.reflect.Method.toGenericString() to identify the API method name. So there are workarounds. But the best solution to us at this time seems to be to always report something of the form "<HTTPMETHOD> <full/{template}/path>" -- it is API-friendly because everybody thinks in terms of methods and paths, and the information is there already; we are just looking for an API to get at it.
>>>
>>> Is this something a lot of people would want to do? I don't know. There was a reason for including UriInfo.getMatchingResources() and UriInfo.getPathParameters(); I don't know what the reason was, but the use case I describe requires a more complete exposure of the kind of information that these methods already provide.
>>>
>>> Ron
>>>
>>>
>>>
>>> On Wed, Feb 17, 2016 at 10:01 AM, Marek Potociar <marek.potociar_at_oracle.com> wrote:
>>> Hi Ron,
>>>
>>> I think you really need to first make case why is it important to expose API for constructing a full path template. We need to understand how many people would benefit from such API, before we can consider adding it to the spec.
>>>
>>> Cheers,
>>> Marek
>>>
>>>> On 17 Feb 2016, at 03:01, Ron Dagostino <rndgstn_at_gmail.com> wrote:
>>>>
>>>> Hi again. I have concluded that it is not possible to construct the full path template for a request without (re-)implementing a significant portion of the matching algorithm (specifically, stage 3). The problem is that UriInfo does not provide a complete picture of what happened during the matching process -- it does not specify which methods were matched on instances generated by sub-resource locators. It provides the instances, but it does not provide the matched methods.
>>>>
>>>> Assuming it is agreed to be reasonable to want to know the full path template for a request (I can explain why I want to do this if necessary), and assuming I am not missing anything and it is indeed not (easily) possible with the 2.0 API, and simple solution would be to add a method to UriInfo that returns the matched methods as shown in the sample Javadoc below. A more complete solution would be to expose the entire match model: a list with each element being an object that contained a resource method, a path parameters map (empty if no template substitutions were made), and the matched resource.
>>>>
>>>> I am hoping for some feedback on this.
>>>>
>>>> Ron
>>>>
>>>> java.lang.List<java.lang.reflect.Method> getMatchedMethods()
>>>> Get a read-only list of the currently matched resource methods. Each entry is a resource method that matched the request URI either directly or via a sub-resource method or a sub-resource locator. Entries are ordered according to reverse request URI matching order, with the current resource method first. E.g. given the following resource classes:
>>>> @Path("foo")
>>>> public class FooResource {
>>>> @GET
>>>> public String getFoo() {...}
>>>>
>>>> @Path("bar")
>>>> public BarResource getBarResource() {...}
>>>> }
>>>>
>>>> public class BarResource {
>>>> @GET
>>>> public String getBar() {...}
>>>> }
>>>>
>>>>
>>>> The values returned by this method based on request uri and where the method is called from are:
>>>>
>>>> Request Called from Value(s)
>>>> GET /foo FooResource.getFoo FooResource.getFoo
>>>> GET /foo/bar FooResource.getBarResource FooResource.getBarResource
>>>> GET /foo/bar BarResource.getBar BarResource.getBar, FooResource.getBarResource
>>>>
>>>> Request Called from Value(s)
>>>> GET /foo RequestContextFilter (pre-match) null
>>>> GET /foo
>>>> RequestContextFilter (post-match)
>>>> FooResource.getFoo
>>>> GET /foo/bar
>>>> RequestContextFilter (post-match)
>>>> BarResource.getBar, FooResource.getBarResource
>>>>
>>>> Returns:
>>>> a read-only list of matched resource methods.
>>>>
>>>>
>>>>
>>>> On Mon, Feb 15, 2016 at 9:55 PM, Ron Dagostino <rndgstn_at_gmail.com> wrote:
>>>> Hi everyone. I want to write a ContainerRequestFilter that can generate the full path template value "root/id1={id1Value}/id2={id2Value}" for the following case and also generate correct full path template values in the general case. I don't think it can be reliably done when sub-resource locators are involved. For example, given these classes:
>>>>
>>>>
>>>> @Path("root") // resource class
>>>> public class Root {
>>>> @Path("id1={id1Value}") // sub-resource locator
>>>> public SubResource getSubResource() {
>>>> return new SubResource();
>>>> }
>>>> }
>>>>
>>>> public class SubResource {
>>>> @Path("id2={id2Value}")
>>>> @GET // sub-resource method
>>>> public String get() {
>>>> return "the entity";
>>>> }
>>>> }
>>>>
>>>> And given this request:
>>>>
>>>> /root/id1=2/id2=2
>>>>
>>>>
>>>> The problem is that uriInfo.getPathParameters() returns this MultiValuedMap in the filter:
>>>>
>>>> {id2Value=[2], id1Value=[2]}
>>>>
>>>> There is no way I can reliably get from "/root/id1=2/id2=2" to "root/id1={id1Value}/id2={id2Value}" given the MultiValuesMap contents.
>>>>
>>>> Basically I think there is no way to reliably know what the full path template value is for a request when sub-resource locators are involved. Is this true?
>>>>
>>>> Ron
>