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/23 19:11:08 UTC

cxf git commit: Prototyping a code to make it much easier for confoidential client webapps to deal with OAuth2 authorization code flows

Repository: cxf
Updated Branches:
  refs/heads/master 969eb031f -> b2db2a2b5


Prototyping a code to make it much easier for confoidential client webapps to deal with OAuth2 authorization code flows


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

Branch: refs/heads/master
Commit: b2db2a2b5fa4ce39a5026731d5200881f5b0bf4a
Parents: 969eb03
Author: Sergey Beryozkin <sb...@talend.com>
Authored: Tue Dec 23 18:10:52 2014 +0000
Committer: Sergey Beryozkin <sb...@talend.com>
Committed: Tue Dec 23 18:10:52 2014 +0000

----------------------------------------------------------------------
 .../jose/jws/NoneJwsSignatureVerifier.java      |  35 ++++
 .../oauth2/client/ClientCodeRequest.java        |  56 ++++++
 .../ClientCodeRequestContextProvider.java       |  31 ++++
 .../oauth2/client/ClientCodeRequestFilter.java  | 174 +++++++++++++++++++
 .../client/ClientCodeRequestProvider.java       |  28 +++
 .../oauth2/client/ClientCodeStateProvider.java  |  32 ++++
 .../client/JoseClientCodeStateProvider.java     | 129 ++++++++++++++
 .../client/MemoryClientCodeRequestProvider.java |  50 ++++++
 .../client/MemoryClientCodeStateProvider.java   |  47 +++++
 9 files changed, 582 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/b2db2a2b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureVerifier.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureVerifier.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureVerifier.java
new file mode 100644
index 0000000..99cb770
--- /dev/null
+++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/NoneJwsSignatureVerifier.java
@@ -0,0 +1,35 @@
+/**
+ * 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 NoneJwsSignatureVerifier implements JwsSignatureVerifier {
+
+    @Override
+    public boolean verify(JoseHeaders headers, String unsignedText, byte[] signature) {
+        return headers.getAlgorithm().equals(getAlgorithm()) && signature.length == 0;
+    }
+
+    @Override
+    public String getAlgorithm() {
+        return "none";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/b2db2a2b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequest.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequest.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequest.java
new file mode 100644
index 0000000..0a5dd0b
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequest.java
@@ -0,0 +1,56 @@
+/**
+ * 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.client;
+
+import java.io.Serializable;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
+
+public class ClientCodeRequest implements Serializable {
+    private static final long serialVersionUID = -3501237730333195311L;
+    private ClientAccessToken token;
+    private MultivaluedMap<String, String> state;
+    private String userName;
+    
+    public ClientAccessToken getToken() {
+        return token;
+    }
+
+    public void setToken(ClientAccessToken token) {
+        this.token = token;
+    }
+
+    public MultivaluedMap<String, String> getState() {
+        return state;
+    }
+
+    public void setState(MultivaluedMap<String, String> state) {
+        this.state = state;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/b2db2a2b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestContextProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestContextProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestContextProvider.java
new file mode 100644
index 0000000..ee18e2c
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestContextProvider.java
@@ -0,0 +1,31 @@
+/**
+ * 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.client;
+
+import org.apache.cxf.jaxrs.ext.ContextProvider;
+import org.apache.cxf.message.Message;
+
+public class ClientCodeRequestContextProvider implements ContextProvider<ClientCodeRequest> {
+
+    @Override
+    public ClientCodeRequest createContext(Message m) {
+        return m.getContent(ClientCodeRequest.class);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/b2db2a2b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestFilter.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestFilter.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestFilter.java
new file mode 100644
index 0000000..663d37d
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestFilter.java
@@ -0,0 +1,174 @@
+/**
+ * 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.client;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+
+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.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.jaxrs.utils.ExceptionUtils;
+import org.apache.cxf.jaxrs.utils.FormUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant;
+import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
+import org.apache.cxf.rs.security.oauth2.grants.code.AuthorizationCodeGrant;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+
+@PreMatching
+@Priority(Priorities.AUTHENTICATION + 1)
+public class ClientCodeRequestFilter implements ContainerRequestFilter {
+
+    private String scopes;
+    private String relRedirectUri;
+    private String startUri;
+    private String authorizationServiceUri;
+    private Consumer consumer;
+    private ClientCodeStateProvider clientStateProvider;
+    private ClientCodeRequestProvider clientRequestProvider;
+    private WebClient accessTokenService;
+    
+    @Override
+    public void filter(ContainerRequestContext rc) throws IOException {
+        SecurityContext sc = rc.getSecurityContext();
+        if (sc == null || sc.getUserPrincipal() == null) {
+            throw ExceptionUtils.toNotAuthorizedException(null, null);
+        }
+        UriInfo ui = rc.getUriInfo();
+        if (ui.getPath().endsWith(startUri)) {
+            if (clientRequestProvider != null) {
+                ClientCodeRequest request = clientRequestProvider.getCodeRequest(sc, ui);
+                if (request != null) {
+                    setClientCodeRequest(request);
+                    rc.setRequestUri(URI.create(relRedirectUri));
+                    return;
+                }
+            }
+            Response codeResponse = createCodeResponse(rc, sc, ui);
+            rc.abortWith(codeResponse);
+        } else if (ui.getPath().endsWith(relRedirectUri)) {
+            processCodeResponse(rc, sc, ui);
+        }
+    }
+
+    private Response createCodeResponse(ContainerRequestContext rc, SecurityContext sc, UriInfo ui) {
+        URI uri = OAuthClientUtils.getAuthorizationURI(authorizationServiceUri, 
+                                             consumer.getKey(), 
+                                             getAbsoluteRedirectUri(ui).toString(), 
+                                             createRequestState(rc, sc, ui), 
+                                             scopes);
+        return Response.seeOther(uri).build();
+    }
+
+    private URI getAbsoluteRedirectUri(UriInfo ui) {
+        return ui.getBaseUriBuilder().path(relRedirectUri).build();
+    }
+    private void processCodeResponse(ContainerRequestContext rc, SecurityContext sc, UriInfo ui) {
+        MultivaluedMap<String, String> params = ui.getQueryParameters();
+        String codeParam = params.getFirst(OAuthConstants.AUTHORIZATION_CODE_VALUE);
+        AccessTokenGrant grant = new AuthorizationCodeGrant(codeParam, getAbsoluteRedirectUri(ui));
+        ClientAccessToken at = OAuthClientUtils.getAccessToken(accessTokenService, 
+                                                               consumer, 
+                                                               grant);
+        MultivaluedMap<String, String> state = null;
+        String stateParam = params.getFirst(OAuthConstants.STATE);
+        if (clientStateProvider != null) {
+            state = clientStateProvider.toState(sc, ui, stateParam);
+        }
+        ClientCodeRequest request = new ClientCodeRequest();
+        request.setToken(at);
+        request.setState(state);
+        request.setUserName(sc.getUserPrincipal().getName());
+        if (clientStateProvider != null) {
+            clientRequestProvider.setCodeRequest(sc, ui, request);
+        }
+        setClientCodeRequest(request);
+    }
+    
+    private void setClientCodeRequest(ClientCodeRequest request) {
+        JAXRSUtils.getCurrentMessage().setContent(ClientCodeRequest.class, request);
+    }
+
+    private String createRequestState(ContainerRequestContext rc, SecurityContext sc, UriInfo ui) {
+        if (clientStateProvider == null) {
+            return null;
+        }
+        MultivaluedMap<String, String> state = new MetadataMap<String, String>();
+        state.putAll(ui.getQueryParameters(false));
+        if (MediaType.APPLICATION_FORM_URLENCODED_TYPE.isCompatible(rc.getMediaType())) {
+            String body = FormUtils.readBody(rc.getEntityStream(), "UTF-8");
+            FormUtils.populateMapFromString(state, JAXRSUtils.getCurrentMessage(), body, "UTF-8", false);
+        }
+        return clientStateProvider.toString(sc, ui, state);
+    }
+
+    public void setScopeList(List<String> list) {
+        StringBuilder sb = new StringBuilder();
+        for (String s : list) {
+            if (sb.length() > 0) {
+                sb.append(" ");
+            }
+            sb.append(s);
+        }
+        setScopeString(sb.toString());
+    }
+    public void setScopeString(String scopesString) {
+        this.scopes = scopesString;
+    }
+
+    public void setStartUri(String startUri) {
+        this.startUri = startUri;
+    }
+
+    public void setAuthorizationServiceUri(String authorizationServiceUri) {
+        this.authorizationServiceUri = authorizationServiceUri;
+    }
+
+    public void setConsumer(Consumer consumer) {
+        this.consumer = consumer;
+    }
+
+    public void setRelativeRedirectUri(String redirectUri) {
+        this.relRedirectUri = redirectUri;
+    }
+
+    public void setAccessTokenService(WebClient accessTokenService) {
+        this.accessTokenService = accessTokenService;
+    }
+
+    public void setClientStateProvider(ClientCodeStateProvider clientStateProvider) {
+        this.clientStateProvider = clientStateProvider;
+    }
+    public void setClientRequestProvider(ClientCodeRequestProvider clientRequestProvider) {
+        this.clientRequestProvider = clientRequestProvider;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/b2db2a2b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestProvider.java
new file mode 100644
index 0000000..ec92d25
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeRequestProvider.java
@@ -0,0 +1,28 @@
+/**
+ * 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.client;
+
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+
+public interface ClientCodeRequestProvider {
+    void setCodeRequest(SecurityContext sc, UriInfo ui, ClientCodeRequest request);
+    ClientCodeRequest getCodeRequest(SecurityContext sc, UriInfo ui);
+    void removeCodeRequest(ClientCodeRequest request);
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/b2db2a2b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeStateProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeStateProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeStateProvider.java
new file mode 100644
index 0000000..d51e7b3
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/ClientCodeStateProvider.java
@@ -0,0 +1,32 @@
+/**
+ * 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.client;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+
+public interface ClientCodeStateProvider {
+    String toString(SecurityContext sc, 
+                    UriInfo ui,
+                    MultivaluedMap<String, String> state);
+    MultivaluedMap<String, String> toState(SecurityContext sc, 
+                                           UriInfo ui,
+                                           String stateParam);
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/b2db2a2b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/JoseClientCodeStateProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/JoseClientCodeStateProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/JoseClientCodeStateProvider.java
new file mode 100644
index 0000000..290d76e
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/JoseClientCodeStateProvider.java
@@ -0,0 +1,129 @@
+/**
+ * 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.client;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.jaxrs.provider.json.JsonMapObjectReaderWriter;
+import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider;
+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.JwsCompactConsumer;
+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.JwsSignatureVerifier;
+import org.apache.cxf.rs.security.jose.jws.JwsUtils;
+import org.apache.cxf.rs.security.jose.jws.NoneJwsSignatureProvider;
+
+public class JoseClientCodeStateProvider implements ClientCodeStateProvider {
+    
+    private JwsSignatureProvider sigProvider;
+    private JweEncryptionProvider encryptionProvider;
+    private JweDecryptionProvider decryptionProvider;
+    private JwsSignatureVerifier signatureVerifier;
+    private JsonMapObjectReaderWriter jsonp = new JsonMapObjectReaderWriter();
+    @Override
+    public String toString(SecurityContext sc, UriInfo ui,
+            MultivaluedMap<String, String> state) {
+        
+        Map<String, Object> stateMap = CastUtils.cast((Map<?, ?>)state);
+        String json = jsonp.toJson(stateMap);
+        
+        JwsCompactProducer producer = new JwsCompactProducer(json);
+        JwsSignatureProvider theSigProvider = getInitializedSigProvider();
+        String stateParam = producer.signWith(theSigProvider);
+        
+        JweEncryptionProvider theEncryptionProvider = getInitializedEncryptionProvider();
+        if (theEncryptionProvider != null) {
+            stateParam = theEncryptionProvider.encrypt(StringUtils.toBytesUTF8(stateParam), null);
+        }
+        return stateParam;
+    }
+
+    @Override
+    public MultivaluedMap<String, String> toState(SecurityContext sc,
+            UriInfo ui, String stateParam) {
+        
+        JweDecryptionProvider jwe = getInitializedDecryptionProvider();
+        if (jwe != null) {
+            stateParam = jwe.decrypt(stateParam).getContentText();
+        }
+        JwsCompactConsumer jws = new JwsCompactConsumer(stateParam);
+        JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier();
+        if (!jws.verifySignatureWith(theSigVerifier)) {
+            throw new SecurityException();
+        }
+        String json = jws.getUnsignedEncodedSequence();
+        Map<String, List<String>> map = CastUtils.cast((Map<?, ?>)jsonp.fromJson(json));
+        //CHECKSTYLE:OFF
+        return (MultivaluedMap<String, String>)map;
+        //CHECKSTYLE:ON
+    }
+    
+    public void setSignatureProvider(JwsSignatureProvider signatureProvider) {
+        this.sigProvider = signatureProvider;
+    }
+    
+    protected JwsSignatureProvider getInitializedSigProvider() {
+        if (sigProvider != null) {
+            return sigProvider;    
+        } 
+        JwsSignatureProvider theSigProvider = JwsUtils.loadSignatureProvider(false);
+        if (theSigProvider == null) {
+            theSigProvider = new NoneJwsSignatureProvider();
+        }
+        return theSigProvider;
+    }
+    public void setDecryptionProvider(JweDecryptionProvider decProvider) {
+        this.decryptionProvider = decProvider;
+    }
+    protected JweDecryptionProvider getInitializedDecryptionProvider() {
+        if (decryptionProvider != null) {
+            return decryptionProvider;    
+        } 
+        return JweUtils.loadDecryptionProvider(false);
+    }
+    public void setSignatureVerifier(JwsSignatureVerifier signatureVerifier) {
+        this.signatureVerifier = signatureVerifier;
+    }
+    
+    protected JwsSignatureVerifier getInitializedSigVerifier() {
+        if (signatureVerifier != null) {
+            return signatureVerifier;    
+        } 
+        return JwsUtils.loadSignatureVerifier(false);
+    }
+    public void setEncryptionProvider(JweEncryptionProvider encProvider) {
+        this.encryptionProvider = encProvider;
+    }
+    protected JweEncryptionProvider getInitializedEncryptionProvider() {
+        if (encryptionProvider != null) {
+            return encryptionProvider;    
+        } 
+        return JweUtils.loadEncryptionProvider(false);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/b2db2a2b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeRequestProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeRequestProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeRequestProvider.java
new file mode 100644
index 0000000..09412b0
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeRequestProvider.java
@@ -0,0 +1,50 @@
+/**
+ * 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.client;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+
+public class MemoryClientCodeRequestProvider implements ClientCodeRequestProvider {
+    private ConcurrentHashMap<String, ClientCodeRequest> map = 
+            new ConcurrentHashMap<String, ClientCodeRequest>();
+
+    @Override
+    public void setCodeRequest(SecurityContext sc, UriInfo ui, ClientCodeRequest request) {
+        map.put(getKey(sc), request);
+        
+    }
+
+    private String getKey(SecurityContext sc) {
+        return sc.getUserPrincipal().getName();
+    }
+
+    @Override
+    public ClientCodeRequest getCodeRequest(SecurityContext sc, UriInfo ui) {
+        // TODO: support an automatic removal based on the token expires property
+        return map.remove(getKey(sc));
+    }
+
+    @Override
+    public void removeCodeRequest(ClientCodeRequest request) {
+        map.remove(request.getUserName());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/b2db2a2b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeStateProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeStateProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeStateProvider.java
new file mode 100644
index 0000000..ecc147b
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeStateProvider.java
@@ -0,0 +1,47 @@
+/**
+ * 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.client;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+
+public class MemoryClientCodeStateProvider implements ClientCodeStateProvider {
+    private ConcurrentHashMap<String, MultivaluedMap<String, String>> map = 
+            new ConcurrentHashMap<String, MultivaluedMap<String, String>>();
+    
+    @Override
+    public String toString(SecurityContext sc, UriInfo ui,
+            MultivaluedMap<String, String> state) {
+        String name = sc.getUserPrincipal().getName();
+        String hashCode = Integer.toString(name.hashCode());
+        map.put(hashCode, state);
+        return hashCode;
+    }
+
+    @Override
+    public MultivaluedMap<String, String> toState(SecurityContext sc,
+            UriInfo ui, String stateParam) {
+        String name = sc.getUserPrincipal().getName();
+        String hashCode = Integer.toString(name.hashCode());
+        return map.remove(hashCode);
+    }
+}