This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch 3.1.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 44216c8e5d081cfea61874281cb7f73f9f8e5b23
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Wed Aug 22 12:49:51 2018 +0100

    CXF-7806 - Add option to create JWT access tokens without persisting them
---
 .../cxf/rs/security/oauth2/common/AccessToken.java |  39 ++++---
 .../oauth2/provider/AbstractOAuthDataProvider.java | 123 ++++++++++++---------
 .../services/AbstractAccessTokenValidator.java     |  62 ++++++++---
 .../oauth2/services/TokenIntrospectionService.java |  47 ++++++--
 .../cxf/rs/security/oauth2/utils/OAuthUtils.java   |  96 ++++++++--------
 .../security/oidc/idp/IdTokenResponseFilter.java   |  23 ++--
 6 files changed, 241 insertions(+), 149 deletions(-)

diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessToken.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessToken.java
index 39699d4..5bee11e 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessToken.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessToken.java
@@ -27,6 +27,7 @@ import javax.persistence.FetchType;
 import javax.persistence.Id;
 import javax.persistence.MapKeyColumn;
 import javax.persistence.MappedSuperclass;
+import javax.persistence.Transient;
 
 /**
  * Base Access Token representation
@@ -35,33 +36,34 @@ import javax.persistence.MappedSuperclass;
 public abstract class AccessToken implements Serializable {
 
     private static final long serialVersionUID = -5750544301887053480L;
-    
+
     private String tokenKey;
     private String tokenType;
     private String refreshToken;
     private long expiresIn = -1;
     private long issuedAt = -1;
     private String issuer;
-    
-    
+    private String encodedToken;
+
+
     private Map<String, String> parameters = new LinkedHashMap<String, 
String>();
-    
+
     protected AccessToken() {
-        
+
     }
-    
+
     protected AccessToken(String tokenType, String tokenKey) {
         this.tokenType = tokenType;
         this.tokenKey = tokenKey;
     }
-    
+
     protected AccessToken(String tokenType, String tokenKey,
                           long expiresIn, long issuedAt) {
         this(tokenType, tokenKey);
         this.expiresIn = expiresIn;
         this.issuedAt = issuedAt;
     }
-    
+
     protected AccessToken(String tokenType, String tokenKey,
                           long expiresIn, long issuedAt,
                           String refreshToken,
@@ -78,11 +80,11 @@ public abstract class AccessToken implements Serializable {
     public String getTokenType() {
         return tokenType;
     }
-    
+
     public void setTokenType(String type) {
         this.tokenType = type;
     }
-    
+
     /**
      * Returns the token key
      * @return the key
@@ -91,7 +93,7 @@ public abstract class AccessToken implements Serializable {
     public String getTokenKey() {
         return tokenKey;
     }
-    
+
     public void setTokenKey(String key) {
         this.tokenKey = key;
     }
@@ -113,9 +115,9 @@ public abstract class AccessToken implements Serializable {
     public String getRefreshToken() {
         return refreshToken;
     }
-    
+
     /**
-     * Gets token parameters 
+     * Gets token parameters
      * @return
      */
     @ElementCollection(fetch = FetchType.EAGER)
@@ -143,7 +145,7 @@ public abstract class AccessToken implements Serializable {
     public void setIssuedAt(long issuedAt) {
         this.issuedAt = issuedAt;
     }
-    
+
     /**
      * Sets additional token parameters
      * @param parameters the token parameters
@@ -159,4 +161,13 @@ public abstract class AccessToken implements Serializable {
     public void setIssuer(String issuer) {
         this.issuer = issuer;
     }
+
+    @Transient
+    public String getEncodedToken() {
+        return encodedToken;
+    }
+
+    public void setEncodedToken(String encodedToken) {
+        this.encodedToken = encodedToken;
+    }
 }
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
index 209e574..a699912 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
@@ -54,15 +54,16 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
     private List<String> requiredScopes;
     private List<String> invisibleToClientScopes;
     private boolean supportPreauthorizedTokens;
-    
+
     private boolean useJwtFormatForAccessTokens;
+    private boolean persistJwtEncoding = true;
     private OAuthJoseJwtProducer jwtAccessTokenProducer;
     private Map<String, String> jwtAccessTokenClaimMap;
     private ProviderAuthenticationStrategy authenticationStrategy;
 
     protected AbstractOAuthDataProvider() {
     }
-    
+
     @Override
     public ServerAccessToken createAccessToken(AccessTokenRegistration reg)
         throws OAuthServiceException {
@@ -73,13 +74,13 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
         }
         return at;
     }
-    
+
     protected ServerAccessToken doCreateAccessToken(AccessTokenRegistration 
atReg) {
         ServerAccessToken at = createNewAccessToken(atReg.getClient(), 
atReg.getSubject());
         at.setAudiences(atReg.getAudiences());
         at.setGrantType(atReg.getGrantType());
         List<String> theScopes = atReg.getApprovedScope();
-        List<OAuthPermission> thePermissions = 
+        List<OAuthPermission> thePermissions =
             convertScopeToPermissions(atReg.getClient(), theScopes);
         at.setScopes(thePermissions);
         at.setSubject(atReg.getSubject());
@@ -100,19 +101,23 @@ public abstract class AbstractOAuthDataProvider 
implements OAuthDataProvider, Cl
         if (isUseJwtFormatForAccessTokens()) {
             JwtClaims claims = createJwtAccessToken(at);
             String jose = processJwtAccessToken(claims);
-            at.setTokenKey(jose);
+            if (isPersistJwtEncoding()) {
+                at.setTokenKey(jose);
+            } else {
+                at.setEncodedToken(jose);
+            }
         }
-        
+
         return at;
     }
-    
+
     protected JwtClaims createJwtAccessToken(ServerAccessToken at) {
         JwtClaims claims = new JwtClaims();
         claims.setTokenId(at.getTokenKey());
-        
+
         // 'client_id' or 'cid', default client_id
-        String clientIdClaimName = 
-            JwtTokenUtils.getClaimName(OAuthConstants.CLIENT_ID, 
OAuthConstants.CLIENT_ID, 
+        String clientIdClaimName =
+            JwtTokenUtils.getClaimName(OAuthConstants.CLIENT_ID, 
OAuthConstants.CLIENT_ID,
                                              getJwtAccessTokenClaimMap());
         claims.setClaim(clientIdClaimName, at.getClient().getClientId());
         claims.setIssuedAt(at.getIssuedAt());
@@ -124,10 +129,10 @@ public abstract class AbstractOAuthDataProvider 
implements OAuthDataProvider, Cl
             if (userSubject.getId() != null) {
                 claims.setSubject(userSubject.getId());
             }
-            
+
             // 'username' by default to be consistent with the token 
introspection response
             final String usernameProp = "username";
-            String usernameClaimName = 
+            String usernameClaimName =
                 JwtTokenUtils.getClaimName(usernameProp, usernameProp, 
getJwtAccessTokenClaimMap());
             claims.setClaim(usernameClaimName, userSubject.getLogin());
         }
@@ -135,7 +140,7 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
             claims.setIssuer(at.getIssuer());
         }
         if (!at.getScopes().isEmpty()) {
-            claims.setClaim(OAuthConstants.SCOPE, 
+            claims.setClaim(OAuthConstants.SCOPE,
                             
OAuthUtils.convertPermissionsToScopeList(at.getScopes()));
         }
         // OAuth2 resource indicators (resource server audience)
@@ -180,22 +185,22 @@ public abstract class AbstractOAuthDataProvider 
implements OAuthDataProvider, Cl
         }
         return claims;
     }
-    
+
     protected ServerAccessToken createNewAccessToken(Client client, 
UserSubject userSub) {
         return new BearerAccessToken(client, accessTokenLifetime);
     }
-    
+
     @Override
     public void removeAccessToken(ServerAccessToken token) throws 
OAuthServiceException {
         revokeAccessToken(token.getTokenKey());
     }
-    
+
     @Override
     public ServerAccessToken refreshAccessToken(Client client, String 
refreshTokenKey,
                                                 List<String> restrictedScopes) 
throws OAuthServiceException {
-        RefreshToken currentRefreshToken = recycleRefreshTokens 
+        RefreshToken currentRefreshToken = recycleRefreshTokens
             ? revokeRefreshToken(refreshTokenKey) : 
getRefreshToken(refreshTokenKey);
-        if (currentRefreshToken == null) { 
+        if (currentRefreshToken == null) {
             throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED);
         }
         if (OAuthUtils.isExpired(currentRefreshToken.getIssuedAt(), 
currentRefreshToken.getExpiresIn())) {
@@ -207,7 +212,7 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
         if (recycleRefreshTokens) {
             revokeAccessTokens(currentRefreshToken);
         }
-        
+
         ServerAccessToken at = doRefreshAccessToken(client, 
currentRefreshToken, restrictedScopes);
         saveAccessToken(at);
         if (recycleRefreshTokens) {
@@ -217,11 +222,11 @@ public abstract class AbstractOAuthDataProvider 
implements OAuthDataProvider, Cl
         }
         return at;
     }
-    
+
     @Override
     public void revokeToken(Client client, String tokenKey, String 
tokenTypeHint) throws OAuthServiceException {
         ServerAccessToken accessToken = null;
-        if (!OAuthConstants.REFRESH_TOKEN.equals(tokenTypeHint)) { 
+        if (!OAuthConstants.REFRESH_TOKEN.equals(tokenTypeHint)) {
             accessToken = revokeAccessToken(tokenKey);
         }
         if (accessToken != null) {
@@ -237,7 +242,7 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
             if (rt == null) {
                 return;
             }
-            
+
             unlinkRefreshAccessToken(rt, accessToken.getTokenKey());
             if (rt.getAccessTokens().isEmpty()) {
                 revokeRefreshToken(rt.getTokenKey());
@@ -245,7 +250,7 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
                 saveRefreshToken(rt);
             }
         }
-        
+
     }
 
     protected void revokeAccessTokens(RefreshToken currentRefreshToken) {
@@ -266,8 +271,8 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
         }
     }
 
-        
-    
+
+
     @Override
     public List<OAuthPermission> convertScopeToPermissions(Client client, 
List<String> requestedScopes) {
         checkRequestedScopes(client, requestedScopes);
@@ -281,9 +286,9 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
             if (!list.isEmpty()) {
                 return list;
             }
-        } 
+        }
         throw new OAuthServiceException("Requested scopes can not be mapped");
-        
+
     }
 
     protected void checkRequestedScopes(Client client, List<String> 
requestedScopes) {
@@ -292,7 +297,7 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
         }
     }
 
-    protected void convertSingleScopeToPermission(Client client, 
+    protected void convertSingleScopeToPermission(Client client,
                                                   String scope,
                                                   List<OAuthPermission> perms) 
{
         OAuthPermission permission = permissionMap.get(scope);
@@ -303,9 +308,9 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
     }
 
     @Override
-    public ServerAccessToken getPreauthorizedToken(Client client, 
+    public ServerAccessToken getPreauthorizedToken(Client client,
                                                    List<String> 
requestedScopes,
-                                                   UserSubject sub, 
+                                                   UserSubject sub,
                                                    String grantType) throws 
OAuthServiceException {
         if (!isSupportPreauthorizedTokens()) {
             return null;
@@ -321,15 +326,15 @@ public abstract class AbstractOAuthDataProvider 
implements OAuthDataProvider, Cl
                 break;
             }
         }
-        if (token != null 
+        if (token != null
             && OAuthUtils.isExpired(token.getIssuedAt(), 
token.getExpiresIn())) {
             revokeToken(client, token.getTokenKey(), 
OAuthConstants.ACCESS_TOKEN);
             token = null;
         }
         return token;
-        
+
     }
-    
+
     protected boolean isRefreshTokenSupported(List<String> theScopes) {
         return theScopes.contains(OAuthConstants.REFRESH_TOKEN_SCOPE);
     }
@@ -384,7 +389,7 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
         rt.setClientCodeVerifier(at.getClientCodeVerifier());
         return rt;
     }
-    
+
     protected void linkAccessTokenToRefreshToken(RefreshToken rt, 
ServerAccessToken at) {
         if (!rt.getAccessTokens().contains(at.getTokenKey())) {
             rt.getAccessTokens().add(at.getTokenKey());
@@ -394,8 +399,8 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
         at.setRefreshToken(rt.getTokenKey());
     }
 
-    protected ServerAccessToken doRefreshAccessToken(Client client, 
-                                                     RefreshToken 
oldRefreshToken, 
+    protected ServerAccessToken doRefreshAccessToken(Client client,
+                                                     RefreshToken 
oldRefreshToken,
                                                      List<String> 
restrictedScopes) {
         ServerAccessToken at = createNewAccessToken(client, 
oldRefreshToken.getSubject());
         at.setAudiences(oldRefreshToken.getAudiences() != null
@@ -421,12 +426,16 @@ public abstract class AbstractOAuthDataProvider 
implements OAuthDataProvider, Cl
         if (isUseJwtFormatForAccessTokens()) {
             JwtClaims claims = createJwtAccessToken(at);
             String jose = processJwtAccessToken(claims);
-            at.setTokenKey(jose);
+            if (isPersistJwtEncoding()) {
+                at.setTokenKey(jose);
+            } else {
+                at.setEncodedToken(jose);
+            }
         }
 
         return at;
     }
-    
+
     public void setAccessTokenLifetime(long accessTokenLifetime) {
         this.accessTokenLifetime = accessTokenLifetime;
     }
@@ -434,7 +443,7 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
     public void setRefreshTokenLifetime(long refreshTokenLifetime) {
         this.refreshTokenLifetime = refreshTokenLifetime;
     }
-    
+
     public void setRecycleRefreshTokens(boolean recycleRefreshTokens) {
         this.recycleRefreshTokens = recycleRefreshTokens;
         this.refreshTokenLock = recycleRefreshTokens ? null : new Object();
@@ -454,10 +463,10 @@ public abstract class AbstractOAuthDataProvider 
implements OAuthDataProvider, Cl
             }
         }
     }
-    
+
     public void close() {
     }
-    
+
     public Map<String, OAuthPermission> getPermissionMap() {
         return permissionMap;
     }
@@ -465,7 +474,7 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
     public void setPermissionMap(Map<String, OAuthPermission> permissionMap) {
         this.permissionMap = permissionMap;
     }
-    
+
     public void setSupportedScopes(Map<String, String> scopes) {
         for (Map.Entry<String, String> entry : scopes.entrySet()) {
             OAuthPermission permission = new OAuthPermission(entry.getKey(), 
entry.getValue());
@@ -483,7 +492,7 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
             OAuthUtils.injectContextIntoOAuthProvider(messageContext, 
authenticationStrategy);
         }
     }
-    
+
     protected void removeClientTokens(Client c) {
         List<RefreshToken> refreshTokens = getRefreshTokens(c, null);
         if (refreshTokens != null) {
@@ -498,7 +507,7 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
             }
         }
     }
-    
+
     @Override
     public Client removeClient(String clientId) {
         Client c = doGetClient(clientId);
@@ -549,15 +558,15 @@ public abstract class AbstractOAuthDataProvider 
implements OAuthDataProvider, Cl
         }
         return at;
     }
-    protected RefreshToken revokeRefreshToken(String refreshTokenKey) { 
+    protected RefreshToken revokeRefreshToken(String refreshTokenKey) {
         RefreshToken refreshToken = getRefreshToken(refreshTokenKey);
         if (refreshToken != null) {
             doRevokeRefreshToken(refreshToken);
         }
         return refreshToken;
     }
-    
-    
+
+
     protected abstract void saveAccessToken(ServerAccessToken serverToken);
     protected abstract void saveRefreshToken(RefreshToken refreshToken);
     protected abstract void doRevokeAccessToken(ServerAccessToken accessToken);
@@ -600,8 +609,8 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
         this.supportPreauthorizedTokens = supportPreauthorizedTokens;
     }
     protected static boolean isClientMatched(Client c, UserSubject 
resourceOwner) {
-        return resourceOwner == null 
-            || c.getResourceOwnerSubject() != null 
+        return resourceOwner == null
+            || c.getResourceOwnerSubject() != null
                 && 
c.getResourceOwnerSubject().getLogin().equals(resourceOwner.getLogin());
     }
     protected static boolean isTokenMatched(ServerAccessToken token, Client c, 
UserSubject sub) {
@@ -613,7 +622,7 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
         }
         return false;
     }
-    public void setClients(List<Client> clients) {    
+    public void setClients(List<Client> clients) {
         for (Client c : clients) {
             setClient(c);
         }
@@ -634,11 +643,11 @@ public abstract class AbstractOAuthDataProvider 
implements OAuthDataProvider, Cl
     public void setJwtAccessTokenProducer(OAuthJoseJwtProducer 
jwtAccessTokenProducer) {
         this.jwtAccessTokenProducer = jwtAccessTokenProducer;
     }
-    
+
     protected String processJwtAccessToken(JwtClaims jwtCliams) {
         // It will JWS-sign (default) and/or JWE-encrypt
-        OAuthJoseJwtProducer processor = 
-            getJwtAccessTokenProducer() == null ? new OAuthJoseJwtProducer() : 
getJwtAccessTokenProducer(); 
+        OAuthJoseJwtProducer processor =
+            getJwtAccessTokenProducer() == null ? new OAuthJoseJwtProducer() : 
getJwtAccessTokenProducer();
         return processor.processJwt(new JwtToken(jwtCliams));
     }
 
@@ -649,4 +658,12 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
     public void setJwtAccessTokenClaimMap(Map<String, String> 
jwtAccessTokenClaimMap) {
         this.jwtAccessTokenClaimMap = jwtAccessTokenClaimMap;
     }
+
+    public boolean isPersistJwtEncoding() {
+        return persistJwtEncoding;
+    }
+
+    public void setPersistJwtEncoding(boolean persistJwtEncoding) {
+        this.persistJwtEncoding = persistJwtEncoding;
+    }
 }
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractAccessTokenValidator.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractAccessTokenValidator.java
index 4d80d89..f8ab2ae 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractAccessTokenValidator.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractAccessTokenValidator.java
@@ -31,6 +31,9 @@ import org.apache.cxf.jaxrs.ext.MessageContext;
 import org.apache.cxf.jaxrs.ext.MessageContextImpl;
 import org.apache.cxf.jaxrs.utils.ExceptionUtils;
 import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.apache.cxf.rs.security.jose.jwt.JoseJwtConsumer;
+import org.apache.cxf.rs.security.jose.jwt.JwtException;
+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;
@@ -41,41 +44,43 @@ import 
org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
 import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
 
 public abstract class AbstractAccessTokenValidator {
-    
+
     private static final String DEFAULT_AUTH_SCHEME = 
OAuthConstants.BEARER_AUTHORIZATION_SCHEME;
-    
+
 
     protected Set<String> supportedSchemes = new HashSet<String>();
     protected String realm;
-    
+
     private MessageContext mc;
     private List<AccessTokenValidator> tokenHandlers = Collections.emptyList();
     private OAuthDataProvider dataProvider;
-    
+
     private int maxValidationDataCacheSize;
     private ConcurrentHashMap<String, AccessTokenValidation> 
accessTokenValidations =
         new ConcurrentHashMap<String, AccessTokenValidation>();
-    
+    private JoseJwtConsumer jwtTokenConsumer;
+    private boolean persistJwtEncoding = true;
+
     public void setTokenValidator(AccessTokenValidator validator) {
         setTokenValidators(Collections.singletonList(validator));
     }
-    
+
     public void setTokenValidators(List<AccessTokenValidator> validators) {
         tokenHandlers = validators;
         for (AccessTokenValidator handler : validators) {
             
supportedSchemes.addAll(handler.getSupportedAuthorizationSchemes());
         }
     }
-    
+
     public void setDataProvider(OAuthDataProvider provider) {
         dataProvider = provider;
     }
-    
+
     @Context
     public void setMessageContext(MessageContext context) {
         this.mc = context;
     }
-    
+
     public MessageContext getMessageContext() {
         return mc != null ? mc : new 
MessageContextImpl(PhaseInterceptorChain.getCurrentMessage());
     }
@@ -88,9 +93,9 @@ public abstract class AbstractAccessTokenValidator {
                 return handler;
             }
         }
-        return null;        
+        return null;
     }
-    
+
     /**
      * Get the access token
      */
@@ -100,10 +105,10 @@ public abstract class AbstractAccessTokenValidator {
         if (dataProvider == null && tokenHandlers.isEmpty()) {
             throw ExceptionUtils.toInternalServerErrorException(null, null);
         }
-        
+
         if (maxValidationDataCacheSize > 0) {
             accessTokenV = accessTokenValidations.get(authSchemeData);
-        } 
+        }
         ServerAccessToken localAccessToken = null;
         if (accessTokenV == null) {
             // Get the registered handler capable of processing the token
@@ -111,7 +116,7 @@ public abstract class AbstractAccessTokenValidator {
             if (handler != null) {
                 try {
                     // Convert the HTTP Authorization scheme data into a token
-                    accessTokenV = 
handler.validateAccessToken(getMessageContext(), authScheme, authSchemeData, 
+                    accessTokenV = 
handler.validateAccessToken(getMessageContext(), authScheme, authSchemeData,
                                                                extraProps);
                 } catch (OAuthServiceException ex) {
                     
AuthorizationUtils.throwAuthorizationFailure(Collections.singleton(authScheme), 
realm);
@@ -122,8 +127,16 @@ public abstract class AbstractAccessTokenValidator {
             // Default processing if no registered providers available
             if (accessTokenV == null && dataProvider != null && 
authScheme.equals(DEFAULT_AUTH_SCHEME)) {
                 try {
-                    localAccessToken = 
dataProvider.getAccessToken(authSchemeData);
-                } catch (OAuthServiceException ex) {
+                    String cacheKey = authSchemeData;
+                    if (!persistJwtEncoding) {
+                        JoseJwtConsumer theConsumer =
+                            jwtTokenConsumer == null ? new JoseJwtConsumer() : 
jwtTokenConsumer;
+                        JwtToken token = 
theConsumer.getJwtToken(authSchemeData);
+                        cacheKey = token.getClaims().getTokenId();
+                    }
+
+                    localAccessToken = dataProvider.getAccessToken(cacheKey);
+                } catch (JwtException | OAuthServiceException ex) {
                     // to be handled next
                 }
                 if (localAccessToken == null) {
@@ -168,5 +181,20 @@ public abstract class AbstractAccessTokenValidator {
         this.maxValidationDataCacheSize = maxValidationDataCacheSize;
     }
 
-    
+    public JoseJwtConsumer getJwtTokenConsumer() {
+        return jwtTokenConsumer;
+    }
+
+    public void setJwtTokenConsumer(JoseJwtConsumer jwtTokenConsumer) {
+        this.jwtTokenConsumer = jwtTokenConsumer;
+    }
+
+    public boolean isPersistJwtEncoding() {
+        return persistJwtEncoding;
+    }
+
+    public void setPersistJwtEncoding(boolean persistJwtEncoding) {
+        this.persistJwtEncoding = persistJwtEncoding;
+    }
+
 }
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/TokenIntrospectionService.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/TokenIntrospectionService.java
index c21d43e..3fe5461 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/TokenIntrospectionService.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/TokenIntrospectionService.java
@@ -34,6 +34,9 @@ import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.jaxrs.ext.MessageContext;
 import org.apache.cxf.jaxrs.utils.ExceptionUtils;
+import org.apache.cxf.rs.security.jose.jwt.JoseJwtConsumer;
+import org.apache.cxf.rs.security.jose.jwt.JwtException;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
 import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
 import org.apache.cxf.rs.security.oauth2.common.TokenIntrospection;
 import org.apache.cxf.rs.security.oauth2.common.UserSubject;
@@ -49,14 +52,27 @@ public class TokenIntrospectionService {
     private boolean reportExtraTokenProperties = true;
     private MessageContext mc;
     private OAuthDataProvider dataProvider;
+    private JoseJwtConsumer jwtTokenConsumer;
+    private boolean persistJwtEncoding = true;
+
     @POST
     @Produces({MediaType.APPLICATION_JSON })
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public TokenIntrospection getTokenIntrospection(@Encoded 
MultivaluedMap<String, String> params) {
         checkSecurityContext();
         String tokenId = params.getFirst(OAuthConstants.TOKEN_ID);
+        if (!persistJwtEncoding) {
+            try {
+                JoseJwtConsumer theConsumer = jwtTokenConsumer == null ? new 
JoseJwtConsumer() : jwtTokenConsumer;
+                JwtToken token = theConsumer.getJwtToken(tokenId);
+                tokenId = token.getClaims().getTokenId();
+            } catch (JwtException ex) {
+                return new TokenIntrospection(false);
+            }
+        }
+
         ServerAccessToken at = dataProvider.getAccessToken(tokenId);
-        if (at == null || OAuthUtils.isExpired(at.getIssuedAt(), 
at.getExpiresIn())) { 
+        if (at == null || OAuthUtils.isExpired(at.getIssuedAt(), 
at.getExpiresIn())) {
             return new TokenIntrospection(false);
         }
         TokenIntrospection response = new TokenIntrospection(true);
@@ -77,18 +93,18 @@ public class TokenIntrospectionService {
         if (at.getIssuer() != null) {
             response.setIss(at.getIssuer());
         }
-        
+
         response.setIat(at.getIssuedAt());
         if (at.getExpiresIn() > 0) {
             response.setExp(at.getIssuedAt() + at.getExpiresIn());
         }
-        
+
         response.setTokenType(at.getTokenType());
-        
+
         if (reportExtraTokenProperties) {
             response.getExtensions().putAll(at.getExtraProperties());
         }
-        
+
         return response;
     }
 
@@ -102,7 +118,7 @@ public class TokenIntrospectionService {
             LOG.warning("Authenticated Principal is not available");
             ExceptionUtils.toNotAuthorizedException(null, null);
         }
-        
+
     }
 
     public void setBlockUnsecureRequests(boolean blockUnsecureRequests) {
@@ -116,7 +132,7 @@ public class TokenIntrospectionService {
     public void setDataProvider(OAuthDataProvider dataProvider) {
         this.dataProvider = dataProvider;
     }
-    
+
     @Context
     public void setMessageContext(MessageContext context) {
         this.mc = context;
@@ -125,4 +141,21 @@ public class TokenIntrospectionService {
     public void setReportExtraTokenProperties(boolean 
reportExtraTokenProperties) {
         this.reportExtraTokenProperties = reportExtraTokenProperties;
     }
+
+    public JoseJwtConsumer getJwtTokenConsumer() {
+        return jwtTokenConsumer;
+    }
+
+    public void setJwtTokenConsumer(JoseJwtConsumer jwtTokenConsumer) {
+        this.jwtTokenConsumer = jwtTokenConsumer;
+    }
+
+    public boolean isPersistJwtEncoding() {
+        return persistJwtEncoding;
+    }
+
+    public void setPersistJwtEncoding(boolean persistJwtEncoding) {
+        this.persistJwtEncoding = persistJwtEncoding;
+    }
+
 }
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
index ffe0180..18412d1 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
@@ -68,7 +68,7 @@ import org.apache.cxf.security.SecurityContext;
 import org.apache.cxf.security.transport.TLSSessionInfo;
 
 /**
- * Various utility methods 
+ * Various utility methods
  */
 public final class OAuthUtils {
 
@@ -88,7 +88,7 @@ public final class OAuthUtils {
             throw new OAuthServiceException(ex);
         }
     }
-    
+
     public static boolean compareCertificateThumbprints(X509Certificate cert, 
String encodedThumbprint) {
         try {
             byte[] thumbprint = createCertificateThumbprint(cert);
@@ -98,7 +98,7 @@ public final class OAuthUtils {
             return false;
         }
     }
-    
+
 
     public static boolean compareTlsCertificates(TLSSessionInfo tlsInfo,
                                           List<String> base64EncodedCerts) {
@@ -120,24 +120,24 @@ public final class OAuthUtils {
         }
         return false;
     }
-    
+
     public static boolean isMutualTls(javax.ws.rs.core.SecurityContext sc, 
TLSSessionInfo tlsSessionInfo) {
         // Pure 2-way TLS authentication
-        return tlsSessionInfo != null 
+        return tlsSessionInfo != null
             && StringUtils.isEmpty(sc.getAuthenticationScheme())
             && getRootTLSCertificate(tlsSessionInfo) != null;
     }
-    
+
     public static String getSubjectDnFromTLSCertificates(X509Certificate cert) 
{
         X500Principal x509Principal = cert.getSubjectX500Principal();
         return x509Principal.getName();
     }
-    
+
     public static String getIssuerDnFromTLSCertificates(X509Certificate cert) {
         X500Principal x509Principal = cert.getIssuerX500Principal();
         return x509Principal.getName();
     }
-    
+
     public static X509Certificate getRootTLSCertificate(TLSSessionInfo 
tlsInfo) {
         Certificate[] clientCerts = tlsInfo.getPeerCertificates();
         if (clientCerts != null && clientCerts.length > 0) {
@@ -145,7 +145,7 @@ public final class OAuthUtils {
         }
         return null;
     }
-    
+
     public static void injectContextIntoOAuthProvider(MessageContext context, 
Object provider) {
         Method dataProviderContextMethod = null;
         try {
@@ -162,7 +162,7 @@ public final class OAuthUtils {
             }
         }
     }
-    
+
     public static String setSessionToken(MessageContext mc) {
         return setSessionToken(mc, 0);
     }
@@ -175,8 +175,8 @@ public final class OAuthUtils {
     public static String setSessionToken(MessageContext mc, String 
sessionToken, int maxInactiveInterval) {
         return setSessionToken(mc, sessionToken, null, 0);
     }
-    public static String setSessionToken(MessageContext mc, String 
sessionToken, 
-                                                String attribute, int 
maxInactiveInterval) {    
+    public static String setSessionToken(MessageContext mc, String 
sessionToken,
+                                                String attribute, int 
maxInactiveInterval) {
         HttpSession session = mc.getHttpServletRequest().getSession();
         if (maxInactiveInterval > 0) {
             session.setMaxInactiveInterval(maxInactiveInterval);
@@ -192,12 +192,12 @@ public final class OAuthUtils {
     public static String getSessionToken(MessageContext mc, String attribute) {
         return getSessionToken(mc, attribute, true);
     }
-    public static String getSessionToken(MessageContext mc, String attribute, 
boolean remove) {    
+    public static String getSessionToken(MessageContext mc, String attribute, 
boolean remove) {
         HttpSession session = mc.getHttpServletRequest().getSession();
-        String theAttribute = attribute == null ? 
OAuthConstants.SESSION_AUTHENTICITY_TOKEN : attribute;  
+        String theAttribute = attribute == null ? 
OAuthConstants.SESSION_AUTHENTICITY_TOKEN : attribute;
         String sessionToken = (String)session.getAttribute(theAttribute);
         if (sessionToken != null && remove) {
-            session.removeAttribute(theAttribute);    
+            session.removeAttribute(theAttribute);
         }
         return sessionToken;
     }
@@ -225,7 +225,7 @@ public final class OAuthUtils {
         }
         return subject;
     }
-    
+
     public static String convertPermissionsToScope(List<OAuthPermission> 
perms) {
         StringBuilder sb = new StringBuilder();
         for (OAuthPermission perm : perms) {
@@ -239,7 +239,7 @@ public final class OAuthUtils {
         }
         return sb.toString();
     }
-    
+
     public static List<String> 
convertPermissionsToScopeList(List<OAuthPermission> perms) {
         List<String> list = new LinkedList<String>();
         for (OAuthPermission perm : perms) {
@@ -247,9 +247,9 @@ public final class OAuthUtils {
         }
         return list;
     }
-    
-    public static boolean isGrantSupportedForClient(Client client, 
-                                                    boolean 
canSupportPublicClients, 
+
+    public static boolean isGrantSupportedForClient(Client client,
+                                                    boolean 
canSupportPublicClients,
                                                     String grantType) {
         if (grantType == null || !client.isConfidential() && 
!canSupportPublicClients) {
             return false;
@@ -257,13 +257,13 @@ public final class OAuthUtils {
         List<String> allowedGrants = client.getAllowedGrantTypes();
         return allowedGrants.isEmpty() || allowedGrants.contains(grantType);
     }
-    
+
     public static List<String> parseScope(String requestedScope) {
         List<String> list = new LinkedList<String>();
         if (requestedScope != null) {
             String[] scopeValues = requestedScope.split(" ");
             for (String scope : scopeValues) {
-                if (!StringUtils.isEmpty(scope)) {        
+                if (!StringUtils.isEmpty(scope)) {
                     list.add(scope);
                 }
             }
@@ -280,34 +280,34 @@ public final class OAuthUtils {
         }
         return 
StringUtils.toHexString(CryptoUtils.generateSecureRandomBytes(byteSize));
     }
-    
+
     public static long getIssuedAt() {
         return System.currentTimeMillis() / 1000L;
     }
-    
+
     public static boolean isExpired(Long issuedAt, Long lifetime) {
         // At some point -1 was used to indicate an unlimited lifetime
-        // with 0 being introduced instead at a later stage. 
-        // In theory there still could be a code around initializing the 
tokens with -1. 
+        // with 0 being introduced instead at a later stage.
+        // In theory there still could be a code around initializing the 
tokens with -1.
         // Treating -1 and 0 the same way is reasonable and it also makes it 
easier to
         // deal with the token introspection responses with no issuedAt time 
reported
         return lifetime == null
             || lifetime < -1
             || lifetime > 0L && issuedAt + lifetime < 
System.currentTimeMillis() / 1000L;
     }
-    
-    public static boolean validateAudience(String providedAudience, 
+
+    public static boolean validateAudience(String providedAudience,
                                            List<String> allowedAudiences) {
-        return providedAudience == null 
+        return providedAudience == null
             || validateAudiences(Collections.singletonList(providedAudience), 
allowedAudiences);
     }
-    public static boolean validateAudiences(List<String> providedAudiences, 
+    public static boolean validateAudiences(List<String> providedAudiences,
                                             List<String> allowedAudiences) {
-        return StringUtils.isEmpty(providedAudiences) 
+        return StringUtils.isEmpty(providedAudiences)
                && StringUtils.isEmpty(allowedAudiences)
                || allowedAudiences.containsAll(providedAudiences);
     }
-    
+
     public static boolean checkRequestURI(String servletPath, String uri) {
         boolean wildcard = uri.endsWith("*");
         String theURI = wildcard ? uri.substring(0, uri.length() - 1) : uri;
@@ -325,8 +325,8 @@ public final class OAuthUtils {
         }
         return false;
     }
-    
-    public static List<String> getRequestedScopes(Client client, 
+
+    public static List<String> getRequestedScopes(Client client,
                                                   String scopeParameter,
                                                   boolean useAllClientScopes,
                                                   boolean 
partialMatchScopeValidation) {
@@ -346,21 +346,21 @@ public final class OAuthUtils {
                 }
             }
         }
-        
+
         return requestScopes;
     }
-    
+
     public static boolean validateScopes(List<String> requestScopes, 
List<String> registeredScopes,
                                          boolean partialMatchScopeValidation) {
         if (!registeredScopes.isEmpty()) {
-            // if it is a strict validation then pre-registered scopes have to 
contains all 
+            // if it is a strict validation then pre-registered scopes have to 
contains all
             // the current request scopes
             if (!partialMatchScopeValidation) {
                 return registeredScopes.containsAll(requestScopes);
             } else {
                 for (String requestScope : requestScopes) {
                     boolean match = false;
-                    for (String registeredScope : registeredScopes) { 
+                    for (String registeredScope : registeredScopes) {
                         if (requestScope.startsWith(registeredScope)) {
                             match = true;
                             break;
@@ -376,15 +376,17 @@ public final class OAuthUtils {
     }
 
     public static ClientAccessToken toClientAccessToken(ServerAccessToken 
serverToken, boolean supportOptionalParams) {
+        String tokenKey =
+            serverToken.getEncodedToken() != null ? 
serverToken.getEncodedToken() : serverToken.getTokenKey();
         ClientAccessToken clientToken = new 
ClientAccessToken(serverToken.getTokenType(),
-                                                              
serverToken.getTokenKey());
+                                                              tokenKey);
         clientToken.setRefreshToken(serverToken.getRefreshToken());
         if (supportOptionalParams) {
             clientToken.setExpiresIn(serverToken.getExpiresIn());
             List<OAuthPermission> perms = serverToken.getScopes();
             String scopeString = OAuthUtils.convertPermissionsToScope(perms);
             if (!StringUtils.isEmpty(scopeString)) {
-                clientToken.setApprovedScope(scopeString);    
+                clientToken.setApprovedScope(scopeString);
             }
             clientToken.setParameters(new HashMap<String, 
String>(serverToken.getParameters()));
         }
@@ -393,27 +395,27 @@ public final class OAuthUtils {
 
     public static JwsSignatureProvider getClientSecretSignatureProvider(String 
clientSecret) {
         Properties sigProps = JwsUtils.loadSignatureOutProperties(false);
-        return JwsUtils.getHmacSignatureProvider(clientSecret, 
+        return JwsUtils.getHmacSignatureProvider(clientSecret,
                                                  
getClientSecretSignatureAlgorithm(sigProps));
     }
     public static JwsSignatureVerifier getClientSecretSignatureVerifier(String 
clientSecret) {
         Properties sigProps = JwsUtils.loadSignatureOutProperties(false);
-        return JwsUtils.getHmacSignatureVerifier(clientSecret, 
+        return JwsUtils.getHmacSignatureVerifier(clientSecret,
                                                  
getClientSecretSignatureAlgorithm(sigProps));
     }
-    
+
     public static JweDecryptionProvider 
getClientSecretDecryptionProvider(String clientSecret) {
         Properties props = JweUtils.loadEncryptionInProperties(false);
         byte[] key = StringUtils.toBytesUTF8(clientSecret);
         return JweUtils.getDirectKeyJweDecryption(key, 
getClientSecretContentAlgorithm(props));
     }
-    
+
     public static JweEncryptionProvider 
getClientSecretEncryptionProvider(String clientSecret) {
         Properties props = JweUtils.loadEncryptionInProperties(false);
         byte[] key = StringUtils.toBytesUTF8(clientSecret);
         return JweUtils.getDirectKeyJweEncryption(key, 
getClientSecretContentAlgorithm(props));
     }
-    
+
     private static ContentAlgorithm getClientSecretContentAlgorithm(Properties 
props) {
         String ctAlgoProp = 
props.getProperty(OAuthConstants.CLIENT_SECRET_CONTENT_ENCRYPTION_ALGORITHM);
         if (ctAlgoProp == null) {
@@ -423,9 +425,9 @@ public final class OAuthUtils {
         ctAlgo = ctAlgo != null ? ctAlgo : ContentAlgorithm.A128GCM;
         return ctAlgo;
     }
-    
+
     public static SignatureAlgorithm 
getClientSecretSignatureAlgorithm(Properties sigProps) {
-        
+
         String clientSecretSigProp = 
sigProps.getProperty(OAuthConstants.CLIENT_SECRET_SIGNATURE_ALGORITHM);
         if (clientSecretSigProp == null) {
             String sigProp = 
sigProps.getProperty(JoseConstants.RSSEC_SIGNATURE_ALGORITHM);
diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java
index f7ed11f..7fe1e89 100644
--- 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java
+++ 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/IdTokenResponseFilter.java
@@ -59,13 +59,13 @@ public class IdTokenResponseFilter extends 
OAuthServerJoseJwtProducer implements
         String idToken = getProcessedIdToken(st);
         if (idToken != null) {
             ct.getParameters().put(OidcUtils.ID_TOKEN, idToken);
-        } 
-        
+        }
+
     }
     private String getProcessedIdToken(ServerAccessToken st) {
         if (idTokenProvider != null) {
-            IdToken idToken = 
-                idTokenProvider.getIdToken(st.getClient().getClientId(), 
st.getSubject(), 
+            IdToken idToken =
+                idTokenProvider.getIdToken(st.getClient().getClientId(), 
st.getSubject(),
                                            
OAuthUtils.convertPermissionsToScopeList(st.getScopes()));
             setAtHashAndNonce(idToken, st);
             return processJwt(new JwtToken(idToken), st.getClient());
@@ -84,17 +84,17 @@ public class IdTokenResponseFilter extends 
OAuthServerJoseJwtProducer implements
             }
         }
         return null;
-        
+
     }
     private void setAtHashAndNonce(IdToken idToken, ServerAccessToken st) {
         String rType = st.getResponseType();
         boolean atHashRequired = idToken.getAccessTokenHash() == null
             && (rType == null || 
!rType.equals(OidcUtils.ID_TOKEN_RESPONSE_TYPE));
-        boolean cHashRequired = idToken.getAuthorizationCodeHash() == null 
-            && rType != null 
+        boolean cHashRequired = idToken.getAuthorizationCodeHash() == null
+            && rType != null
             && (rType.equals(OidcUtils.CODE_ID_TOKEN_AT_RESPONSE_TYPE)
                 || rType.equals(OidcUtils.CODE_ID_TOKEN_RESPONSE_TYPE));
-        
+
         Message m = JAXRSUtils.getCurrentMessage();
         if (atHashRequired || cHashRequired) {
             Properties props = JwsUtils.loadSignatureOutProperties(false);
@@ -106,7 +106,8 @@ public class IdTokenResponseFilter extends 
OAuthServerJoseJwtProducer implements
             }
             if (sigAlgo != SignatureAlgorithm.NONE) {
                 if (atHashRequired) {
-                    String atHash = 
OidcUtils.calculateAccessTokenHash(st.getTokenKey(), sigAlgo);
+                    String tokenKey = st.getEncodedToken() != null ? 
st.getEncodedToken() : st.getTokenKey();
+                    String atHash = 
OidcUtils.calculateAccessTokenHash(tokenKey, sigAlgo);
                     idToken.setAccessTokenHash(atHash);
                 }
                 if (cHashRequired) {
@@ -125,13 +126,13 @@ public class IdTokenResponseFilter extends 
OAuthServerJoseJwtProducer implements
                 }
             }
         }
-        
+
         if (m != null && m.getExchange().containsKey(OAuthConstants.NONCE)) {
             
idToken.setNonce((String)m.getExchange().get(OAuthConstants.NONCE));
         } else if (st.getNonce() != null) {
             idToken.setNonce(st.getNonce());
         }
-        
+
     }
     public void setIdTokenProvider(IdTokenProvider idTokenProvider) {
         this.idTokenProvider = idTokenProvider;

Reply via email to