You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cxf.apache.org by Benson Margulies <bi...@gmail.com> on 2011/12/01 15:51:26 UTC

[proposal] Cross-Origin JAX-RS annotations

I propose to add the following

@CorsAllowAllOrigins
@CorsAllowOrigins(  "origin1.", ... "originN" )
@CorsAllowMethods( "meth1" ... "methn" )
@CorsExposeMethods( ... )
@CorsMaxAge(integer)
@CorsAllowCredentials(boolean)

and make the filter look for them on resources and classes in the usual way.

Any objections?

Re: [proposal] Cross-Origin JAX-RS annotations

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Benson

On 02/12/11 22:16, Benson Margulies wrote:
> On Fri, Dec 2, 2011 at 4:45 PM, Sergey Beryozkin<sb...@gmail.com>  wrote:
>> Hi Benson
>>
>> I think we should get rid of that Class level annotation that you
>> introduced. It is not secure enough - the path and verb values it lists -
>> they can not serve as a guarantee that the actual resource handler exists.
>> They simply duplicate @Path&  @GET/friends.
>> I propose to get rid of it.
>> As I said, JAXRSUtils.getResourceClass&  JAXRSUtils.findOperation are the
>> only guarantee and we should not be concerned if we have multiple GET
>> handlers listening on the same path but differing in @Produces.
>
>
> Sergey,
>
> I don't yet agree(, but you'll probably convince me eventually). The
> whole thrust of my discussion with the CORS people is that CORS isn't
> exactly security. A service cannot delegate security to the browser.
> The browser could be hacked.
>
> The effect of CORS is to instruct the browser to open up a range of
> resources, but it's still up to the actual handlers for those
> resources in the server to implement security.
>
@CrossScriptResourceSharing can be used to enforce the security on the 
server side; the class-level annotation may give us the illusion of 
security at the CORS level but it won't guarantee that JAXRS runtime 
will actually find such a matching resource.

> The only vocabulary for instructing the browser is URI+method, and the
> annotation does that.
>
> That being said, could I interest you in starting by producing an
> alternative version of the package.html that would explain to a user
> how to use your preferred alternative?
>
I'll try but a bit later on once I get to grips with CORS :-)

> If I could read a user-facing document that explained what a user
> should do, I'd stop carping.
>
> Meanwhile, I had a thought that may just be identical to yours, but
> I'm feeling really slow.
>
> Let's say that we eliminate the nested annotation business. Also note
> that this mess only applies to preflight, so as an example I'll talk
> about PUT.
>
> Now, what exactly happens if we have multiple @PUT handlers for the
> same URI that dispatch on the incoming Content-Type, or on the
> presence of particular multipart pieces, which are the losing cases?
>
> We could say: Only one of them may have a @CrossScriptResourceSharing
> annotation. If more than one have it, we throw. Or we log and decline
> fail the CORS transaction.
>
> How's about that?
>
Exactly, +1. We don't need to worry right now about such fine-grained 
cases where we have multiple PUT handlers which only differ from each 
other by accepted or produced media types, if CORS will eventually get 
other headers introduced to do with the major headers such as 
Content-Type or Accept then we will deal with such cases better.

So the method selected by the runtime must contain the annotation
@CrossScriptResourceSharing.

I think we should configure the CORS filter with preferred Content-Type 
& Accept header values which if set will be used during the try 
selection initiated by the CORS filter, otherwise we can just default to 
*/*; it will only be needed when the developer know that say multiple 
PUT handlers exist;

So JAXRSUtils.findResourceClass followed by JAXRSUtils.findTargetMethod 
in combination with @CrossScriptResourceSharing is all we need;

Cheers, Sergey

Re: [proposal] Cross-Origin JAX-RS annotations

Posted by Benson Margulies <bi...@gmail.com>.
On Fri, Dec 2, 2011 at 4:45 PM, Sergey Beryozkin <sb...@gmail.com> wrote:
> Hi Benson
>
> I think we should get rid of that Class level annotation that you
> introduced. It is not secure enough - the path and verb values it lists -
> they can not serve as a guarantee that the actual resource handler exists.
> They simply duplicate @Path & @GET/friends.
> I propose to get rid of it.
> As I said, JAXRSUtils.getResourceClass & JAXRSUtils.findOperation are the
> only guarantee and we should not be concerned if we have multiple GET
> handlers listening on the same path but differing in @Produces.


Sergey,

I don't yet agree(, but you'll probably convince me eventually). The
whole thrust of my discussion with the CORS people is that CORS isn't
exactly security. A service cannot delegate security to the browser.
The browser could be hacked.

The effect of CORS is to instruct the browser to open up a range of
resources, but it's still up to the actual handlers for those
resources in the server to implement security.

The only vocabulary for instructing the browser is URI+method, and the
annotation does that.

That being said, could I interest you in starting by producing an
alternative version of the package.html that would explain to a user
how to use your preferred alternative?

If I could read a user-facing document that explained what a user
should do, I'd stop carping.

Meanwhile, I had a thought that may just be identical to yours, but
I'm feeling really slow.

Let's say that we eliminate the nested annotation business. Also note
that this mess only applies to preflight, so as an example I'll talk
about PUT.

Now, what exactly happens if we have multiple @PUT handlers for the
same URI that dispatch on the incoming Content-Type, or on the
presence of particular multipart pieces, which are the losing cases?

We could say: Only one of them may have a @CrossScriptResourceSharing
annotation. If more than one have it, we throw. Or we log and decline
fail the CORS transaction.

How's about that?




>
> Agreed ? We just have one more annotation at the moment which is not secure
> enough, i.e, it;s not taken into account by the selection algorithm and thus
> it may go out of sync with the actual resource handlers, etc
>
> Sergey
>
> On 02/12/11 16:31, Benson Margulies wrote:
>>
>> the spec requires us to ignore the whole thing if it isn't a
>> space-separated list.
>>
>> On Dec 2, 2011, at 10:19 AM, Sergey Beryozkin<sb...@gmail.com>
>>  wrote:
>>
>>> On 02/12/11 14:13, Benson Margulies wrote:
>>>>
>>>> On Fri, Dec 2, 2011 at 9:09 AM, Sergey Beryozkin<sb...@gmail.com>
>>>> wrote:
>>>>>
>>>>> On 02/12/11 13:40, Benson Margulies wrote:
>>>>>>
>>>>>>
>>>>>> For the record, please see:
>>>>>>
>>>>>>
>>>>>> http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/1307.html
>>>>>>
>>>>>> Sergey, would it make any sense to add an injection annotation to
>>>>>> deliver the Origin header more conveniently (parsed on spaces into a
>>>>>> list) or do you think that anyone who wants to make access control
>>>>>> decision should just use header injection?
>>>>>>
>>>>>> I've just checked in about 80% of all this.
>>>>>
>>>>>
>>>>>
>>>>> List<String>   values = HttpHeaders.getRequestHeader("Origin")
>>>>> should return the list of individual values, but I think it expects a
>>>>> ',' as
>>>>> a default separator;
>>>>> How about introducing a
>>>>> "org.apache.cxf.http.header.separator" property (def is ',') and update
>>>>> HttpHeadersImpl to use that property ?
>>>>
>>>>
>>>> The problem is that the Origin header is space-separated and the
>>>> others are comma-separated. So a property seems pretty scary to me.
>>>> Should the class just know that Origin is defined by W3C to be
>>>> space-separated?
>>>>
>>> Sounds good to me; I guess that even though it's space separated sosme
>>> clients will still use ',' - but we can handle that later; would you like me
>>> to fix that ?
>>> Sergey
>
>
>
> --
> Sergey Beryozkin
>
> Talend Community Coders
> http://coders.talend.com/
>
> Blog: http://sberyozkin.blogspot.com

Re: [proposal] Cross-Origin JAX-RS annotations

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Benson

On 01/12/11 18:36, Benson Margulies wrote:
> Sergey,
>
> I've hit a snag with preflight. In preflight, the client sends an
> OPTIONS with a 'requestMethod' and we have to decide if we like that
> method. This is section 6.1.5.
>
> The client sends OPTIONS with the method, a list of custom headers,
> and of course the full URL.
>
> I need to map that to the method that would be selected for the actual
> request to look at the annotations.
>
> That is, given a method as a string and a URL, I need to obtain the
> 'annotated method' that would be invoked. Not everything we'd usually
> use to select a method will be there. In particular, if the Consumes
> is 'interesting', the relevant content-type won't be there. Here's the
> list of request headers that will come with the OPTIONS header.
>

You can use JAXRSUtils.selectResourceClass & 
JAXRSUtils.findTargetMethod, create an empty Message

> Accept, Accept-Language, Content-Language, or Last-Event-ID, or if it
> is an ASCII case-insensitive match for Content-Type and the header
> field value media type (excluding parameters) is an ASCII
> case-insensitive match for application/x-www-form-urlencoded,
> multipart/form-data, or text/plain.
>
HttpHeaders should help there, lookups are case-insensitive

Does it help a bit ?

Cheers, Sergey

> The coward's way out of this is to use only class-level annotations
> for preflight, and document that we're doing so. Can you think of any
> better alternative?


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: [proposal] Cross-Origin JAX-RS annotations

Posted by Benson Margulies <bi...@gmail.com>.
I forgot to ask, can you help me figure out which class is the right
class for the information I've got?

Re: [proposal] Cross-Origin JAX-RS annotations

Posted by Benson Margulies <bi...@gmail.com>.
Sergey,

I've hit a snag with preflight. In preflight, the client sends an
OPTIONS with a 'requestMethod' and we have to decide if we like that
method. This is section 6.1.5.

The client sends OPTIONS with the method, a list of custom headers,
and of course the full URL.

I need to map that to the method that would be selected for the actual
request to look at the annotations.

That is, given a method as a string and a URL, I need to obtain the
'annotated method' that would be invoked. Not everything we'd usually
use to select a method will be there. In particular, if the Consumes
is 'interesting', the relevant content-type won't be there. Here's the
list of request headers that will come with the OPTIONS header.

Accept, Accept-Language, Content-Language, or Last-Event-ID, or if it
is an ASCII case-insensitive match for Content-Type and the header
field value media type (excluding parameters) is an ASCII
case-insensitive match for application/x-www-form-urlencoded,
multipart/form-data, or text/plain.

The coward's way out of this is to use only class-level annotations
for preflight, and document that we're doing so. Can you think of any
better alternative?

Re: [proposal] Cross-Origin JAX-RS annotations

Posted by Sergey Beryozkin <sb...@gmail.com>.
On 01/12/11 15:51, Benson Margulies wrote:
> On Thu, Dec 1, 2011 at 10:34 AM, Sergey Beryozkin<sb...@gmail.com>  wrote:
>> On 01/12/11 14:51, Benson Margulies wrote:
>>>
>>> I propose to add the following
>>>
>>> @CorsAllowAllOrigins
>>> @CorsAllowOrigins(  "origin1.", ... "originN" )
>>> @CorsAllowMethods( "meth1" ... "methn" )
>>> @CorsExposeMethods( ... )
>>> @CorsMaxAge(integer)
>>> @CorsAllowCredentials(boolean)
>>>
>>> and make the filter look for them on resources and classes in the usual
>>> way.
>>>
>>> Any objections?
>>
>>
>> Can we collapse it all into a single annotation but with many properties ?
>> @Cors(origins = "...",
>>       methods = "a b c"
>>       allowCredentials = true
>>       )
>>
>> I'd prefer if possible to avoid the explosion of annotations.
>
> I hate space-separated. Can they be String[], or am I stuck with those spaces?
>

Yes, they can

>>
>> Re @CorsAllowMethods( "meth1" ... "methn" ) (or methods = "a b") - is it
>> HTTP methods ?
>
> yes.
>
>> Then how it work on a method annotated with say @POST ? May be it should be
>> a single method value only ?
>
> So we don't need this annotation. If any of the others are there, it
> would imply permission for the method.
>
OK
>> Re CorsAllowOrigins, is it relative URIs ? We'd probably need to think of
>> introducing properties such as absolute.uri, etc, to be reused by other
>> annotation such as SchemaLocation&  XMLInstruction
>
> Origin must be an absolute URI. In fact, it's a list of them due to redirects.
>
> You never need to list 'right here', right here is always allowed.
> It's only necessary to list other places, so I don't see the need for
> anything tricky.
>
Ok, I guess this is an optional property here. But if we have a redirect 
allowed to other endpoint hosted inside the same web app then we may 
have to deal with the substitution - I'll take care of it as I will need 
to do something about it in context of the other work too

Thanks, Sergey

>>
>> Thanks, Sergey


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: [proposal] Cross-Origin JAX-RS annotations

Posted by Benson Margulies <bi...@gmail.com>.
On Thu, Dec 1, 2011 at 10:34 AM, Sergey Beryozkin <sb...@gmail.com> wrote:
> On 01/12/11 14:51, Benson Margulies wrote:
>>
>> I propose to add the following
>>
>> @CorsAllowAllOrigins
>> @CorsAllowOrigins(  "origin1.", ... "originN" )
>> @CorsAllowMethods( "meth1" ... "methn" )
>> @CorsExposeMethods( ... )
>> @CorsMaxAge(integer)
>> @CorsAllowCredentials(boolean)
>>
>> and make the filter look for them on resources and classes in the usual
>> way.
>>
>> Any objections?
>
>
> Can we collapse it all into a single annotation but with many properties ?
> @Cors(origins = "...",
>      methods = "a b c"
>      allowCredentials = true
>      )
>
> I'd prefer if possible to avoid the explosion of annotations.

I hate space-separated. Can they be String[], or am I stuck with those spaces?

>
> Re @CorsAllowMethods( "meth1" ... "methn" ) (or methods = "a b") - is it
> HTTP methods ?

yes.

> Then how it work on a method annotated with say @POST ? May be it should be
> a single method value only ?

So we don't need this annotation. If any of the others are there, it
would imply permission for the method.

> Re CorsAllowOrigins, is it relative URIs ? We'd probably need to think of
> introducing properties such as absolute.uri, etc, to be reused by other
> annotation such as SchemaLocation & XMLInstruction

Origin must be an absolute URI. In fact, it's a list of them due to redirects.

You never need to list 'right here', right here is always allowed.
It's only necessary to list other places, so I don't see the need for
anything tricky.

>
> Thanks, Sergey

Re: [proposal] Cross-Origin JAX-RS annotations

Posted by Sergey Beryozkin <sb...@gmail.com>.
On 01/12/11 14:51, Benson Margulies wrote:
> I propose to add the following
>
> @CorsAllowAllOrigins
> @CorsAllowOrigins(  "origin1.", ... "originN" )
> @CorsAllowMethods( "meth1" ... "methn" )
> @CorsExposeMethods( ... )
> @CorsMaxAge(integer)
> @CorsAllowCredentials(boolean)
>
> and make the filter look for them on resources and classes in the usual way.
>
> Any objections?

Can we collapse it all into a single annotation but with many properties ?
@Cors(origins = "...",
       methods = "a b c"
       allowCredentials = true
       )

I'd prefer if possible to avoid the explosion of annotations.

Re @CorsAllowMethods( "meth1" ... "methn" ) (or methods = "a b") - is it 
HTTP methods ?
Then how it work on a method annotated with say @POST ? May be it should 
be a single method value only ?
Re CorsAllowOrigins, is it relative URIs ? We'd probably need to think 
of introducing properties such as absolute.uri, etc, to be reused by 
other annotation such as SchemaLocation & XMLInstruction

Thanks, Sergey