You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2012/11/06 12:54:52 UTC

svn commit: r1406106 - in /cxf/trunk/rt/rs/security: cors/src/main/java/org/apache/cxf/rs/security/cors/CrossOriginResourceSharingFilter.java oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java

Author: sergeyb
Date: Tue Nov  6 11:54:51 2012
New Revision: 1406106

URL: http://svn.apache.org/viewvc?rev=1406106&view=rev
Log:
[CXF-4615] Updating OAuthRequestFilter to ignore CORS preflight requests to be handled by the service code

Modified:
    cxf/trunk/rt/rs/security/cors/src/main/java/org/apache/cxf/rs/security/cors/CrossOriginResourceSharingFilter.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java

Modified: cxf/trunk/rt/rs/security/cors/src/main/java/org/apache/cxf/rs/security/cors/CrossOriginResourceSharingFilter.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/cors/src/main/java/org/apache/cxf/rs/security/cors/CrossOriginResourceSharingFilter.java?rev=1406106&r1=1406105&r2=1406106&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/cors/src/main/java/org/apache/cxf/rs/security/cors/CrossOriginResourceSharingFilter.java (original)
+++ cxf/trunk/rt/rs/security/cors/src/main/java/org/apache/cxf/rs/security/cors/CrossOriginResourceSharingFilter.java Tue Nov  6 11:54:51 2012
@@ -58,7 +58,7 @@ import org.apache.cxf.service.Service;
  * to handle @OPTIONS,
  * <em>unless</em> that method is annotated as follows:
  * <pre>
- *   @CrossOriginResourceSharing(localPreflight = true)
+ *   @LocalPreflight
  * </pre>
  * or unless the <tt>defaultOptionsMethodsHandlePreflight</tt> property of this class is set to <tt>true</tt>.
  */
@@ -66,6 +66,10 @@ public class CrossOriginResourceSharingF
     private static final Pattern SPACE_PATTERN = Pattern.compile(" ");
     private static final Pattern FIELD_COMMA_PATTERN = Pattern.compile(",\\w*");
     
+    private static final String LOCAL_PREFLIGHT = "local_preflight";
+    private static final String LOCAL_PREFLIGHT_ORIGIN = "local_preflight.origin";
+    private static final String LOCAL_PREFLIGHT_METHOD = "local_preflight.method";
+    
     private static final String PREFLIGHT_PASSED = "preflight_passed";
     private static final String PREFLIGHT_FAILED = "preflight_failed";
     private static final String SIMPLE_REQUEST = "simple_request";
@@ -159,44 +163,48 @@ public class CrossOriginResourceSharingF
     private Response preflightRequest(Message m, CrossOriginResourceSharing corsAnn,
                                       OperationResourceInfo opResInfo, ClassResourceInfo resourceClass) {
 
-        /*
-         * What to do if the resource class indeed has a method annotated with @OPTIONS 
-         * that is matched by this request? We go ahead and do this job unless the request
-         * has one of our annotations on it (or its parent class) indicating 'localPreflight' --
-         * or the defaultOptionsMethodsHandlePreflight flag is true.
-         */
-        LocalPreflight preflightAnnotation = 
-            getAnnotation(opResInfo, LocalPreflight.class);
-        if (preflightAnnotation != null || defaultOptionsMethodsHandlePreflight) { 
-            return null; // let the resource method take all responsibility.
-        }
+        // Validate main CORS preflight properties (origin, method) 
+        // even if Local preflight is requested
         
-        List<String> headerOriginValues = getHeaderValues(CorsHeaderConstants.HEADER_ORIGIN, true);
-        String origin;
         // 5.2.1 -- must have origin, must have one origin.
+        List<String> headerOriginValues = getHeaderValues(CorsHeaderConstants.HEADER_ORIGIN, true);
         if (headerOriginValues == null || headerOriginValues.size() != 1) {
             return null;
         }
-        origin = headerOriginValues.get(0);
-
-        List<String> requestMethodValues = getHeaderValues(CorsHeaderConstants.HEADER_AC_REQUEST_METHOD, false);
+        String origin = headerOriginValues.get(0);
 
         // 5.2.3 must have access-control-request-method, must be single-valued
         // we should reject parse errors but we cannot.
+        List<String> requestMethodValues = getHeaderValues(CorsHeaderConstants.HEADER_AC_REQUEST_METHOD, false);
         if (requestMethodValues == null || requestMethodValues.size() != 1) {
             return createPreflightResponse(m, false);
         }
         String requestMethod = requestMethodValues.get(0);
+        
         /*
-         * CORS doesn't send enough information with a preflight to accurately identity the single method
-         * that will handle the request. We ask the JAX-RS runtime to find the matching method which is
-         * expected to have a CrossOriginResourceSharing annotation set.
+         * Ask JAX-RS runtime to validate that the matching resource method actually exists.
          */
         
         Method method = getPreflightMethod(m, requestMethod);
         if (method == null) {
             return null;
         }
+        
+        /*
+         * What to do if the resource class indeed has a method annotated with @OPTIONS 
+         * that is matched by this request? We go ahead and do this job unless the request
+         * has one of our annotations on it (or its parent class) indicating 'localPreflight' --
+         * or the defaultOptionsMethodsHandlePreflight flag is true.
+         */
+        LocalPreflight preflightAnnotation = 
+            getAnnotation(opResInfo, LocalPreflight.class);
+        if (preflightAnnotation != null || defaultOptionsMethodsHandlePreflight) { 
+            m.put(LOCAL_PREFLIGHT, "true");
+            m.put(LOCAL_PREFLIGHT_ORIGIN, origin);
+            m.put(LOCAL_PREFLIGHT_METHOD, method);
+            return null; // let the resource method take all responsibility.
+        }
+        
         CrossOriginResourceSharing ann = method.getAnnotation(CrossOriginResourceSharing.class);
         ann = ann == null ? corsAnn : ann;
         

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java?rev=1406106&r1=1406105&r2=1406106&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java Tue Nov  6 11:54:51 2012
@@ -33,6 +33,7 @@ import org.apache.cxf.common.security.Si
 import org.apache.cxf.jaxrs.ext.RequestHandler;
 import org.apache.cxf.jaxrs.model.ClassResourceInfo;
 import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageUtils;
 import org.apache.cxf.rs.security.oauth2.common.AccessTokenValidation;
 import org.apache.cxf.rs.security.oauth2.common.OAuthContext;
 import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
@@ -51,6 +52,11 @@ public class OAuthRequestFilter extends 
     private boolean useUserSubject;
     
     public Response handleRequest(Message m, ClassResourceInfo resourceClass) {
+        
+        if (isCorsRequest(m)) {
+            return null;
+        }
+        
         // Get the access token
         AccessTokenValidation accessTokenV = getAccessTokenValidation(); 
         
@@ -149,5 +155,14 @@ public class OAuthRequestFilter extends 
         };
     }
     
+    protected boolean isCorsRequest(Message m) {
+        //Redirection-based flows (Implicit Grant Flow specifically) may have 
+        //the browser issuing CORS preflight OPTIONS request. 
+        //org.apache.cxf.rs.security.cors.CrossOriginResourceSharingFilter can be
+        //used to handle preflights but local preflights (to be handled by the service code)
+        // will be blocked by this filter unless CORS filter has done the initial validation
+        // and set a message "local_preflight" property to true
+        return MessageUtils.isTrue(m.get("local_preflight"));
+    }
     
 }