Repository: syncope
Updated Branches:
  refs/heads/master e76c59da5 -> ab4c623a3


SYNCOPE-1120 - Use the standard Bearer Authorization header for JWT tokens


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/ab4c623a
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/ab4c623a
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/ab4c623a

Branch: refs/heads/master
Commit: ab4c623a3f6ccdbe03968235b843ec81a2d97b1f
Parents: e76c59d
Author: Colm O hEigeartaigh <cohei...@apache.org>
Authored: Fri Jun 23 16:36:16 2017 +0100
Committer: Colm O hEigeartaigh <cohei...@apache.org>
Committed: Fri Jun 23 16:36:48 2017 +0100

----------------------------------------------------------------------
 .../client/console/rest/BaseRestClient.java     |  5 +++-
 .../syncope/client/lib/SyncopeClient.java       | 24 +++++++++++++-------
 .../client/lib/SyncopeClientFactoryBean.java    |  6 ++---
 .../security/JWTAuthenticationFilter.java       | 11 +++++----
 .../rest/cxf/service/SAML2SPServiceImpl.java    | 16 ++++++++++---
 .../org/apache/syncope/fit/AbstractITCase.java  |  4 +++-
 6 files changed, 46 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/ab4c623a/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
index 8b3dce2..4a780a6 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/BaseRestClient.java
@@ -19,6 +19,9 @@
 package org.apache.syncope.client.console.rest;
 
 import java.net.URI;
+
+import javax.ws.rs.core.HttpHeaders;
+
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.lib.SyncopeClient;
@@ -76,7 +79,7 @@ public abstract class BaseRestClient implements RestClient {
         
webClient.accept(SyncopeConsoleSession.get().getMediaType()).to(location.toASCIIString(),
 false);
         return webClient.
                 header(RESTHeaders.DOMAIN, 
SyncopeConsoleSession.get().getDomain()).
-                header(RESTHeaders.TOKEN, 
SyncopeConsoleSession.get().getJWT()).
+                header(HttpHeaders.AUTHORIZATION, "Bearer " + 
SyncopeConsoleSession.get().getJWT()).
                 get(resultClass);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab4c623a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
----------------------------------------------------------------------
diff --git 
a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java 
b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
index f722cf8..c13fa77 100644
--- a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
@@ -27,6 +27,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.tuple.ImmutablePair;
@@ -107,18 +108,19 @@ public class SyncopeClient {
             restClientFactory.setPassword(((BasicAuthenticationHandler) 
handler).getPassword());
 
             String jwt = 
getService(AccessTokenService.class).login().getHeaderString(RESTHeaders.TOKEN);
-            restClientFactory.getHeaders().put(RESTHeaders.TOKEN, 
Collections.singletonList(jwt));
+            restClientFactory.getHeaders().put(HttpHeaders.AUTHORIZATION, 
Collections.singletonList("Bearer " + jwt));
 
             restClientFactory.setUsername(null);
             restClientFactory.setPassword(null);
         } else if (handler instanceof JWTAuthenticationHandler) {
             restClientFactory.getHeaders().put(
-                    RESTHeaders.TOKEN, 
Collections.singletonList(((JWTAuthenticationHandler) handler).getJwt()));
+                    HttpHeaders.AUTHORIZATION,
+                    Collections.singletonList("Bearer " + 
((JWTAuthenticationHandler) handler).getJwt()));
         }
     }
 
     protected void cleanup() {
-        restClientFactory.getHeaders().remove(RESTHeaders.TOKEN);
+        restClientFactory.getHeaders().remove(HttpHeaders.AUTHORIZATION);
         restClientFactory.setUsername(null);
         restClientFactory.setPassword(null);
     }
@@ -128,7 +130,7 @@ public class SyncopeClient {
      */
     public void refresh() {
         String jwt = 
getService(AccessTokenService.class).refresh().getHeaderString(RESTHeaders.TOKEN);
-        restClientFactory.getHeaders().put(RESTHeaders.TOKEN, 
Collections.singletonList(jwt));
+        restClientFactory.getHeaders().put(HttpHeaders.AUTHORIZATION, 
Collections.singletonList("Bearer " + jwt));
     }
 
     /**
@@ -186,16 +188,22 @@ public class SyncopeClient {
     }
 
     /**
-     * Returns the JWT in used by this instance, passed with the {@link 
RESTHeaders#TOKEN} header in all requests.
-     * It can be null (in case {@link NoAuthenticationHandler} or {@link 
AnonymousAuthenticationHandler} were used).
+     * Returns the JWT in used by this instance, passed with the {@link 
HttpHeaders#AUTHORIZATION} header
+     * in all requests. It can be null (in case {@link 
NoAuthenticationHandler} or
+     * {@link AnonymousAuthenticationHandler} were used).
      *
      * @return the JWT in used by this instance
      */
     public String getJWT() {
-        List<String> headerValues = 
restClientFactory.getHeaders().get(RESTHeaders.TOKEN);
-        return headerValues == null || headerValues.isEmpty()
+        List<String> headerValues = 
restClientFactory.getHeaders().get(HttpHeaders.AUTHORIZATION);
+        String header = headerValues == null || headerValues.isEmpty()
                 ? null
                 : headerValues.get(0);
+        if (header != null && header.startsWith("Bearer ")) {
+            return header.substring("Bearer ".length());
+
+        }
+        return null;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab4c623a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
----------------------------------------------------------------------
diff --git 
a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
 
b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
index 45e6ffa..1e5924b 100644
--- 
a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
+++ 
b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
@@ -245,7 +245,7 @@ public class SyncopeClientFactoryBean {
 
     /**
      * Builds client instance with the given credentials.
-     * Such credentials will be used only to obtain a valid JWT in the {@link 
RESTHeaders#TOKEN} header;
+     * Such credentials will be used only to obtain a valid JWT in the {@link 
HttpHeaders#AUTHORIZATION} header;
      *
      * @param username username
      * @param password password
@@ -256,11 +256,11 @@ public class SyncopeClientFactoryBean {
     }
 
     /**
-     * Builds client instance which will be passing the provided value in the 
{@link RESTHeaders#TOKEN}
+     * Builds client instance which will be passing the provided value in the 
{@link HttpHeaders#AUTHORIZATION}
      * request header.
      *
      * @param jwt value received after login, in the {@link RESTHeaders#TOKEN} 
response header
-     * @return client instance which will be passing the provided value in the 
{{@link RESTHeaders#TOKEN}
+     * @return client instance which will be passing the provided value in the 
{@link HttpHeaders#AUTHORIZATION}
      * request header
      */
     public SyncopeClient create(final String jwt) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab4c623a/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationFilter.java
----------------------------------------------------------------------
diff --git 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationFilter.java
 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationFilter.java
index 05b46f0..e5b13de 100644
--- 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationFilter.java
+++ 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTAuthenticationFilter.java
@@ -23,9 +23,10 @@ import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.HttpHeaders;
+
 import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer;
 import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
-import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -39,7 +40,7 @@ import org.springframework.util.Assert;
 import org.springframework.web.filter.OncePerRequestFilter;
 
 /**
- * Processes the JSON Web Token provided as {@link RESTHeaders#TOKEN} HTTP 
header, putting the result into the
+ * Processes the JSON Web Token provided as {@link HttpHeaders#AUTHORIZATION} 
HTTP header, putting the result into the
  * {@link SecurityContextHolder}.
  */
 public class JWTAuthenticationFilter extends OncePerRequestFilter {
@@ -84,12 +85,14 @@ public class JWTAuthenticationFilter extends 
OncePerRequestFilter {
             final FilterChain chain)
             throws ServletException, IOException {
 
-        String stringToken = request.getHeader(RESTHeaders.TOKEN);
-        if (stringToken == null) {
+        String auth = request.getHeader(HttpHeaders.AUTHORIZATION);
+        String[] parts = auth == null ? null : auth.split(" ");
+        if (parts == null || parts.length != 2 || !"Bearer".equals(parts[0])) {
             chain.doFilter(request, response);
             return;
         }
 
+        String stringToken = parts[1];
         LOG.debug("JWT received: {}", stringToken);
 
         JwsJwtCompactConsumer consumer = new 
JwsJwtCompactConsumer(stringToken);

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab4c623a/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2SPServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2SPServiceImpl.java
 
b/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2SPServiceImpl.java
index 191081f..94d14f1 100644
--- 
a/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2SPServiceImpl.java
+++ 
b/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2SPServiceImpl.java
@@ -20,6 +20,8 @@ package org.apache.syncope.core.rest.cxf.service;
 
 import java.io.IOException;
 import java.io.OutputStream;
+
+import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.StreamingOutput;
@@ -27,7 +29,6 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.to.SAML2RequestTO;
 import org.apache.syncope.common.lib.to.SAML2LoginResponseTO;
 import org.apache.syncope.common.lib.to.SAML2ReceivedResponseTO;
-import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.SAML2SPService;
 import org.apache.syncope.core.logic.SAML2SPLogic;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -68,13 +69,22 @@ public class SAML2SPServiceImpl extends AbstractServiceImpl 
implements SAML2SPSe
     @Override
     public SAML2RequestTO createLogoutRequest(final String spEntityID) {
         return logic.createLogoutRequest(
-                
messageContext.getHttpHeaders().getHeaderString(RESTHeaders.TOKEN),
+                getJWTToken(),
                 StringUtils.appendIfMissing(spEntityID, "/"));
     }
 
     @Override
     public void validateLogoutResponse(final SAML2ReceivedResponseTO response) 
{
-        
logic.validateLogoutResponse(messageContext.getHttpHeaders().getHeaderString(RESTHeaders.TOKEN),
 response);
+        logic.validateLogoutResponse(getJWTToken(), response);
     }
 
+    private String getJWTToken() {
+        String auth = 
messageContext.getHttpHeaders().getHeaderString(HttpHeaders.AUTHORIZATION);
+        String[] parts = auth == null ? null : auth.split(" ");
+        if (parts == null || parts.length != 2 || !"Bearer".equals(parts[0])) {
+            return null;
+        }
+
+        return parts[1];
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/ab4c623a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
----------------------------------------------------------------------
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index ba819af..b584802 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -104,6 +104,8 @@ import org.junit.FixMethodOrder;
 import org.junit.runners.MethodSorters;
 import org.springframework.jdbc.core.JdbcTemplate;
 
+import com.google.common.net.HttpHeaders;
+
 @FixMethodOrder(MethodSorters.JVM)
 public abstract class AbstractITCase {
 
@@ -322,7 +324,7 @@ public abstract class AbstractITCase {
 
         return webClient.
                 header(RESTHeaders.DOMAIN, adminClient.getDomain()).
-                header(RESTHeaders.TOKEN, adminClient.getJWT()).
+                header(HttpHeaders.AUTHORIZATION, "Bearer " + 
adminClient.getJWT()).
                 get(resultClass);
     }
 

Reply via email to