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 2014/12/10 18:04:48 UTC
cxf git commit: Adding JWT token related utility code
Repository: cxf
Updated Branches:
refs/heads/master 4fb4de764 -> 2ef6f5840
Adding JWT token related utility code
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/2ef6f584
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/2ef6f584
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/2ef6f584
Branch: refs/heads/master
Commit: 2ef6f584022b7672df00a883525dc58807ffe7d7
Parents: 4fb4de7
Author: Sergey Beryozkin <sb...@talend.com>
Authored: Wed Dec 10 17:04:30 2014 +0000
Committer: Sergey Beryozkin <sb...@talend.com>
Committed: Wed Dec 10 17:04:30 2014 +0000
----------------------------------------------------------------------
.../cxf/rs/security/jose/JoseConstants.java | 2 +
.../apache/cxf/rs/security/jose/JoseUtils.java | 31 ++++++++
.../jose/jaxrs/AbstractJwsWriterProvider.java | 11 ++-
.../jose/jaxrs/JwsContainerRequestFilter.java | 18 +----
.../jaxrs/JwtAuthenticationClientFilter.java | 75 ++++++++++++++++++++
.../jose/jaxrs/JwtAuthenticationFilter.java | 70 ++++++++++++++++++
.../cxf/rs/security/jose/jaxrs/Priorities.java | 15 ++--
.../jose/jws/NoneJwsSignatureProvider.java | 55 ++++++++++++++
.../jose/jwt/AbstractJoseJwtConsumer.java | 73 +++++++++++++++++++
.../jose/jwt/AbstractJoseJwtProducer.java | 58 +++++++++++++++
.../jwt/AbstactJwtAccessTokenValidator.java | 63 ++++++++++++++++
.../oauth2/tokens/jwt/JwtAccessTokenUtils.java | 38 +---------
.../oidc/rp/AbstractTokenValidator.java | 64 +++++++++--------
13 files changed, 478 insertions(+), 95 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseConstants.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseConstants.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseConstants.java
index 6d95234..b268129 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseConstants.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseConstants.java
@@ -76,6 +76,8 @@ public final class JoseConstants {
public static final String A192GCM_ALGO = "A192GCM";
public static final String A256GCM_ALGO = "A256GCM";
+ public static final String JOSE_CONTEXT_PROPERTY = "org.apache.cxf.jose.context";
+
private JoseConstants() {
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseUtils.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseUtils.java
index 23f9936..122c3eb 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseUtils.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/JoseUtils.java
@@ -24,12 +24,43 @@ import java.util.List;
import java.util.Set;
import org.apache.cxf.common.util.crypto.CryptoUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
public final class JoseUtils {
+
private JoseUtils() {
}
+ public static void setJoseContextProperty(JoseHeaders headers) {
+ String context = (String)JAXRSUtils.getCurrentMessage().get(JoseConstants.JOSE_CONTEXT_PROPERTY);
+ if (context != null) {
+ headers.setHeader(JoseConstants.JOSE_CONTEXT_PROPERTY, context);
+ }
+ }
+ public static void setJoseMessageContextProperty(JoseHeaders headers, String value) {
+ headers.setHeader(JoseConstants.JOSE_CONTEXT_PROPERTY, value);
+ JAXRSUtils.getCurrentMessage().put(JoseConstants.JOSE_CONTEXT_PROPERTY, value);
+ }
+ public static void setMessageContextProperty(JoseHeaders headers) {
+ String context = (String)headers.getHeader(JoseConstants.JOSE_CONTEXT_PROPERTY);
+ if (context != null) {
+ JAXRSUtils.getCurrentMessage().put(JoseConstants.JOSE_CONTEXT_PROPERTY, context);
+ }
+ }
+ public static void validateRequestContextProperty(JoseHeaders headers) {
+ Object requestContext = JAXRSUtils.getCurrentMessage().get(JoseConstants.JOSE_CONTEXT_PROPERTY);
+ Object headerContext = headers.getHeader(JoseConstants.JOSE_CONTEXT_PROPERTY);
+ if (requestContext == null && headerContext == null) {
+ return;
+ }
+ if (requestContext == null && headerContext != null
+ || requestContext != null && headerContext == null
+ || !requestContext.equals(headerContext)) {
+ throw new SecurityException();
+ }
+ }
+
public static String checkContentType(String contentType, String defaultType) {
if (contentType != null) {
int paramIndex = contentType.indexOf(';');
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java
index d281b2e..1fc5bdc 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwsWriterProvider.java
@@ -24,14 +24,13 @@ import java.io.OutputStream;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.helpers.IOUtils;
-import org.apache.cxf.message.Message;
import org.apache.cxf.rs.security.jose.JoseHeaders;
+import org.apache.cxf.rs.security.jose.JoseUtils;
import org.apache.cxf.rs.security.jose.jws.JwsCompactProducer;
import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
import org.apache.cxf.rs.security.jose.jws.JwsUtils;
public class AbstractJwsWriterProvider {
- private static final String JWS_CONTEXT_PROPERTY = "org.apache.cxf.jws.context";
private JwsSignatureProvider sigProvider;
public void setSignatureProvider(JwsSignatureProvider signatureProvider) {
@@ -39,6 +38,7 @@ public class AbstractJwsWriterProvider {
}
protected JwsSignatureProvider getInitializedSigProvider(JoseHeaders headers) {
+ setRequestContextProperty(headers);
if (sigProvider != null) {
return sigProvider;
}
@@ -46,11 +46,8 @@ public class AbstractJwsWriterProvider {
headers.setAlgorithm(theSigProvider.getAlgorithm());
return theSigProvider;
}
- protected void setRequestContextProperty(Message m, JoseHeaders headers) {
- String context = (String)m.getContextualProperty(JWS_CONTEXT_PROPERTY);
- if (context != null) {
- headers.setHeader(JWS_CONTEXT_PROPERTY, context);
- }
+ protected void setRequestContextProperty(JoseHeaders headers) {
+ JoseUtils.setJoseContextProperty(headers);
}
protected void writeJws(JwsCompactProducer p, JwsSignatureProvider theSigProvider, OutputStream os)
throws IOException {
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java
index 1b5f5d2..6164b8f 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwsContainerRequestFilter.java
@@ -36,7 +36,6 @@ import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
@PreMatching
@Priority(Priorities.JWS_SERVER_READ_PRIORITY)
public class JwsContainerRequestFilter extends AbstractJwsReaderProvider implements ContainerRequestFilter {
- private static final String JWS_CONTEXT_PROPERTY = "org.apache.cxf.jws.context";
@Override
public void filter(ContainerRequestContext context) throws IOException {
if (HttpMethod.GET.equals(context.getMethod())) {
@@ -48,7 +47,7 @@ public class JwsContainerRequestFilter extends AbstractJwsReaderProvider impleme
context.abortWith(JAXRSUtils.toResponse(400));
return;
}
- validateRequestContextProperty(p);
+ JoseUtils.validateRequestContextProperty(p.getJoseHeaders());
byte[] bytes = p.getDecodedJwsPayloadBytes();
context.setEntityStream(new ByteArrayInputStream(bytes));
context.getHeaders().putSingle("Content-Length", Integer.toString(bytes.length));
@@ -58,18 +57,5 @@ public class JwsContainerRequestFilter extends AbstractJwsReaderProvider impleme
context.getHeaders().putSingle("Content-Type", ct);
}
}
- protected void validateRequestContextProperty(JwsCompactConsumer c) {
- Object requestContext = JAXRSUtils.getCurrentMessage().get(JWS_CONTEXT_PROPERTY);
- Object headerContext = c.getJoseHeaders().getHeader(JWS_CONTEXT_PROPERTY);
- if (requestContext == null && headerContext == null) {
- return;
- }
- if (requestContext == null && headerContext != null
- || requestContext != null && headerContext == null
- || !requestContext.equals(headerContext)) {
- throw new SecurityException();
- }
-
-
- }
+
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtAuthenticationClientFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtAuthenticationClientFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtAuthenticationClientFilter.java
new file mode 100644
index 0000000..d8bd8c2
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtAuthenticationClientFilter.java
@@ -0,0 +1,75 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jaxrs;
+
+import java.io.IOException;
+
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.core.HttpHeaders;
+
+import org.apache.cxf.common.util.Base64UrlUtility;
+import org.apache.cxf.common.util.crypto.CryptoUtils;
+import org.apache.cxf.configuration.security.AuthorizationPolicy;
+import org.apache.cxf.endpoint.Endpoint;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.rs.security.jose.JoseHeaders;
+import org.apache.cxf.rs.security.jose.JoseUtils;
+import org.apache.cxf.rs.security.jose.jwt.AbstractJoseJwtProducer;
+import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
+
+@Priority(Priorities.AUTHENTICATION)
+public class JwtAuthenticationClientFilter extends AbstractJoseJwtProducer
+ implements ClientRequestFilter {
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ JwtToken jwt = getJwtToken(requestContext);
+ boolean jweRequired = false;
+ if (jwt == null) {
+ AuthorizationPolicy ap = JAXRSUtils.getCurrentMessage().getExchange()
+ .get(Endpoint.class).getEndpointInfo().getExtensor(AuthorizationPolicy.class);
+ if (ap != null && ap.getUserName() != null) {
+ JwtClaims claims = new JwtClaims();
+ claims.setSubject(ap.getUserName());
+ claims.setClaim("password", ap.getPassword());
+ claims.setIssuedAt(System.currentTimeMillis() / 1000);
+ jwt = new JwtToken(new JoseHeaders(), claims);
+ jweRequired = true;
+ }
+ }
+ if (jwt == null) {
+ throw new SecurityException();
+ }
+ JoseUtils.setJoseMessageContextProperty(jwt.getHeaders(),
+ getContextPropertyValue());
+ String data = super.processJwt(jwt, true, jweRequired);
+ requestContext.getHeaders().putSingle(HttpHeaders.AUTHORIZATION,
+ "JWT " + data);
+ }
+ protected JwtToken getJwtToken(ClientRequestContext requestContext) {
+ return (JwtToken)requestContext.getProperty("jwt.token");
+ }
+ protected String getContextPropertyValue() {
+ return Base64UrlUtility.encode(CryptoUtils.generateSecureRandomBytes(16));
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtAuthenticationFilter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtAuthenticationFilter.java
new file mode 100644
index 0000000..32de426
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/JwtAuthenticationFilter.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jaxrs;
+
+import java.io.IOException;
+
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.core.HttpHeaders;
+
+import org.apache.cxf.common.security.SimplePrincipal;
+import org.apache.cxf.common.security.SimpleSecurityContext;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.rs.security.jose.JoseUtils;
+import org.apache.cxf.rs.security.jose.jwt.AbstractJoseJwtConsumer;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
+import org.apache.cxf.security.SecurityContext;
+
+@PreMatching
+@Priority(Priorities.AUTHENTICATION)
+public class JwtAuthenticationFilter extends AbstractJoseJwtConsumer implements ContainerRequestFilter {
+
+ private boolean jweOnly;
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws IOException {
+ String auth = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
+ String[] parts = auth == null ? null : auth.split(" ");
+ if (parts == null || !"JWT".equals(parts[0]) || parts.length != 2) {
+ throw new SecurityException();
+ }
+ JwtToken jwt = super.getJwtToken(parts[1], jweOnly);
+ JoseUtils.setMessageContextProperty(jwt.getHeaders());
+ JAXRSUtils.getCurrentMessage().put(SecurityContext.class,
+ new SimpleSecurityContext(new JwtPrincipal(jwt)));
+ }
+
+ public void setJweOnly(boolean jweOnly) {
+ this.jweOnly = jweOnly;
+ }
+ public static class JwtPrincipal extends SimplePrincipal {
+ private JwtToken jwt;
+ public JwtPrincipal(JwtToken jwt) {
+ super(jwt.getClaims().getSubject());
+ this.jwt = jwt;
+ }
+ public JwtToken getJwt() {
+ return jwt;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/Priorities.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/Priorities.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/Priorities.java
index fc48ebc..877ff0c 100644
--- a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/Priorities.java
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/Priorities.java
@@ -19,12 +19,15 @@
package org.apache.cxf.rs.security.jose.jaxrs;
public final class Priorities {
- public static final int JWE_SERVER_READ_PRIORITY = 1000;
- public static final int JWE_WRITE_PRIORITY = 1000;
- public static final int JWE_CLIENT_READ_PRIORITY = 1001;
- public static final int JWS_SERVER_READ_PRIORITY = 1001;
- public static final int JWS_WRITE_PRIORITY = 1001;
- public static final int JWS_CLIENT_READ_PRIORITY = 1000;
+ public static final int JWE_SERVER_READ_PRIORITY = 1001;
+ public static final int JWS_SERVER_READ_PRIORITY = 1002;
+
+ public static final int JWE_WRITE_PRIORITY = 1001;
+ public static final int JWS_WRITE_PRIORITY = 1002;
+
+ public static final int JWE_CLIENT_READ_PRIORITY = 1002;
+ public static final int JWS_CLIENT_READ_PRIORITY = 1001;
+
private Priorities() {
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureProvider.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureProvider.java
new file mode 100644
index 0000000..6226102
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureProvider.java
@@ -0,0 +1,55 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jws;
+
+import org.apache.cxf.rs.security.jose.JoseHeaders;
+
+public class NoneJwsSignatureProvider implements JwsSignatureProvider {
+
+ @Override
+ public String getAlgorithm() {
+ return "none";
+ }
+
+ @Override
+ public JwsSignature createJwsSignature(JoseHeaders headers) {
+ return new NoneJwsSignature();
+ }
+
+ @Override
+ public byte[] sign(JoseHeaders headers, byte[] content) {
+ JwsSignature sig = createJwsSignature(headers);
+ sig.update(content, 0, content.length);
+ return sig.sign();
+ }
+ private static class NoneJwsSignature implements JwsSignature {
+
+ @Override
+ public void update(byte[] src, int off, int len) {
+ // complete
+ }
+
+ @Override
+ public byte[] sign() {
+ return new byte[]{};
+ }
+
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtConsumer.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtConsumer.java
new file mode 100644
index 0000000..34dd60c
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtConsumer.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwt;
+
+import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider;
+import org.apache.cxf.rs.security.jose.jwe.JweJwtCompactConsumer;
+import org.apache.cxf.rs.security.jose.jwe.JweUtils;
+import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
+import org.apache.cxf.rs.security.jose.jws.JwsUtils;
+
+public abstract class AbstractJoseJwtConsumer {
+ private JweDecryptionProvider jweDecryptor;
+ private JwsSignatureVerifier jwsVerifier;
+ protected JwtToken getJwtToken(String wrappedJwtToken, boolean jweOnly) {
+ JweDecryptionProvider theJweDecryptor = getInitializedDecryptionProvider(jweOnly);
+ if (theJweDecryptor != null) {
+ if (jweOnly) {
+ return new JweJwtCompactConsumer(wrappedJwtToken).decryptWith(jweDecryptor);
+ }
+ wrappedJwtToken = jweDecryptor.decrypt(wrappedJwtToken).getContentText();
+ } else if (jweOnly) {
+ throw new SecurityException();
+ }
+
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(wrappedJwtToken);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier();
+ return validateToken(jwtConsumer, jwt, theSigVerifier);
+ }
+ protected JwtToken validateToken(JwsJwtCompactConsumer consumer, JwtToken jwt, JwsSignatureVerifier jws) {
+ if (!consumer.verifySignatureWith(jws)) {
+ throw new SecurityException("Invalid Signature");
+ }
+ return jwt;
+ }
+ public void setJweDecryptor(JweDecryptionProvider jweDecryptor) {
+ this.jweDecryptor = jweDecryptor;
+ }
+
+ public void setJweVerifier(JwsSignatureVerifier theJwsVerifier) {
+ this.jwsVerifier = theJwsVerifier;
+ }
+
+ protected JweDecryptionProvider getInitializedDecryptionProvider(boolean jweOnly) {
+ if (jweDecryptor != null) {
+ return jweDecryptor;
+ }
+ return JweUtils.loadDecryptionProvider(jweOnly);
+ }
+ protected JwsSignatureVerifier getInitializedSigVerifier() {
+ if (jwsVerifier != null) {
+ return jwsVerifier;
+ }
+ return JwsUtils.loadSignatureVerifier(true);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtProducer.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtProducer.java
new file mode 100644
index 0000000..80318fb
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/AbstractJoseJwtProducer.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.jose.jwt;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider;
+import org.apache.cxf.rs.security.jose.jwe.JweUtils;
+import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactProducer;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
+import org.apache.cxf.rs.security.jose.jws.JwsUtils;
+import org.apache.cxf.rs.security.jose.jws.NoneJwsSignatureProvider;
+
+public abstract class AbstractJoseJwtProducer {
+ private JwsSignatureProvider sigProvider;
+ private JweEncryptionProvider encryptionProvider;
+ protected String processJwt(JwtToken jwt, boolean jwsRequired, boolean jweRequired) {
+ JwsJwtCompactProducer jws = new JwsJwtCompactProducer(jwt);
+ JwsSignatureProvider theSigProvider = getInitializedSigProvider(jweRequired, jwsRequired);
+ String data = jws.signWith(theSigProvider);
+ JweEncryptionProvider theEncProvider = getInitializedEncryptionProvider(jweRequired);
+ if (theEncProvider != null) {
+ data = theEncProvider.encrypt(StringUtils.toBytesUTF8(data), null);
+ }
+ return data;
+ }
+ protected JwsSignatureProvider getInitializedSigProvider(boolean jwsRequired, boolean jweRequired) {
+ if (sigProvider != null) {
+ return sigProvider;
+ }
+ JwsSignatureProvider theSigProvider = JwsUtils.loadSignatureProvider(jwsRequired);
+ if (theSigProvider == null && jweRequired) {
+ return new NoneJwsSignatureProvider();
+ }
+ throw new SecurityException();
+ }
+ protected JweEncryptionProvider getInitializedEncryptionProvider(boolean required) {
+ if (encryptionProvider != null) {
+ return encryptionProvider;
+ }
+ return JweUtils.loadEncryptionProvider(required);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/jwt/AbstactJwtAccessTokenValidator.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/jwt/AbstactJwtAccessTokenValidator.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/jwt/AbstactJwtAccessTokenValidator.java
new file mode 100644
index 0000000..c0caa7c
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/jwt/AbstactJwtAccessTokenValidator.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.oauth2.tokens.jwt;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.rs.security.jose.jwt.AbstractJoseJwtConsumer;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
+import org.apache.cxf.rs.security.oauth2.common.AccessTokenValidation;
+import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
+import org.apache.cxf.rs.security.oauth2.provider.AccessTokenValidator;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthDataProvider;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+
+public abstract class AbstactJwtAccessTokenValidator extends AbstractJoseJwtConsumer
+ implements AccessTokenValidator {
+ private OAuthDataProvider dataProvider;
+
+ @Override
+ public List<String> getSupportedAuthorizationSchemes() {
+ return Collections.singletonList("*");
+ }
+
+ @Override
+ public AccessTokenValidation validateAccessToken(MessageContext mc,
+ String authScheme,
+ String authSchemeData,
+ MultivaluedMap<String, String> extraProps)
+ throws OAuthServiceException {
+ ServerAccessToken at = dataProvider.getAccessToken(authSchemeData);
+ JwtToken token = super.getJwtToken(at.getTokenKey(), false);
+ validateToken(token);
+ return new AccessTokenValidation(at);
+ }
+
+ public void setDataProvider(OAuthDataProvider dataProvider) {
+ this.dataProvider = dataProvider;
+ }
+
+ protected void validateToken(JwtToken jwt) {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/jwt/JwtAccessTokenUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/jwt/JwtAccessTokenUtils.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/jwt/JwtAccessTokenUtils.java
index 33e74e4..ddd3c51 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/jwt/JwtAccessTokenUtils.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/jwt/JwtAccessTokenUtils.java
@@ -25,7 +25,6 @@ import javax.crypto.SecretKey;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.rs.security.jose.JoseConstants;
-import org.apache.cxf.rs.security.jose.JoseHeaders;
import org.apache.cxf.rs.security.jose.jwa.Algorithm;
import org.apache.cxf.rs.security.jose.jwe.DirectKeyJweDecryption;
import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider;
@@ -33,10 +32,10 @@ import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider;
import org.apache.cxf.rs.security.jose.jwe.JweUtils;
import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer;
import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactProducer;
-import org.apache.cxf.rs.security.jose.jws.JwsSignature;
import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
import org.apache.cxf.rs.security.jose.jws.JwsUtils;
+import org.apache.cxf.rs.security.jose.jws.NoneJwsSignatureProvider;
import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
import org.apache.cxf.rs.security.jose.jwt.JwtToken;
import org.apache.cxf.rs.security.jose.jwt.JwtUtils;
@@ -60,7 +59,7 @@ public final class JwtAccessTokenUtils {
Client client,
JweEncryptionProvider jweEncryption) {
String jwtString = new JwsJwtCompactProducer(jwt)
- .signWith(new NoneSignatureProvider());
+ .signWith(new NoneJwsSignatureProvider());
String tokenId = jweEncryption.encrypt(getBytes(jwtString), null);
return toAccessToken(jwt, client, tokenId);
}
@@ -128,38 +127,7 @@ public final class JwtAccessTokenUtils {
// TODO: the issuer is indirectly validated by validating the signature
// but an extra check can be done
}
- private static class NoneSignatureProvider implements JwsSignatureProvider {
-
- @Override
- public String getAlgorithm() {
- return "none";
- }
-
- @Override
- public JwsSignature createJwsSignature(JoseHeaders headers) {
- return new NoneJwsSignature();
- }
-
- @Override
- public byte[] sign(JoseHeaders headers, byte[] content) {
- // TODO Auto-generated method stub
- return null;
- }
-
- }
- private static class NoneJwsSignature implements JwsSignature {
-
- @Override
- public void update(byte[] src, int off, int len) {
- // complete
- }
-
- @Override
- public byte[] sign() {
- return new byte[]{};
- }
-
- }
+
private static byte[] getBytes(String str) {
return StringUtils.toBytesUTF8(str);
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/2ef6f584/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/AbstractTokenValidator.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/AbstractTokenValidator.java b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/AbstractTokenValidator.java
index 69c54a4..f6e95c6 100644
--- a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/AbstractTokenValidator.java
+++ b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/AbstractTokenValidator.java
@@ -56,8 +56,11 @@ public abstract class AbstractTokenValidator {
wrappedJwtToken = jweDecryptor.decrypt(wrappedJwtToken).getContentText();
}
- // validate token signature
- return getTokenValidateSignature(wrappedJwtToken, idTokenKid);
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(wrappedJwtToken);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier(jwt, idTokenKid);
+ return validateToken(jwtConsumer, jwt, theSigVerifier);
+
}
protected void validateJwtClaims(JwtClaims claims, String clientId, boolean validateClaimsAlways) {
@@ -79,33 +82,7 @@ public abstract class AbstractTokenValidator {
JwtUtils.validateJwtTimeClaims(claims, issuedAtRange, validateClaimsAlways);
}
- protected JwtToken getTokenValidateSignature(String wrappedJwtToken, String idTokenKid) {
- // read id_token into JwtToken
- JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(wrappedJwtToken);
- JwtToken jwt = jwtConsumer.getJwtToken();
- JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier();
- if (theSigVerifier != null) {
- return validateToken(jwtConsumer, jwt, theSigVerifier);
- }
- if (jwkSetClient == null) {
- throw new SecurityException("Provider Jwk Set Client is not available");
- }
- String keyId = idTokenKid != null ? idTokenKid : jwtConsumer.getJwtToken().getHeaders().getKeyId();
- JsonWebKey key = keyId != null ? keyMap.get(keyId) : null;
- if (key == null) {
- JsonWebKeys keys = jwkSetClient.get(JsonWebKeys.class);
- if (keyId != null) {
- key = keys.getKey(keyId);
- } else if (keys.getKeys().size() == 1) {
- key = keys.getKeys().get(0);
- }
- keyMap.putAll(keys.getKeyIdMap());
- }
- if (key == null) {
- throw new SecurityException("JWK key with the key id: \"" + keyId + "\" is not available");
- }
- return validateToken(jwtConsumer, jwt, JwsUtils.getSignatureVerifier(key));
- }
+
protected JwtToken validateToken(JwsJwtCompactConsumer consumer, JwtToken jwt, JwsSignatureVerifier jws) {
if (!consumer.verifySignatureWith(jws)) {
throw new SecurityException("Invalid Signature");
@@ -138,10 +115,35 @@ public abstract class AbstractTokenValidator {
}
return JweUtils.loadDecryptionProvider(jweOnly);
}
- protected JwsSignatureVerifier getInitializedSigVerifier() {
+ protected JwsSignatureVerifier getInitializedSigVerifier(JwtToken jwt, String idTokenKid) {
if (jwsVerifier != null) {
return jwsVerifier;
}
- return JwsUtils.loadSignatureVerifier(false);
+ JwsSignatureVerifier theJwsVerifier = JwsUtils.loadSignatureVerifier(false);
+ if (theJwsVerifier != null) {
+ return theJwsVerifier;
+ }
+ if (jwkSetClient == null) {
+ throw new SecurityException("Provider Jwk Set Client is not available");
+ }
+ String keyId = idTokenKid != null ? idTokenKid : jwt.getHeaders().getKeyId();
+ JsonWebKey key = keyId != null ? keyMap.get(keyId) : null;
+ if (key == null) {
+ JsonWebKeys keys = jwkSetClient.get(JsonWebKeys.class);
+ if (keyId != null) {
+ key = keys.getKey(keyId);
+ } else if (keys.getKeys().size() == 1) {
+ key = keys.getKeys().get(0);
+ }
+ keyMap.putAll(keys.getKeyIdMap());
+ }
+ if (key == null) {
+ throw new SecurityException("JWK key with the key id: \"" + keyId + "\" is not available");
+ }
+ theJwsVerifier = JwsUtils.getSignatureVerifier(key);
+ if (jwkSetClient == null) {
+ throw new SecurityException();
+ }
+ return theJwsVerifier;
}
}