Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Wiki Markup
{span:style=font-size:2em;font-weight:bold} JAX-RS Kerberos Support {span}

 

Table of Contents

Introduction

...

'Negotiate' authentication scheme is used to pass Kerberos service tickets over HTTP.
Example:

Code Block
java
java

Authorization: Negotiate "the encrypted service ticket"

...

As explained on this page, Authorization Policy typically needs to have its type set to "Negotiate" and its "authorization" property set to the name of the JAAS context. AuthorizationPolicy is set as a "policy" property on the interceptor, example:

Code Block
java
java

WebClient wc = WebClient.create("http://localhost:" + PORT + "/bookstore/books/123");
        
KerberosAuthOutInterceptor kbInterceptor = new KerberosAuthOutInterceptor();
        
AuthorizationPolicy policy = new AuthorizationPolicy();
policy.setAuthorizationType(HttpAuthHeader.AUTH_TYPE_NEGOTIATE);
policy.setAuthorization("KerberosClientKeyTab");
        
kbInterceptor.setPolicy(policy);
WebClient.getConfig(wc).getOutInterceptors().add(kbInterceptor);
        
Book b = wc.get(Book.class);

...

org.apache.cxf.jaxrs.security.KerberosAuthenticationFilter can be used to protected JAX-RS endpoints and enforce that a Negotiate authentication scheme is used by clients, example:

Code Block
xml
xml


<bean id="kerberosFilter" class="org.apache.cxf.jaxrs.security.KerberosAuthenticationFilter">
   <property name="loginContextName" value="KerberosServiceKeyTab"/>
</bean>

<jaxrs:server>
  <jaxrs:serviceBeans>
    <bean class="org.mycompany.MyCompanyResource"/>
  </jaxrs:serviceBeans>
  <jaxrs:providers>
    <ref bean="kerberosFilter">
  </jaxrs:providers>
</jaxrs:server>

...

javax.security.auth.callback.CallbackHandler needs to be registered if no Kerberos key tabs are used, here is an example of setting it up from Java:

Code Block
java
java

public class TestResource {
 public static void main(String[] args) {
   JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
   sf.setResourceClasses(BookStore.class);
   KerberosAuthenticationFilter filter = new KerberosAuthenticationFilter();
   filter.setLoginContextName("KerberosServer");
   
   CallbackHandler handler = 
     new org.apache.cxf.interceptor.security.NamePasswordCallbackHandler("HTTP/localhost", "http"); 
   filter.setCallbackHandler(handler);

   //filter.setLoginContextName("KerberosServerKeyTab");
   //filter.setServicePrincipalName("HTTP/ktab");
   sf.setProvider(filter);
   sf.setAddress("http://localhost:" + PORT + "/");
      
   sf.create();
 }
}

...

Note that if you have a JAX-RS KerberosAuthenticationFilter protecting the endpoints, then the filter will have an org.ietf.jgss.GSSContext instance available in the current CXF SecurityContext, via its KerberosAuthenticationFilter$KerberosSecurityContext implementation, which can be used to get to org.ietf.jgss.GSSCredential if the credential delegation is supported for a given source principal. The current credential if any can be set as a client property next, for example:

Code Block
java
java


import org.ietf.jgss.GSSCredential;

import org.apache.cxf.jaxrs.security.KerberosAuthenticationFilter;
import org.apache.cxf.jaxrs.security.KerberosAuthenticationFilter.KerberosSecurityContext;
import org.apache.cxf.phase.PhaseInterceptorChain;
import org.apache.cxf.security.SecurityContext;

@Path("service")
public class MyResource {

   @Context 
   private javax.ws.rs.core.SecurityContext securityContext;

   @GET
   public Book getBookFromKerberosProtectedStore() {
       WebClient wc = webClient.create("http://internal.com/store");
       SecurityContext securityContext = PhaseInterceptorChain.getCurrentMessage().get(SecurityContext.class);

       if (securityContext instanceof KerberosSecurityContext) {
           KerberosSecurityContext ksc = (KerberosSecurityContext)securityContext;
           GSSCredential cred = ksc.getGSSContext().getDelegCred();
           if (cred != null) {
               WebClient.getConfig(wc).getRequestContext().put(GSSCredential.class.getName(), cred);
           } 
       }
       return wc.get(Book.class); 
   }

}

...