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 2013/02/21 16:57:25 UTC

svn commit: r1448696 [1/2] - in /cxf/trunk: rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ rt/rs/security/oauth-parent/ rt/rs/security/oauth-parent/oauth2-saml/ rt/rs/security/...

Author: sergeyb
Date: Thu Feb 21 15:57:24 2013
New Revision: 1448696

URL: http://svn.apache.org/r1448696
Log:
[CXF-4828] Support for OAuth2 SAML2 grants and authentication

Added:
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/pom.xml   (with props)
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthHandler.java   (with props)
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthOutInterceptor.java   (with props)
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrant.java   (with props)
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java   (with props)
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/SamlUserSubject.java   (with props)
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Base64UrlUtility.java   (with props)
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Constants.java   (with props)
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/SamlOAuthValidator.java   (with props)
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/test/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/test/java/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/test/java/org/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/test/java/org/apache/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/test/java/org/apache/cxf/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/test/java/org/apache/cxf/rs/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/test/java/org/apache/cxf/rs/security/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/test/java/org/apache/cxf/rs/security/oauth2/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/test/java/org/apache/cxf/rs/security/oauth2/grants/
    cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/test/java/org/apache/cxf/rs/security/oauth2/grants/saml/
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/BookServerOAuth2.java   (with props)
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/CustomGrantHandler.java   (with props)
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java   (with props)
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/OAuthDataProviderImpl.java   (with props)
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/SamlCallbackHandler.java   (with props)
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/SamlCallbackHandler2.java   (with props)
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/client.xml   (with props)
    cxf/trunk/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/server.xml   (with props)
Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/OAuthClientUtils.java
    cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/owner/ResourceOwnerGrant.java
    cxf/trunk/rt/rs/security/oauth-parent/pom.xml
    cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/CryptoLoader.java
    cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java
    cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SAMLUtils.java
    cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SamlFormInHandler.java
    cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SamlFormOutInterceptor.java
    cxf/trunk/systests/rs-security/pom.xml

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java?rev=1448696&r1=1448695&r2=1448696&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/FormEncodingProvider.java Thu Feb 21 15:57:24 2013
@@ -63,6 +63,14 @@ public class FormEncodingProvider<T> imp
 
     private boolean expectEncoded;
     
+    public FormEncodingProvider() {
+        
+    }
+    
+    public FormEncodingProvider(boolean expectEncoded) {
+        this.expectEncoded = expectEncoded;
+    }
+    
     public void setExpectedEncoded(boolean expect) {
         this.expectEncoded = expect;
     }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java?rev=1448696&r1=1448695&r2=1448696&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/FormUtils.java Thu Feb 21 15:57:24 2013
@@ -23,6 +23,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.lang.annotation.Annotation;
 import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.Iterator;
@@ -34,15 +35,20 @@ import javax.servlet.http.HttpServletReq
 import javax.ws.rs.BadRequestException;
 import javax.ws.rs.InternalServerErrorException;
 import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.interceptor.LoggingInInterceptor;
+import org.apache.cxf.io.CachedOutputStream;
+import org.apache.cxf.jaxrs.ext.form.Form;
 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
 import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition;
 import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.jaxrs.provider.FormEncodingProvider;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.PhaseInterceptorChain;
 
@@ -57,6 +63,30 @@ public final class FormUtils {
         
     }
     
+    public static void restoreForm(FormEncodingProvider<Form> provider, 
+                                   Form form, 
+                                   Message message)
+        throws Exception {
+        CachedOutputStream os = new CachedOutputStream();
+        writeForm(provider, form, os);
+        message.setContent(InputStream.class, os.getInputStream());
+    }
+    
+    public static void writeForm(FormEncodingProvider<Form> provider, 
+                                 Form form, OutputStream os)
+        throws Exception {
+        provider.writeTo(form, Form.class, Form.class, new Annotation[]{}, 
+                         MediaType.APPLICATION_FORM_URLENCODED_TYPE, new MetadataMap<String, Object>(), os);
+    }
+    
+    public static Form readForm(FormEncodingProvider<Form> provider, Message message) 
+        throws Exception {
+        return provider.readFrom(Form.class, Form.class, 
+                              new Annotation[]{}, MediaType.APPLICATION_FORM_URLENCODED_TYPE, 
+                              new MetadataMap<String, String>(), 
+                              message.getContent(InputStream.class));
+    }
+    
     public static void addPropertyToForm(MultivaluedMap<String, String> map, String name, Object value) {
         if (!"".equals(name)) {
             map.add(name, value.toString());

Added: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/pom.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/pom.xml?rev=1448696&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/pom.xml (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/pom.xml Thu Feb 21 15:57:24 2013
@@ -0,0 +1,62 @@
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.cxf</groupId>
+    <artifactId>cxf-rt-rs-security-oauth2-saml</artifactId>
+    <version>2.8.0-SNAPSHOT</version>
+
+    <packaging>jar</packaging>
+    <name>Apache CXF Runtime OAuth 2.0 SAML</name>
+    <description>Apache CXF Runtime OAuth 2.0 SAML</description>
+    <url>http://cxf.apache.org</url>
+
+    <parent>
+        <artifactId>cxf-rt-rs-security-oauth-parent</artifactId>
+        <groupId>org.apache.cxf</groupId>
+        <version>2.8.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-rs-security-oauth2</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-rs-security-xml</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!--test dependencies-->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>  
+    </dependencies>
+    
+</project>

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthHandler.java?rev=1448696&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthHandler.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthHandler.java Thu Feb 21 15:57:24 2013
@@ -0,0 +1,131 @@
+/**
+ * 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.auth.saml;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import javax.ws.rs.NotAuthorizedException;
+import javax.ws.rs.core.Response;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.util.Base64Exception;
+import org.apache.cxf.jaxrs.ext.form.Form;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.provider.FormEncodingProvider;
+import org.apache.cxf.jaxrs.utils.FormUtils;
+import org.apache.cxf.jaxrs.utils.HttpUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.rs.security.oauth2.saml.Base64UrlUtility;
+import org.apache.cxf.rs.security.oauth2.saml.Constants;
+import org.apache.cxf.rs.security.oauth2.saml.SamlOAuthValidator;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.rs.security.saml.AbstractSamlInHandler;
+import org.apache.cxf.rs.security.saml.SAMLUtils;
+import org.apache.cxf.rs.security.saml.assertion.Subject;
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+
+public class Saml2BearerAuthHandler extends AbstractSamlInHandler {
+    private FormEncodingProvider<Form> provider = new FormEncodingProvider<Form>(true);
+    private SamlOAuthValidator samlOAuthValidator = new SamlOAuthValidator();
+    
+    public Saml2BearerAuthHandler() {
+    }
+    
+    public void setSamlOAuthValidator(SamlOAuthValidator validator) {
+        samlOAuthValidator = validator;
+    }
+    
+    public Response handleRequest(Message message, ClassResourceInfo resourceClass) {
+        
+        Form form = readFormData(message);    
+        String assertionType = form.getData().getFirst(Constants.CLIENT_AUTH_ASSERTION_TYPE);
+        String decodedAssertionType = assertionType != null ? HttpUtils.urlDecode(assertionType) : null;
+        if (decodedAssertionType == null || !Constants.CLIENT_AUTH_SAML2_BEARER.equals(decodedAssertionType)) {
+            throw new NotAuthorizedException(errorResponse());
+        }
+        String assertion = form.getData().getFirst(Constants.CLIENT_AUTH_ASSERTION_PARAM);
+        
+        Element token = readToken(message, assertion);         
+        String clientId = form.getData().getFirst(OAuthConstants.CLIENT_ID);
+        validateToken(message, token, clientId);
+        
+        
+        form.getData().remove(OAuthConstants.CLIENT_ID);
+        form.getData().remove(Constants.CLIENT_AUTH_ASSERTION_PARAM);
+        form.getData().remove(Constants.CLIENT_AUTH_ASSERTION_TYPE);
+        
+        // restore input stream
+        try {
+            FormUtils.restoreForm(provider, form, message);
+        } catch (Exception ex) {
+            throw new NotAuthorizedException(errorResponse());
+        }
+        return null;
+    }
+    
+    private Form readFormData(Message message) {
+        try {
+            return FormUtils.readForm(provider, message);
+        } catch (Exception ex) {
+            throw new NotAuthorizedException(errorResponse());    
+        }
+    }
+    
+    protected Element readToken(Message message, String assertion) {
+        if (assertion == null) {
+            throw new NotAuthorizedException(errorResponse());
+        }
+        try {
+            byte[] deflatedToken = Base64UrlUtility.decode(assertion);
+            InputStream is = new ByteArrayInputStream(deflatedToken); 
+            return readToken(message, is); 
+        } catch (Base64Exception ex) {
+            throw new NotAuthorizedException(errorResponse());
+        }         
+    }
+    
+    protected void validateToken(Message message, Element element, String clientId) {
+        
+        AssertionWrapper wrapper = toWrapper(element);
+        // The common SAML assertion validation:
+        // signature, subject confirmation, etc
+        super.validateToken(message, wrapper);
+        
+        // This is specific to OAuth2 path
+        // Introduce SAMLOAuth2Validator to be reused between auth and grant handlers
+        Subject subject = SAMLUtils.getSubject(message, wrapper);
+        if (subject.getName() == null) {
+            throw new NotAuthorizedException(errorResponse());  
+        }
+        
+        if (clientId != null && !clientId.equals(subject.getName())) {
+            //TODO:  Attempt to map client_id to subject.getName()
+            throw new NotAuthorizedException(errorResponse());
+        }
+        samlOAuthValidator.validate(message, wrapper);
+        message.put(OAuthConstants.CLIENT_ID, subject.getName());
+    }
+    
+    private static Response errorResponse() {
+        return Response.status(401).build();
+    }
+}

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthHandler.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthOutInterceptor.java?rev=1448696&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthOutInterceptor.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthOutInterceptor.java Thu Feb 21 15:57:24 2013
@@ -0,0 +1,39 @@
+/**
+ * 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.auth.saml;
+
+import org.apache.cxf.common.util.Base64Exception;
+import org.apache.cxf.jaxrs.ext.form.Form;
+import org.apache.cxf.rs.security.oauth2.saml.Base64UrlUtility;
+import org.apache.cxf.rs.security.oauth2.saml.Constants;
+import org.apache.cxf.rs.security.saml.SamlFormOutInterceptor;
+
+public class Saml2BearerAuthOutInterceptor extends SamlFormOutInterceptor {
+
+    @Override
+    protected void updateForm(Form form, String encodedToken) {
+        form.set(Constants.CLIENT_AUTH_ASSERTION_TYPE, Constants.CLIENT_AUTH_SAML2_BEARER);
+        form.set(Constants.CLIENT_AUTH_ASSERTION_PARAM, encodedToken);
+    }
+    
+    @Override
+    protected String encodeToken(String token) throws Base64Exception {
+        return Base64UrlUtility.encode(token);
+    }
+}

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthOutInterceptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/auth/saml/Saml2BearerAuthOutInterceptor.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrant.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrant.java?rev=1448696&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrant.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrant.java Thu Feb 21 15:57:24 2013
@@ -0,0 +1,78 @@
+/**
+ * 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.grants.saml;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+import org.apache.cxf.rs.security.oauth2.saml.Base64UrlUtility;
+import org.apache.cxf.rs.security.oauth2.saml.Constants;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+
+public class Saml2BearerGrant implements AccessTokenGrant {
+    private String assertion;
+    private String scope;
+    private boolean encoded; 
+    
+    public Saml2BearerGrant(String assertion) {
+        this(assertion, false);
+    }
+    
+    public Saml2BearerGrant(String assertion, boolean encoded) {
+        this(assertion, false, null);
+    }
+    
+    public Saml2BearerGrant(String assertion, String scope) {
+        this(assertion, false, scope);
+    }
+    
+    public Saml2BearerGrant(String assertion, boolean encoded, String scope) {
+        this.assertion = assertion;
+        this.encoded = encoded;
+        this.scope = scope;
+    }
+    
+    public String getType() {
+        return Constants.SAML2_BEARER_GRANT;
+    }
+
+    public MultivaluedMap<String, String> toMap() {
+        MultivaluedMap<String, String> map = new MetadataMap<String, String>();
+        map.putSingle(OAuthConstants.GRANT_TYPE, Constants.SAML2_BEARER_GRANT);
+        map.putSingle(Constants.CLIENT_GRANT_ASSERTION_PARAM, encodeAssertion());
+        if (scope != null) {
+            map.putSingle(OAuthConstants.SCOPE, scope);
+        }
+        return map;
+    }
+
+    protected String encodeAssertion() {
+        if (encoded) {
+            return assertion;
+        }
+        
+        try {
+            return Base64UrlUtility.encode(assertion);
+        } catch (Exception ex) {
+            throw new OAuthServiceException(ex.getMessage(), ex);
+        }
+    }
+}

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrant.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrant.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java?rev=1448696&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java Thu Feb 21 15:57:24 2013
@@ -0,0 +1,220 @@
+/**
+ * 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.grants.saml;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.security.Principal;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.util.Base64Exception;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.jaxrs.utils.HttpUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageUtils;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.apache.cxf.rs.security.common.CryptoLoader;
+import org.apache.cxf.rs.security.common.SecurityUtils;
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
+import org.apache.cxf.rs.security.oauth2.grants.AbstractGrantHandler;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+import org.apache.cxf.rs.security.oauth2.saml.Base64UrlUtility;
+import org.apache.cxf.rs.security.oauth2.saml.Constants;
+import org.apache.cxf.rs.security.oauth2.saml.SamlOAuthValidator;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
+import org.apache.cxf.rs.security.saml.authorization.JAXRSSAMLSecurityContext;
+import org.apache.cxf.rs.security.saml.authorization.SecurityContextProvider;
+import org.apache.cxf.rs.security.saml.authorization.SecurityContextProviderImpl;
+import org.apache.cxf.security.SecurityContext;
+import org.apache.cxf.security.transport.TLSSessionInfo;
+import org.apache.cxf.ws.security.SecurityConstants;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+import org.apache.ws.security.validate.Credential;
+import org.apache.ws.security.validate.SamlAssertionValidator;
+import org.apache.ws.security.validate.Validator;
+
+/**
+ * The "SAML2 Bearer" grant handler
+ */
+public class Saml2BearerGrantHandler extends AbstractGrantHandler {
+    private static final String ENCODED_SAML2_BEARER_GRANT;
+    static {
+        WSSConfig.init();
+        ENCODED_SAML2_BEARER_GRANT = HttpUtils.urlEncode(Constants.SAML2_BEARER_GRANT, "UTF-8");
+    }
+    private Validator samlValidator = new SamlAssertionValidator();
+    private SamlOAuthValidator samlOAuthValidator = new SamlOAuthValidator(); 
+    private SecurityContextProvider scProvider = new SecurityContextProviderImpl(); 
+    
+    public Saml2BearerGrantHandler() {
+        super(Constants.SAML2_BEARER_GRANT, true);
+    }
+    
+    @Override
+    public List<String> getSupportedGrantTypes() {
+        // AccessTokenService may be configured with the form provider
+        // which will not decode by default - so listing both the actual 
+        // and encoded grant type value will help
+        List<String> types = new LinkedList<String>();
+        types.add(Constants.SAML2_BEARER_GRANT);
+        types.add(ENCODED_SAML2_BEARER_GRANT);
+        return types;
+    }
+
+    public void setSamlValidator(Validator validator) {
+        samlValidator = validator;
+    }
+    
+    public void setSamlOAuthValidator(SamlOAuthValidator validator) {
+        samlOAuthValidator = validator;
+    }
+    
+    public void setSecurityContextProvider(SecurityContextProvider p) {
+        scProvider = p;
+    }
+    
+    public ServerAccessToken createAccessToken(Client client, MultivaluedMap<String, String> params)
+        throws OAuthServiceException {
+        checkIfGrantSupported(client);
+        
+        String assertion = params.getFirst(Constants.CLIENT_GRANT_ASSERTION_PARAM);
+        if (assertion == null) {
+            throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
+        }
+        try {   
+            InputStream tokenStream = decodeAssertion(assertion);
+            Element token = readToken(tokenStream);
+            AssertionWrapper assertionWrapper = new AssertionWrapper(token);
+            
+            Message message = PhaseInterceptorChain.getCurrentMessage();
+    
+            validateToken(message, assertionWrapper);
+            UserSubject grantSubject = getGrantSubject(message, assertionWrapper);
+            
+            return doCreateAccessToken(client, 
+                                       grantSubject, 
+                                       OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE)));
+        } catch (OAuthServiceException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new OAuthServiceException(OAuthConstants.INVALID_GRANT, ex);
+        }
+    }
+
+    protected UserSubject getGrantSubject(Message message, AssertionWrapper wrapper) {
+        SecurityContext sc = scProvider.getSecurityContext(message, wrapper);
+        if (sc instanceof JAXRSSAMLSecurityContext) {
+            JAXRSSAMLSecurityContext jaxrsSc = (JAXRSSAMLSecurityContext)sc;
+            Set<Principal> rolesP = jaxrsSc.getUserRoles();
+            List<String> roles = new ArrayList<String>();
+            if (roles != null) {
+                for (Principal p : rolesP) {
+                    roles.add(p.getName());
+                }
+            }
+            return new SamlUserSubject(jaxrsSc.getUserPrincipal().getName(), 
+                                       roles,
+                                       jaxrsSc.getClaims());
+        } else {
+            return new UserSubject(sc.getUserPrincipal().getName());
+        }
+        
+    }
+    
+    private InputStream decodeAssertion(String assertion) {
+        try {
+            byte[] deflatedToken = Base64UrlUtility.decode(assertion);
+            return new ByteArrayInputStream(deflatedToken); 
+        } catch (Base64Exception ex) {
+            throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
+        }   
+    }
+    
+
+    protected Element readToken(InputStream tokenStream) {
+        
+        try {
+            Document doc = DOMUtils.readXml(new InputStreamReader(tokenStream, "UTF-8"));
+            return doc.getDocumentElement();
+        } catch (Exception ex) {
+            throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
+        }
+    }
+
+    protected void validateToken(Message message, AssertionWrapper assertion) {
+        try {
+            RequestData data = new RequestData();
+            if (assertion.isSigned()) {
+                WSSConfig cfg = WSSConfig.getNewInstance(); 
+                data.setWssConfig(cfg);
+                data.setCallbackHandler(SecurityUtils.getCallbackHandler(message, this.getClass()));
+                try {
+                    data.setSigCrypto(new CryptoLoader().getCrypto(message,
+                                                SecurityConstants.SIGNATURE_CRYPTO,
+                                                SecurityConstants.SIGNATURE_PROPERTIES));
+                } catch (IOException ex) {
+                    throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
+                }
+                data.setEnableRevocation(MessageUtils.isTrue(
+                    message.getContextualProperty(WSHandlerConstants.ENABLE_REVOCATION)));
+                assertion.verifySignature(data, null);
+            } else if (getTLSCertificates(message) == null) {
+                throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
+            }
+            
+            if (samlValidator != null) {
+                Credential credential = new Credential();
+                credential.setAssertion(assertion);
+                samlValidator.validate(credential, data);
+            }
+            samlOAuthValidator.validate(message, assertion);
+        } catch (Exception ex) {
+            throw new OAuthServiceException(OAuthConstants.INVALID_GRANT, ex);
+        }
+    }
+    
+    private Certificate[] getTLSCertificates(Message message) {
+        TLSSessionInfo tlsInfo = message.get(TLSSessionInfo.class);
+        return tlsInfo != null ? tlsInfo.getPeerCertificates() : null;
+    }
+    
+    protected void setSecurityContext(Message message, AssertionWrapper wrapper) {
+        if (scProvider != null) {
+            SecurityContext sc = scProvider.getSecurityContext(message, wrapper);
+            message.put(SecurityContext.class, sc);
+        }
+    }
+}

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/Saml2BearerGrantHandler.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/SamlUserSubject.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/SamlUserSubject.java?rev=1448696&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/SamlUserSubject.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/SamlUserSubject.java Thu Feb 21 15:57:24 2013
@@ -0,0 +1,37 @@
+/**
+ * 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.grants.saml;
+
+import java.util.List;
+
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
+import org.apache.cxf.rs.security.saml.assertion.Claims;
+
+public class SamlUserSubject extends UserSubject {
+    private Claims claims;
+    public SamlUserSubject(String user, 
+                           List<String> roles,
+                           Claims claims) {
+        super(user, roles);
+        this.claims = claims;
+    }
+    public Claims getClaims() {
+        return claims;
+    }
+}

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/SamlUserSubject.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/grants/saml/SamlUserSubject.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Base64UrlUtility.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Base64UrlUtility.java?rev=1448696&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Base64UrlUtility.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Base64UrlUtility.java Thu Feb 21 15:57:24 2013
@@ -0,0 +1,380 @@
+/**
+ * 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.saml;
+
+/**
+ * Base64 URL Encoding/Decoding utility (character 62 is '-', 63 - '_')
+ * TODO: 
+ *  - encoding: exclude padding characters by default, 
+ *  - decoding: calculate a number of missing padding characters 
+ *    based on a number of base64url encoded octets
+ *    
+ *  - once the above two points are addressed, consider extracting 
+ *    most of Base64Utility into Base64EncoderDecoder and extending it
+ *    with Base64UrlEncoderDecoder to minimize the duplication 
+ *                  
+ */
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.i18n.Message;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.Base64Exception;
+
+
+public final class Base64UrlUtility {
+    
+    private static final Logger LOG = LogUtils.getL7dLogger(Base64UrlUtility.class);
+
+    private static final String ENCODED_PAD = "%3D";
+        
+    // Base 64 URL character set
+    //
+    private static final char[] BCS = {
+        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 
+        'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 
+        'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 
+        'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 
+        'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 
+        'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', 
+        '8', '9', '-', '_'
+    };
+
+    // base 64 wadding
+    private static final char PAD = '=';
+
+    // size of base 64 decode table
+    private static final int BDTSIZE = 128;
+
+    // base 64 decode table  
+    private static final byte[] BDT = new byte[128];
+
+    
+    private static final int PAD_SIZE0 = 1;
+    private static final int PAD_SIZE4 = 2;
+    private static final int PAD_SIZE8 = 3;
+    
+    // class static intializer for building decode table
+    static {
+        for (int i = 0;  i < BDTSIZE;  i++) {
+            BDT[i] = Byte.MAX_VALUE;
+        }
+
+        for (int i = 0;  i < BCS.length;  i++) {
+            BDT[BCS[i]] = (byte)i;
+        }
+    }
+    
+    
+    private Base64UrlUtility() {
+        //utility class, never constructed
+    }
+    
+    /**
+     * The <code>decode_chunk</code> routine decodes a chunk of data
+     * into its native encoding.
+     *
+     * base64 encodes each 3 octets of data into 4 characters from a
+     * limited 64 character set. The 3 octets are joined to form
+     * 24 bits which are then split into 4 x 6bit values. Each 6 bit
+     * value is then used as an index into the 64 character table of
+     * base64 chars. If the total data length is not a 3 octet multiple
+     * the '=' char is used as padding for the final 4 char group, 
+     * either 1 octet + '==' or 2 octets + '='.
+     *
+     * @param   id  The input data to be processed
+     * @param   o   The offset from which to begin processing
+     * @param   l   The length (bound) at which processing is to end
+     * @return  The decoded data   
+     * @exception   Base64Exception Thrown is processing fails due to
+     * formatting exceptions in the encoded data 
+     */
+    public static byte[] decodeChunk(char[] id,
+                                     int o,
+                                     int l) 
+        throws Base64Exception {
+        
+        // Keep it simple - must be >= 4. Unpadded
+        // base64 data contain < 3 octets is invalid.
+        //
+        if ((l - o) < 4) {
+            return null;
+        }
+
+        char[] ib = new char[4];
+        int ibcount = 0;
+
+        // cryan. Calc the num of octets. Each 4 chars of base64 chars
+        // (representing 24 bits) encodes 3 octets. 
+        //
+        int octetCount = 3 * (l / 4);
+
+        // Final 4 chars may contain 3 octets or padded to contain
+        // 1 or 2 octets.
+        //
+        if (id[l - 1] == PAD) {
+            // TT== means last 4 chars encode 8 bits (ie subtract 2)
+            // TTT= means last 4 chars encode 16 bits (ie subtract 1)
+            octetCount -= (id[l - 2] == PAD) ? 2 : 1;
+        }
+
+        byte[] ob = new byte[octetCount];
+        int obcount = 0;
+
+        for (int i = o;  i < o + l && i < id.length;  i++) {
+            if (id[i] == PAD
+                || id[i] < BDT.length
+                && BDT[id[i]] != Byte.MAX_VALUE) {
+                
+                ib[ibcount++] = id[i];
+
+                // Decode each 4 char sequence.
+                //
+                if (ibcount == ib.length) {
+                    ibcount = 0;
+                    obcount += processEncodeme(ib, ob, obcount);
+                }
+            }
+        }
+        
+        if (obcount != ob.length) {
+            byte []tmp = new byte[obcount];
+            System.arraycopy(ob, 0, tmp, 0, obcount);
+            ob = tmp;
+        }
+
+        return ob;
+    }
+
+    public static byte[] decode(String id) throws Base64Exception {
+        int count = 0;
+        while (id.endsWith(ENCODED_PAD)) {
+            id = id.substring(0, id.length() - ENCODED_PAD.length());
+            count++;
+        }
+        for (int i = 0; i < count; i++) {
+            id += PAD;
+        }
+        
+        try {
+            char[] cd = id.toCharArray();
+            return decodeChunk(cd, 0, cd.length);
+        } catch (Exception e) {
+            LOG.warning("Invalid base64 encoded string : " + id);
+            throw new Base64Exception(new Message("BASE64_RUNTIME_EXCEPTION", LOG), e);
+        }
+    }
+
+    public static void decode(char[] id,
+                             int o,
+                             int l,
+                             OutputStream ostream) 
+        throws Base64Exception {
+
+        try {
+            ostream.write(decodeChunk(id, o, l));
+        } catch (Exception e) {
+            LOG.warning("Invalid base64 encoded string : " + new String(id));
+            throw new Base64Exception(new Message("BASE64_RUNTIME_EXCEPTION", LOG), e);
+        }
+    }
+
+    public static void decode(String id,
+                              OutputStream ostream) 
+        throws Base64Exception {
+        
+        try {
+            char[] cd = id.toCharArray();
+            ostream.write(decodeChunk(cd, 0, cd.length));
+        } catch (IOException ioe) {
+            throw new Base64Exception(new Message("BASE64_DECODE_IOEXCEPTION", LOG), ioe);
+        } catch (Exception e) {
+            LOG.warning("Invalid base64 encoded string : " + id);
+            throw new Base64Exception(new Message("BASE64_RUNTIME_EXCEPTION", LOG), e);
+        }
+    }
+
+    // Returns base64 representation of specified byte array.
+    //
+    public static String encode(byte[] id) {
+        char[] cd = encodeChunk(id, 0, id.length);
+        return new String(cd, 0, cd.length);
+    }
+
+    // Returns base64 representation of specified byte array.
+    //
+    public static char[] encodeChunk(byte[] id,
+                                     int o,
+                                     int l) {
+        if (l <= 0) {
+            return null;
+        }
+
+        char[] out;
+
+        // If not a multiple of 3 octets then a final padded 4 char
+        // slot is needed.
+        //
+        if ((l - o) % 3 == 0) {
+            out = new char[l / 3 * 4];
+        } else {
+            out = new char[l / 3 * 4 + 4];
+        }
+
+        int rindex = o;
+        int windex = 0;
+        int rest = l - o;
+
+        while (rest >= 3) {
+            int i = ((id[rindex] & 0xff) << 16)
+                    + ((id[rindex + 1] & 0xff) << 8)
+                    + (id[rindex + 2] & 0xff);
+
+            out[windex++] = BCS[i >> 18];
+            out[windex++] = BCS[(i >> 12) & 0x3f];
+            out[windex++] = BCS[(i >> 6) & 0x3f];
+            out[windex++] = BCS[i & 0x3f];
+            rindex += 3;
+            rest -= 3;
+        }
+
+        if (rest == 1) {
+            int i = id[rindex] & 0xff;
+            out[windex++] = BCS[i >> 2];
+            out[windex++] = BCS[(i << 4) & 0x3f];
+            out[windex++] = PAD;
+            out[windex++] = PAD;
+        } else if (rest == 2) {
+            int i = ((id[rindex] & 0xff) << 8) + (id[rindex + 1] & 0xff);
+            out[windex++] = BCS[i >> 10];
+            out[windex++] = BCS[(i >> 4) & 0x3f];
+            out[windex++] = BCS[(i << 2) & 0x3f];
+            out[windex++] = PAD;
+        }
+        return out;
+    }
+
+    //
+    // Outputs base64 representation of the specified byte array 
+    // to a byte stream.
+    //
+    public static void encodeChunk(byte[] id,
+                                   int o,
+                                   int l,
+                                   OutputStream ostream) throws Base64Exception {
+        try {
+            ostream.write(new String(encodeChunk(id, o, l)).getBytes());
+        } catch (IOException e) {
+            throw new Base64Exception(new Message("BASE64_ENCODE_IOEXCEPTION", LOG), e);
+        }
+    }
+
+    public static String encode(String value) throws Base64Exception {
+        StringWriter writer = new StringWriter();
+        Base64UrlUtility.encode(value, writer);
+        return writer.toString();
+    }
+    
+    public static void encode(String value, Writer writer) throws Base64Exception {
+        byte[] chunk = null;
+        try {
+            chunk = value.getBytes("UTF-8");
+        } catch (UnsupportedEncodingException ex) {
+            // won't happen
+        }
+        Base64UrlUtility.encode(chunk, 0, chunk.length, writer);
+        
+    }
+    
+
+    // Outputs base64 representation of the specified byte 
+    // array to a character stream.
+    //
+    public static void encode(byte[] id,
+                              int o,
+                              int l,
+                              Writer writer) throws Base64Exception {
+        try {
+            writer.write(encodeChunk(id, o, l));
+        } catch (IOException e) {
+            throw new Base64Exception(new Message("BASE64_ENCODE_WRITER_IOEXCEPTION", LOG), e);
+        }
+    }
+
+
+    //---- Private static methods --------------------------------------
+
+    /**
+     * The <code>process</code> routine processes an atomic base64
+     * unit of encoding (encodeme) into its native encoding. This class is
+     * used by decode routines to do the grunt work of decoding
+     * base64 encoded information
+     *
+     * @param   ib  Input character buffer of encoded bytes
+     * @param   ob  Output byte buffer of decoded bytes
+     * @param   p   Pointer to the encodeme of interest
+     * @return  The decoded encodeme
+     * @exception   Base64Exception Thrown is processing fails due to
+     * formatting exceptions in the encoded data 
+     */ 
+    private static int processEncodeme(char[] ib,
+                                       byte[] ob,
+                                       int p) 
+        throws Base64Exception {
+        
+
+        int spad = PAD_SIZE8;        
+        if (ib[3] == PAD) {
+            spad = PAD_SIZE4;
+        }
+        if (ib[2] == PAD) {
+            spad = PAD_SIZE0;
+        }
+
+        int b0 = BDT[ib[0]];
+        int b1 = BDT[ib[1]];
+        int b2 = BDT[ib[2]];
+        int b3 = BDT[ib[3]];
+
+        switch (spad) {
+        case PAD_SIZE0:
+            ob[p] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3);
+            return PAD_SIZE0;
+        case PAD_SIZE4:
+            ob[p++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3);
+            ob[p] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf);
+            return PAD_SIZE4;
+        case PAD_SIZE8:
+            ob[p++] = (byte)(b0 << 2 & 0xfc | b1 >> 4 & 0x3);
+            ob[p++] = (byte)(b1 << 4 & 0xf0 | b2 >> 2 & 0xf);
+            ob[p] = (byte)(b2 << 6 & 0xc0 | b3 & 0x3f);
+            return PAD_SIZE8;
+        default:
+            // We should never get here
+            throw new IllegalStateException();
+        } 
+    } 
+
+}

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Base64UrlUtility.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Base64UrlUtility.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Constants.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Constants.java?rev=1448696&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Constants.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Constants.java Thu Feb 21 15:57:24 2013
@@ -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.oauth2.saml;
+
+public final class Constants {
+    public static final String SAML2_BEARER_GRANT =
+        "urn:ietf:params:oauth:grant-type:saml2-bearer";
+    public static final String CLIENT_GRANT_ASSERTION_PARAM = "assertion";
+    
+    public static final String CLIENT_AUTH_ASSERTION_PARAM = "client_assertion";
+    public static final String CLIENT_AUTH_ASSERTION_TYPE = "client_assertion_type";
+    public static final String CLIENT_AUTH_SAML2_BEARER = 
+        "urn:ietf:params:oauth:client-assertion-type:saml2-bearer";
+   
+    
+    private Constants() {
+        
+    }
+}

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Constants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/Constants.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/SamlOAuthValidator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/SamlOAuthValidator.java?rev=1448696&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/SamlOAuthValidator.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/SamlOAuthValidator.java Thu Feb 21 15:57:24 2013
@@ -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.saml;
+
+import java.util.List;
+
+import javax.ws.rs.NotAuthorizedException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import org.apache.cxf.jaxrs.impl.UriInfoImpl;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+import org.apache.ws.security.saml.ext.builder.SAML2Constants;
+import org.opensaml.saml2.core.Audience;
+import org.opensaml.saml2.core.AudienceRestriction;
+import org.opensaml.saml2.core.Conditions;
+import org.opensaml.saml2.core.Issuer;
+import org.opensaml.saml2.core.SubjectConfirmation;
+import org.opensaml.saml2.core.SubjectConfirmationData;
+
+public class SamlOAuthValidator {
+    private String accessTokenServiceAddress;
+    private String issuer;
+    private String clientAddress;
+    private boolean subjectConfirmationDataRequired;
+    public SamlOAuthValidator() {
+    }
+    
+    
+    public void setSubjectConfirmationDataRequired(boolean required) {
+        subjectConfirmationDataRequired = required;
+    }
+    
+    public void setAccessTokenServiceAddress(String address) {
+        accessTokenServiceAddress = address;
+    }
+    
+    public void setIssuer(String value) {
+        issuer = value;
+    }
+    
+    public void setClientAddress(String value) {
+        issuer = value;
+    }
+    
+    public void validate(Message message, AssertionWrapper wrapper) {
+        
+        Conditions cs = wrapper.getSaml2().getConditions();
+        validateAudience(message, cs);
+        
+        if (issuer != null) {
+            String actualIssuer = getIssuer(wrapper);
+            String expectedIssuer = OAuthConstants.CLIENT_ID.equals(issuer) 
+                ? wrapper.getSaml2().getSubject().getNameID().getValue() : issuer;
+            if (actualIssuer == null || !actualIssuer.equals(expectedIssuer)) {
+                throw new NotAuthorizedException(errorResponse());
+            }
+        }
+        if (!validateAuthenticationSubject(message, cs, wrapper.getSaml2().getSubject())) {
+            throw new NotAuthorizedException(errorResponse());
+        }
+    }
+    
+    private String getIssuer(AssertionWrapper assertionW) {
+        Issuer samlIssuer = assertionW.getSaml2().getIssuer();
+        return samlIssuer == null ? null : samlIssuer.getValue();
+    }
+    
+    private void validateAudience(Message message, Conditions cs) {
+        String absoluteAddress = getAbsoluteTargetAddress(message);
+        
+        List<AudienceRestriction> restrictions = cs.getAudienceRestrictions();
+        for (AudienceRestriction ar : restrictions) {
+            List<Audience> audiences = ar.getAudiences();
+            for (Audience a : audiences) {
+                if (absoluteAddress.equals(a.getAudienceURI())) {
+                    return;
+                }
+            }
+        }
+        throw new NotAuthorizedException(errorResponse());
+    }
+    
+    private String getAbsoluteTargetAddress(Message m) {
+        if (accessTokenServiceAddress == null) {    
+            return new UriInfoImpl(m).getAbsolutePath().toString();
+        }
+        if (!accessTokenServiceAddress.startsWith("http")) {
+            String httpBasePath = (String)m.get("http.base.path");
+            return UriBuilder.fromUri(httpBasePath)
+                             .path(accessTokenServiceAddress)
+                             .build()
+                             .toString();
+        } else {
+            return accessTokenServiceAddress;
+        }
+    }
+    
+    private boolean validateAuthenticationSubject(Message m, 
+                                                  Conditions cs,
+                                                  org.opensaml.saml2.core.Subject subject) {
+        if (subject.getSubjectConfirmations() == null) {
+            return false;
+        }
+        // We need to find a Bearer Subject Confirmation method
+        for (SubjectConfirmation subjectConf : subject.getSubjectConfirmations()) {
+            if (SAML2Constants.CONF_BEARER.equals(subjectConf.getMethod())) {
+                validateSubjectConfirmation(m, cs, subjectConf.getSubjectConfirmationData());
+            }
+        }
+          
+        return true;
+    }
+      
+      /**
+       * Validate a (Bearer) Subject Confirmation
+       */
+    private void validateSubjectConfirmation(Message m,
+                                             Conditions cs,
+                                             SubjectConfirmationData subjectConfData) {
+        if (subjectConfData == null) {
+            if (!subjectConfirmationDataRequired
+                && cs.getNotOnOrAfter() != null && !cs.getNotOnOrAfter().isBeforeNow()) {
+                return;
+            }
+            throw new NotAuthorizedException(errorResponse());
+        }
+          
+        // Recipient must match assertion consumer URL
+        String recipient = subjectConfData.getRecipient();
+        if (recipient == null || !recipient.equals(getAbsoluteTargetAddress(m))) {
+            throw new NotAuthorizedException(errorResponse());
+        }
+          
+        // We must have a NotOnOrAfter timestamp
+        if (subjectConfData.getNotOnOrAfter() == null
+            || subjectConfData.getNotOnOrAfter().isBeforeNow()) {
+            throw new NotAuthorizedException(errorResponse());
+        }
+          
+        //TODO: replay cache, same as with SAML SSO case
+          
+        // Check address
+        if (subjectConfData.getAddress() != null
+            && (clientAddress == null || !subjectConfData.getAddress().equals(clientAddress))) {
+            throw new NotAuthorizedException(errorResponse());
+        }
+          
+          
+    }
+    
+    private static Response errorResponse() {
+        return Response.status(401).build();
+    }
+}

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/SamlOAuthValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2-saml/src/main/java/org/apache/cxf/rs/security/oauth2/saml/SamlOAuthValidator.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/OAuthClientUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/OAuthClientUtils.java?rev=1448696&r1=1448695&r2=1448696&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/OAuthClientUtils.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/OAuthClientUtils.java Thu Feb 21 15:57:24 2013
@@ -152,11 +152,67 @@ public final class OAuthClientUtils {
     public static ClientAccessToken getAccessToken(WebClient accessTokenService,
                                                    Consumer consumer,
                                                    AccessTokenGrant grant,
+                                                   boolean setAuthorizationHeader) {
+        return getAccessToken(accessTokenService, consumer, grant, null, setAuthorizationHeader);
+    }
+    
+    /**
+     * Obtains the access token from OAuth AccessToken Service 
+     * using the initialized web client 
+     * @param accessTokenService the AccessToken client
+     * @param grant {@link AccessTokenGrant} grant
+     * @param extraParams extra parameters
+     * @return {@link ClientAccessToken} access token
+     * @throws OAuthServiceException
+     */
+    public static ClientAccessToken getAccessToken(WebClient accessTokenService,
+                                                   AccessTokenGrant grant) 
+        throws OAuthServiceException {
+        return getAccessToken(accessTokenService, null, grant, null, false);
+    }
+    
+    /**
+     * Obtains the access token from OAuth AccessToken Service 
+     * using the initialized web client 
+     * @param accessTokenService the AccessToken client
+     * @param grant {@link AccessTokenGrant} grant
+     * @param extraParams extra parameters
+     * @return {@link ClientAccessToken} access token
+     * @throws OAuthServiceException
+     */
+    public static ClientAccessToken getAccessToken(WebClient accessTokenService,
+                                                   AccessTokenGrant grant,
+                                                   Map<String, String> extraParams) 
+        throws OAuthServiceException {
+        return getAccessToken(accessTokenService, null, grant, extraParams, false);
+    }
+    
+    /**
+     * Obtains the access token from OAuth AccessToken Service 
+     * using the initialized web client 
+     * @param accessTokenService the AccessToken client
+     * @param consumer {@link Consumer} representing the registered client.
+     * @param grant {@link AccessTokenGrant} grant
+     * @param extraParams extra parameters
+     * @param setAuthorizationHeader if set to true then HTTP Basic scheme
+     *           will be used to pass client id and secret, otherwise they will
+     *           be passed in the form payload  
+     * @return {@link ClientAccessToken} access token
+     * @throws OAuthServiceException
+     */
+    public static ClientAccessToken getAccessToken(WebClient accessTokenService,
+                                                   Consumer consumer,
+                                                   AccessTokenGrant grant,
+                                                   Map<String, String> extraParams,
                                                    boolean setAuthorizationHeader) 
         throws OAuthServiceException {
         
         Form form = new Form(grant.toMap());
-    
+        if (extraParams != null) {
+            for (Map.Entry<String, String> entry : extraParams.entrySet()) {
+                form.getData().add(entry.getKey(), entry.getValue());
+            }
+        }
         if (consumer != null) {
             if (setAuthorizationHeader) {
                 StringBuilder sb = new StringBuilder();
@@ -229,18 +285,6 @@ public final class OAuthClientUtils {
         }
     }
     
-    /**
-     * Creates OAuth Authorization header with Bearer scheme
-     * @param consumer represents the registered client
-     * @param accessToken the access token  
-     * @return the header value
-     */
-    @Deprecated
-    public static String createAuthorizationHeader(Consumer consumer,
-                                                   ClientAccessToken accessToken)
-        throws OAuthServiceException {
-        return createAuthorizationHeader(accessToken);
-    }
     
     /**
      * Creates OAuth Authorization header with Bearer scheme

Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/owner/ResourceOwnerGrant.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/owner/ResourceOwnerGrant.java?rev=1448696&r1=1448695&r2=1448696&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/owner/ResourceOwnerGrant.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/owner/ResourceOwnerGrant.java Thu Feb 21 15:57:24 2013
@@ -27,10 +27,16 @@ import org.apache.cxf.rs.security.oauth2
 public class ResourceOwnerGrant implements AccessTokenGrant {
     private String ownerName;
     private String ownerPassword;
+    private String scope;
     
     public ResourceOwnerGrant(String name, String password) {
+        this(name, password, null);
+    }
+    
+    public ResourceOwnerGrant(String name, String password, String scope) {
         this.ownerName = name;
         this.ownerPassword = password;
+        this.scope = scope;
     }
     
     public String getType() {
@@ -42,6 +48,9 @@ public class ResourceOwnerGrant implemen
         map.putSingle(OAuthConstants.GRANT_TYPE, OAuthConstants.RESOURCE_OWNER_GRANT);
         map.putSingle(OAuthConstants.RESOURCE_OWNER_NAME, ownerName);
         map.putSingle(OAuthConstants.RESOURCE_OWNER_PASSWORD, ownerPassword);
+        if (scope != null) {
+            map.putSingle(OAuthConstants.SCOPE, scope);
+        }
         return map;
     }
 

Modified: cxf/trunk/rt/rs/security/oauth-parent/pom.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/pom.xml?rev=1448696&r1=1448695&r2=1448696&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/pom.xml (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/pom.xml Thu Feb 21 15:57:24 2013
@@ -44,6 +44,7 @@
     <modules>
         <module>oauth</module>
         <module>oauth2</module> 
+        <module>oauth2-saml</module> 
     </modules>
 
 </project>

Modified: cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/CryptoLoader.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/CryptoLoader.java?rev=1448696&r1=1448695&r2=1448696&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/CryptoLoader.java (original)
+++ cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/CryptoLoader.java Thu Feb 21 15:57:24 2013
@@ -41,6 +41,15 @@ public class CryptoLoader {
     
     private static final String CRYPTO_CACHE = "rs-security-xml-crypto.cache";
     
+    public Crypto loadCrypto(String cryptoResource) throws IOException, WSSecurityException {
+        URL url = ClassLoaderUtils.getResource(cryptoResource, this.getClass());
+        if (url != null) {
+            return loadCryptoFromURL(url);
+        } else {
+            return null;
+        }
+    }
+    
     public Crypto getCrypto(Message message,
                             String cryptoKey, 
                             String propKey) 
@@ -54,8 +63,8 @@ public class CryptoLoader {
         if (o == null) {
             return null;
         }
-        
-        crypto = getCryptoCache(message).get(o);
+        Map<Object, Crypto> cryptoCache = getCryptoCache(message); 
+        crypto = cryptoCache != null ? cryptoCache.get(o) : null;
         if (crypto != null) {
             return crypto;
         }
@@ -73,15 +82,13 @@ public class CryptoLoader {
                 url = manager.resolveResource((String)o, URL.class);
             }
             if (url != null) {
-                Properties props = new Properties();
-                InputStream in = url.openStream(); 
-                props.load(in);
-                in.close();
-                crypto = CryptoFactory.getInstance(props);
+                crypto = loadCryptoFromURL(url);
             } else {
                 crypto = CryptoFactory.getInstance((String)o);
             }
-            getCryptoCache(message).put(o, crypto);
+            if (cryptoCache != null) {
+                cryptoCache.put(o, crypto);
+            }
             return crypto;
         } finally {
             if (orig != null) {
@@ -90,16 +97,29 @@ public class CryptoLoader {
         }
     }
     
+    public static Crypto loadCryptoFromURL(URL url) throws IOException, WSSecurityException {
+        Properties props = new Properties();
+        InputStream in = url.openStream(); 
+        props.load(in);
+        in.close();
+        return CryptoFactory.getInstance(props);
+    }
+    
     public final Map<Object, Crypto> getCryptoCache(Message message) {
-        EndpointInfo info = message.getExchange().get(Endpoint.class).getEndpointInfo();
-        synchronized (info) {
-            Map<Object, Crypto> o = 
-                CastUtils.cast((Map<?, ?>)info.getProperty(CRYPTO_CACHE));
-            if (o == null) {
-                o = new ConcurrentHashMap<Object, Crypto>();
-                info.setProperty(CRYPTO_CACHE, o);
+        Endpoint endpoint = message.getExchange().get(Endpoint.class);
+        if (endpoint != null) {
+            EndpointInfo info  = endpoint.getEndpointInfo();
+            synchronized (info) {
+                Map<Object, Crypto> o = 
+                    CastUtils.cast((Map<?, ?>)info.getProperty(CRYPTO_CACHE));
+                if (o == null) {
+                    o = new ConcurrentHashMap<Object, Crypto>();
+                    info.setProperty(CRYPTO_CACHE, o);
+                }
+                return o;
             }
-            return o;
+        } else {
+            return null;
         }
     }
 }

Modified: cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java?rev=1448696&r1=1448695&r2=1448696&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java (original)
+++ cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/AbstractSamlInHandler.java Thu Feb 21 15:57:24 2013
@@ -82,20 +82,38 @@ public abstract class AbstractSamlInHand
     
     protected void validateToken(Message message, InputStream tokenStream) {
         
-        Document doc = null;
+        Element token = readToken(message, tokenStream);
+        validateToken(message, token);
+        
+    }
+    
+    protected Element readToken(Message message, InputStream tokenStream) {
+        
         try {
-            doc = DOMUtils.readXml(new InputStreamReader(tokenStream, "UTF-8"));
+            Document doc = DOMUtils.readXml(new InputStreamReader(tokenStream, "UTF-8"));
+            return doc.getDocumentElement();
         } catch (Exception ex) {
             throwFault("Assertion can not be read as XML document", ex);
         }
-        validateToken(message, doc.getDocumentElement());
+        return null;
         
     }
 
     protected void validateToken(Message message, Element tokenElement) {
+        validateToken(message, toWrapper(tokenElement));
+    }
+    
+    protected AssertionWrapper toWrapper(Element tokenElement) {
+        try {
+            return new AssertionWrapper(tokenElement);
+        } catch (Exception ex) {
+            throwFault("Assertion can not be validated", ex);
+        }
+        return null;
+    }
+    
+    protected void validateToken(Message message, AssertionWrapper assertion) {
         try {
-            AssertionWrapper assertion = new AssertionWrapper(tokenElement);
-            
             RequestData data = new RequestData();
             if (assertion.isSigned()) {
                 WSSConfig cfg = WSSConfig.getNewInstance(); 
@@ -112,6 +130,8 @@ public abstract class AbstractSamlInHand
                     message.getContextualProperty(WSHandlerConstants.ENABLE_REVOCATION)));
                 assertion.verifySignature(data, null);
                 assertion.parseHOKSubject(data, null);
+            } else if (getTLSCertificates(message) == null) {
+                throwFault("Assertion must be signed", null);
             }
             if (samlValidator != null) {
                 Credential credential = new Credential();
@@ -158,7 +178,7 @@ public abstract class AbstractSamlInHand
         // to rt/rs/security
         LOG.warning(error);
         Response response = Response.status(401).entity(error).build();
-        throw ex != null ? new NotAuthorizedException(ex, response) : new NotAuthorizedException(response);
+        throw ex != null ? new NotAuthorizedException(response, ex) : new NotAuthorizedException(response);
     }
     
     /**

Modified: cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SAMLUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SAMLUtils.java?rev=1448696&r1=1448695&r2=1448696&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SAMLUtils.java (original)
+++ cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SAMLUtils.java Thu Feb 21 15:57:24 2013
@@ -93,15 +93,27 @@ public final class SAMLUtils {
     
     public static AssertionWrapper createAssertion(Message message) throws Fault {
         CallbackHandler handler = SecurityUtils.getCallbackHandler(
-             message, SAMLUtils.class, SecurityConstants.SAML_CALLBACK_HANDLER);
+            message, SAMLUtils.class, SecurityConstants.SAML_CALLBACK_HANDLER);
+        boolean selfSignAssertion = 
+            MessageUtils.getContextualBoolean(
+                message, SecurityConstants.SELF_SIGN_SAML_ASSERTION, false
+            );
+        return createAssertion(message, handler, selfSignAssertion);
+    }
+    
+    public static AssertionWrapper createAssertion(Message message,
+                                                   CallbackHandler handler) {
+        return createAssertion(message, handler, true);
+    }
+    
+    public static AssertionWrapper createAssertion(Message message,
+                                                   CallbackHandler handler,
+                                                   boolean selfSignAssertion) throws Fault {
+            
         SAMLParms samlParms = new SAMLParms();
         samlParms.setCallbackHandler(handler);
         try {
             AssertionWrapper assertion = new AssertionWrapper(samlParms);
-            boolean selfSignAssertion = 
-                MessageUtils.getContextualBoolean(
-                    message, SecurityConstants.SELF_SIGN_SAML_ASSERTION, false
-                );
             if (selfSignAssertion) {
                 //--- This code will be moved to a common utility class
                 Crypto crypto = new CryptoLoader().getCrypto(message, 
@@ -129,4 +141,50 @@ public final class SAMLUtils {
         }
         
     }
+    
+    public static AssertionWrapper createAssertion(CallbackHandler handler,
+                                                   SelfSignInfo info) throws Fault {
+            
+        SAMLParms samlParms = new SAMLParms();
+        samlParms.setCallbackHandler(handler);
+        try {
+            AssertionWrapper assertion = new AssertionWrapper(samlParms);
+            assertion.signAssertion(info.getUser(), 
+                                    info.getPassword(), 
+                                    info.getCrypto(), 
+                                    false);
+            return assertion;
+        } catch (Exception ex) {
+            StringWriter sw = new StringWriter();
+            ex.printStackTrace(new PrintWriter(sw));
+            LOG.warning(sw.toString());
+            throw new Fault(new RuntimeException(ex.getMessage() + ", stacktrace: " + sw.toString()));
+        }
+        
+    }
+    
+    public static class SelfSignInfo {
+        private Crypto crypto;
+        private String user;
+        private String password;
+        
+        public SelfSignInfo(Crypto crypto, String user, String password) {
+            this.crypto = crypto;
+            this.user = user;
+            this.password = password;
+        }
+        
+        public Crypto getCrypto() {
+            return crypto;
+        }
+        public String getUser() {
+            return user;
+        }
+        public String getPassword() {
+            return password;
+        }
+        public void setPassword(String password) {
+            this.password = password;
+        }
+    }
 }

Modified: cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SamlFormInHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SamlFormInHandler.java?rev=1448696&r1=1448695&r2=1448696&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SamlFormInHandler.java (original)
+++ cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SamlFormInHandler.java Thu Feb 21 15:57:24 2013
@@ -19,19 +19,15 @@
 
 package org.apache.cxf.rs.security.saml;
 
-import java.io.InputStream;
-import java.lang.annotation.Annotation;
 import java.net.URI;
 
-import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
-import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.jaxrs.ext.form.Form;
-import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.impl.UriInfoImpl;
 import org.apache.cxf.jaxrs.model.ClassResourceInfo;
 import org.apache.cxf.jaxrs.provider.FormEncodingProvider;
+import org.apache.cxf.jaxrs.utils.FormUtils;
 import org.apache.cxf.message.Message;
 
 public class SamlFormInHandler extends AbstractSamlBase64InHandler {
@@ -39,10 +35,9 @@ public class SamlFormInHandler extends A
     private static final String SAML_ELEMENT = "SAMLToken";
     private static final String SAML_RELAY_STATE = "RelayState";
    
-    private FormEncodingProvider<Form> provider = new FormEncodingProvider<Form>();
+    private FormEncodingProvider<Form> provider = new FormEncodingProvider<Form>(true);
     
     public SamlFormInHandler() {
-        provider.setExpectedEncoded(true);
     }
     
     public Response handleRequest(Message message, ClassResourceInfo resourceClass) {
@@ -63,14 +58,12 @@ public class SamlFormInHandler extends A
                 return Response.status(302).location(URI.create(samlRequestURI)).build();
             }
         }
-        // restore input stream
-        CachedOutputStream os = new CachedOutputStream(); 
         form.getData().remove(SAML_ELEMENT);
         form.getData().remove(SAML_RELAY_STATE);
+        
+        // restore input stream
         try {
-            provider.writeTo(form, Form.class, Form.class, new Annotation[]{}, 
-                MediaType.APPLICATION_FORM_URLENCODED_TYPE, new MetadataMap<String, Object>(), os);
-            message.setContent(InputStream.class, os.getInputStream());
+            FormUtils.restoreForm(provider, form, message);
         } catch (Exception ex) {
             throwFault(ex.getMessage(), ex);
         }
@@ -79,10 +72,7 @@ public class SamlFormInHandler extends A
     
     private Form readFormData(Message message) {
         try {
-            return provider.readFrom(Form.class, Form.class, 
-                              new Annotation[]{}, MediaType.APPLICATION_FORM_URLENCODED_TYPE, 
-                              new MetadataMap<String, String>(), 
-                              message.getContent(InputStream.class));
+            return FormUtils.readForm(provider, message);
         } catch (Exception ex) {
             throwFault("Error reading the form", ex);    
         }

Modified: cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SamlFormOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SamlFormOutInterceptor.java?rev=1448696&r1=1448695&r2=1448696&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SamlFormOutInterceptor.java (original)
+++ cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/SamlFormOutInterceptor.java Thu Feb 21 15:57:24 2013
@@ -57,7 +57,7 @@ public class SamlFormOutInterceptor exte
             
             String encodedToken = encodeToken(assertionWrapper.assertionToString());
                 
-            form.set(SAML_ELEMENT, encodedToken);
+            updateForm(form, encodedToken);
         } catch (Exception ex) {
             StringWriter sw = new StringWriter();
             ex.printStackTrace(new PrintWriter(sw));
@@ -67,8 +67,12 @@ public class SamlFormOutInterceptor exte
         
     }
         
+    protected void updateForm(Form form, String encodedToken) {
+        form.set(SAML_ELEMENT, encodedToken);
+    }
+    
     @SuppressWarnings("unchecked")
-    private Form getRequestForm(Message message) {
+    protected Form getRequestForm(Message message) {
         Object ct = message.get(Message.CONTENT_TYPE);
         if (ct == null || !MediaType.APPLICATION_FORM_URLENCODED.equalsIgnoreCase(ct.toString())) {
             return null;

Modified: cxf/trunk/systests/rs-security/pom.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/rs-security/pom.xml?rev=1448696&r1=1448695&r2=1448696&view=diff
==============================================================================
--- cxf/trunk/systests/rs-security/pom.xml (original)
+++ cxf/trunk/systests/rs-security/pom.xml Thu Feb 21 15:57:24 2013
@@ -83,6 +83,11 @@
         </dependency>
         <dependency>
             <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-rs-security-oauth2-saml</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
             <artifactId>cxf-rt-transports-http</artifactId>
             <version>${project.version}</version>
         </dependency>