Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagexml
<beans>
    
<jaxrs:server id="reservationsServer" address="/reservations">
        <jaxrs:serviceBeans>
           <ref bean="restaurantReserveService"/>
        </jaxrs:serviceBeans>
        <jaxrs:providers>
           <!-- other providers -->

           <bean class="oauth2.thirdparty.ClientTokenContextProviderImplCustomClientTokenContextProvider"/>
           <bean class="org.apache.cxf.rs.security.oauth2.client.ClientCodeRequestFilter">
               <property name="authorizationServiceUri" value="http://localhost:8080/services/authorize"/>
               <property name="accessTokenServiceClient" ref="atServiceClient"/>
               <property name="startUri" value="reserve/table"/>
               <property name="clientCodeStateManager" ref="codeManager"/>
               <property name="consumer" ref="consumer"/>
           </bean>
        </jaxrs:providers>
     </jaxrs:server>
     <bean id="codeManager" class="oauth2.thirdparty.ClientCodeStateManagerImpl"/>

     <!-- the consumer pre-registered with OAuth2 servers -->
     <bean id="consumer" class="org.apache.cxf.rs.security.oauth2.client.Consumer">
         <property name="key" value="123456789"/>
         <property name="secret" value="987654321"/>
     </bean>

     <!-- WebClient for communicating with OAuth2 AccessTokenService -->
    <jaxrs-client:client id="atServiceClient" serviceClass="org.apache.cxf.jaxrs.client.WebClient"
         address="http://localhost:8080/services/oauth2Token/token">
         <jaxrs-client:headers>
            <entry key="Accept" value="application/json"/>
         </jaxrs-client:headers>
     </jaxrs-client:client>

</beans>


...

In the above example the filter uses a custom 'clientCodeStateManager' (org.apache.cxf.rs.security.oauth2.client.ClientCodeStateManager implementation) for keeping the original request state before redirecting for it to be available later on to the applicationc application code - this is optional and is only needed if the redirection request depends on the request parameters (example, Oauth2 scope values are dynamic such as updateCalendar-7 where '7' is the hour) . By default, CXF ships some state managers out of the box, at the moment these are MemoryClientCodeStateManager and JoseClientCodeStateManager implementations, the latter signs and/or encrypts the request state and saves it in the HTTP session.

After the user is redirected back the filter exchanges the code for a new access token and sets this token and the original redirection state in ClientTokenContext. Note CllientTokenContext makes the original request state available to the application as MultivaluedMap.

CXF also ships a default ClientTokenContext implementation, a simple org.apache.cxf.rs.security.oauth2.client.ClientTokenContextImpl bean. Finally CXF ships org.apache.cxf.rs.security.oauth2.client.ClientTokenContextProvider to ensure ClientTokenContext can be available as JAX-RS context. Note though that the above configuration registers a custom ClientTokenContext provider ('oauth2.thirdparty.CustomClientTokenContextProvider') instead - this is optional and is only needed if it is preferred for the application code to access the state in a type safe way (example, via ReservationRequest type as shown above), such a provider can be implemented like this:

 

Code Block
java
java
import javax.ws.rs.core.MultivaluedMap;
import org.apache.cxf.jaxrs.ext.ContextProvider;
import org.apache.cxf.message.Message;
import org.apache.cxf.rs.security.oauth2.client.ClientTokenContext;
import org.apache.cxf.rs.security.oauth2.client.ClientTokenContextProvider;
import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;

public class CustomClientTokenContextProvider extends ClientTokenContextProvider {
    @Override
    public ClientTokenContext createContext(Message m) {
        return new WrapClientTokenContext(super.createContext(m));
    }
    private static class WrapClientTokenContext implements ClientTokenContext {
        private ClientTokenContext ctx;
        public WrapClientTokenContext(ClientTokenContext ctx) { 
            this.ctx = ctx;
        }
        @Override
        public MultivaluedMap<String, String> getState() {
            return ctx.getState();
        }
        @Override
        public <T> T getState(Class<T> cls) {
            if (ReservationRequest.class == cls) {
                MultivaluedMap<String, String> state = getState();
                return (T)new ReservationRequest(state.getFirst("name"),
                                              state.getFirst("phone"),
                                              Integer.parseInt(state.getFirst("hour")));
            }
            return ctx.getState(cls);
        }
        @Override
        public ClientAccessToken getToken() {
            return ctx.getToken();
        }
    }
}

 

ClientCodeRequestFilter can also be configured with org.apache.cxf.rs.security.oauth2.client.ClientTokenContextManager ('clientTokenContextManager' property) to support a case where the same user is returning with the same request and the access token granted previously has not expired yet. At the moment CXF ships only MemoryClientTokenContextManager with the JOSE-aware provider to follow. If the manager is registered and the context (and the access token) for the current user is found then the request goes ahead without the redirection. In this case the filter can pro-actively refresh the token if it has already expired or close to being expired ('expiryThreshold' property, example, if it is set to 5 secs and the filter sees that the token will expire in less than 5 sec then it will try to refresh).

ClientCodeRequestFilter can also be configured with a 'scopes' property when static OAuth2 scopes are used for all the users (note 'scope' is one of redirect parameters typically sent to OAuth2 servers)

Note a similar filter support is availble for client applications depending on OIDC RP authentication.

OAuth2 client authenticators for non-dynamic clients

...