Versions Compared

Key

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

...

Table of Contents

Introduction

New:

  • Ehcache, JCache and JPA2 OAuthDataProviders (as well as Ehcache 2.x prior to CXF 3.3.0) can represent access tokens in JWT
  • Client Certificate Authentication and Token Binding is supported
  • DynamicRegistrationService is enhanced

CXF provides the an implementation of OAuth 2.0. See also the JAX-RS OAuth page for information about OAuth 1.0.

...

Custom grant handlers can be registered.

OAuth2 is a new protocol which offers a complex yet elegant solution toward helping end users (resource owners) authorize third-party providers to access their resources.

The OAuth2 flow which is closely related to the original OAuth 1.0 3-leg flow is called Authorization Code and involves 3 parties: the end user, the third party service (client) and the resource server which is protected by OAuth2 filters. Typically a client offers a service feature that an end user requests and which requires the former to access one or more protected resources on behalf of this user which are located at the resource server. For example, the client may need to access the end user's photos in order to print them and post to the user or read and possibly update a user's calendar in order to make a booking.

In order to make it this happen, the third-party service application/client needs to register itself with the OAuth2 server. This happens out-of-band and after the registration the client gets back a client key and secret pair. Typically the client is expected to provide the name and description of the application, the application logo URI, one or more redirect URIs, and other information that may help the OAuth2 authorization server to identify this client to the end user at the authorization time.

From then on, the authorization code flow works like this:
1. End User requests the third-party service using a browser.

2. The client redirects the end user to OAuth2 Authorization Service, adding its client id, the state, redirect URI and the optional scope to the target URI. The state parameter represents the current end user's request, redirect URI - where the authorization code is expected to be returned to, and the scope is the list of opaque permissions that the client needs in order to access the protected resources.

3. The Authorization Service will retrieve the information about the client using its client id, build an HTML form and return it to the end user. The form will ask the user if a the given third-party application can be allowed to access some specified resources on behalf of this user.

4. If the user approves it , then the Authorization Service will generate an authorization code and redirect the user back to the redirect uri provided by the client, also adding a state parameter to the redirect URI.

...

6. After getting an access token token, the service finally proceeds with accessing the current user's resources and completes the user's request.

As you can see the flow can be complex yet it is very effective. A number of issues may need to be taken care along the way such as managing expired tokens, making sure that the OAuth2 security layer is functioning properly and is not interfering with when the end user itself is trying to access its own resources, etc.

Please check the specification as well as other resources available on the WEB web for more information you may need to know about OAuth2.

CXF JAX-RS gives the best effort to making this process as simple as possible and requiring only a minimum effort on behalf of OAuth2 server developers. It also offers the utility code for greatly simplifying the way the third-party application applications can interact with the OAuth2 service endpoints.

...

Client Registration is typically done out of band, with the the dynamic client registration also being also possible.
The client registration service will offer an HTML form where the clients will enter their details, see a the Client bean for the currently supported properties.

...

3. Validating access tokens

 


CXF offers several JAX-RS service implementations that can be used to create the OAuth2 servers fastquickly: AuthorizationCodeGrantService and ImplicitGrantService for managing the redirection-based flows, as well as AccessTokenService for exchanging the grants for new tokens.

...

Note that some grants that do not require the redirection-based support, such as Client Credentials or SAML2 or JWT assertion grants, and instead may require only require an Access Token Service be operational.

If your OAuth2 server does support either Authorization Code or Implicit flow then either AuthorizationCodeGrantService and ImplicitGrantService need to be registered. If both services need to be supported then simply register two of them, but note each service will have its own @Path segment, "/authorize" and "/authorize-implicit". If you'd like both services listening on the same path then use AuthorizationService and inject inject the AuthorizationCodeGrantService and ImplicitGrantService beans into it.

If no AuthorizationCode redirection flow is supported then implementing OAuthDataProvider is sufficentsufficient.

Writing your own AuthorizationCodeDataProvider or OAuthDataProvider implementation is what is needed to get the OAuth2 server up and running. In many cases all you need to do is to persist or remove the Authorization Code Grant data, use one of the available utility classes to create a new access token and also persist it or remove the expired one, and finally convert the optional opaque scope values (if any are supported) to a more view-able information.

CXF ships several default provider implementations, see the section on wirting writing the providers below.

 


Authorization Service

The main responsibility of OAuth2 Authorization Service is to present an end user with a form asking the user to allow or deny the client accessing some of to access specified resources owned by the user resources. CXF offers  AuthorizationCodeGrantService and ImplicitGrantService for accepting the redirection requests, challenging the end users with the authorization forms, handling the end user decisions and returning the results back to the clients.

...

Note that the end user needs to authenticate. The Request URI includes the client_id, custom scope value, response_type set to 'code', the current request state and the redirect uri. Note the scope is optional - the Authorization Service will usually allocate a default scope; however even if the client does include an additional custom scope the end user may still not approve it. The redirect uri is also optional, assuming one or more ones redirect URIs have been were provided at when the client registration timewas registered with the Authorization Service.

The AuthorizationCodeGrantService will report a warning is if no secure HTTPS transport is used:

...

It can also be configured to reject the requests made over insecure HTTP transport.

The AuthorizationCodeGrantService will retrieve the information about the client application to populate an instance of OAuthAuthorizationData bean and return it. OAuthAuthorizationData contains application name and URI properties, optional list of Permissions and other properties which can be either presented to the user or kept in the hidden form fields in order to uniquely identify the actual authorization request when the end user returns the decision.

One important OAuthAuthorizationData property is "authenticityToken". It is used for validating that the current session has not been hijacked - AuthorizationCodeGrantService generates a random key, stores it in a Servlet HTTPSession instance and expects the returned authenticityToken value to match it - this is a recommended approach and it also implies that the authenticityToken value is hidden from a user, for example, it's kept in a 'hidden' form field. See also "User Session Authenticity" on how SessionAuthenticityTokenProvider can help.

A number of properties which have been submitted to the authorization endpoint with the original user redirect need to be made available after the user has been challenged with the autorization authorization consent form, when the user makes an authorization decision. These are properties such as 'clientId', 'state', 'redirectUri', and other properties, see this class which is extended by OAuthAuthorizationData. One simple approach is to have a view handler preparing prepare an authorization form with OAuthAuthorizationData to have these properties hidden in the form. Another option is to secure them in a session thus making the view creation process much simpler, see "User Session Authenticity" for one example.

The helper "replyTo" property is an absolute URI identifying the AuthorizationCodeGrantService handler processing which processes the user's decision and can be used by view handlers when building the forms or by other OAuthAuthorizationData handlers.

So the populated OAuthAuthorizationData is finally returned. Note that it's a JAXB XMLRootElement-annotated bean and can be processed by registered JAXB or JSON providers given that AuthorizationCodeGrantService supports producing "application/xml" and "application/json" (See the OAuth Without Browser section below for more). But in this case we have the end user working with a browser so an HTML form is what is really expected back.

The AuthorizationCodeGrantService supports producing "text/html" and simply relies on a registered RequestDispatcherProvider to set the OAuthAuthorizationData bean as an HttpServletRequest attribute and redirect the response to a view handler (can be JSP or some other servlet) to actually build the form and return it to the user. See the section below on other alternatives on how a view can be created.

...

Code Block
xml
xml
Address: http://localhost:8080/services/social/authorize/decision
Encoding: ISO-8859-1
Http-Method: POST
Content-Type: application/x-www-form-urlencoded
Headers: {
Authorization=[Basic YmFycnlAc29jaWFsLmNvbToxMjM0],
Content-Type=[application/x-www-form-urlencoded],
...
}
--------------------------------------
12-Apr-2012 15:36:29 org.apache.cxf.jaxrs.utils.FormUtils logRequestParametersIfNeeded
INFO: updateCalendar-7_status=allow&readCalendar_status=allow&scope=updateCalendar-7+readCalendar
&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fservices%2Freservations%2Freserve%2Fcomplete
&session_authenticity_token=4f0005d9-565f-4309-8ffb-c13c72139ebe&oauthDecision=allow&state=1&client_id=123456789

The AuthorizationCodeGrantService will use a the 'session_authenticity_token' to validate first check that the session is valid and if so will process the user's decision next.

If the decision is "allow" then it will check the status of the submitted individual scope values. It relies on the "scopename_status" convention (e.g., "updateCalendar-7_status=allow") in name/value pairs, if the form has offered offers the user a chance to selectively enable individual scopes then name/value pairs such as "updateCalendar-7_status=allow" are submitted. If none of such pairs is coming back are returned then it means the user has approved all the default and any additional (if any) scopes.

Next it will ask the OAuthDataProvider to generate an authorization code grant and return it alongside with the state if any by redirecting the current user back to the redirect URI:

...

You may want to display a resource owner/end user name in the authorization form this user will be facing, you can get org.apache.cxf.rs.security.oauth2.provider.ResourceOwnerNameProvider registered with either AuthorizationCodeGrantService or ImplicitGrantService.
org.apache.cxf.rs.security.oauth2.provider.DefaultResourceOwnerNameProvider, if registered, will return an actual login name, the custom implementations may choose to return a complete user name instead, etc.

Public Clients (Devices)

The Client can be 'public' if it has been registered as a public client with no client secret if the service itself has a "canSupportPublicClients" property enabled. The same property will also have to be enabled on AccessTokenService (described in the next section) for a public client without a secret be able to exchange a code grant for an access token.

...

Having OOB responses supported is useful when a public client (typically a device which can not keep the client secrets and/or where no redirect URI is supported) needs to get a code grant. What will happen is that a device owner will send a request to the Authorization Service which may look like this:

...

Assuming the 'mobileClient' has been registered as public one with no secret and the service has been set up to support such clients, the end user will get a chance to authorize this client the same way it can do can  confidential clients, and after this user gets back a code (delivered directly in the response HTML page by default) the user will enter the code securely into the device which will then replace it for a time-scoped access token by contacting AccessTokenService.

Secure code acquisition with redirect URI

The following extension is supported to help public clients with redirect URIs to accept the code securely.

PKCE support

CXF supports RFC-7636: Proof Key for Code Exchange by OAuth Public Clients (PKCE). If you are using the authorization code grant with public clients, it is recommended to use PKCE to avoid attacks which exploit the lack of a binding between the authorization code request and the token request. This binding is achieved for confidential clients by including the client_id in both requests, however with public clients we do not have a registered client_id.

The public (mobile) client generates a 'code_verifier' value and includes a related 'code_challenge' and optional 'code_challenge_method' to the authorization service. The authorization service will save the code_challenge valueThe public (mobile) client will include a 'code_verifier' value when requesting the authorization code and it will be saved by Authorization service, with the help of the registered AuthorizationCodeDataProvider into an instance of ServerAuthorizationCodeGrant. The client will next request a token providing the 'code' and 'code_challengeverifier' - the latter which will be compared by AuthorizationCodeGrantHandler with the original 'code_verifierchallenge' value. By default, the 'code_challenge' is expected to be equal to the original 'code_verifier', but the grant handler can be registered with the a custom org.apache.cxf.rs.security.oauth2.grants.code.CodeVerifierTransformer - CXF ships a DigestCodeVerifier which implements a transformation mentioned in the extension.

From CXF 3.5.1/3.4.6, the AuthorizationCodeGrantHandler has a "requireCodeVerifier" property, which when set to "true" requires that all clients must specify a code verifier. This aligns with the OAuth 2.1 specification.

Form Post Response Mode

Form Post Response Mode has been orinially was originally introduced for OpenId Connect but has been generally recomended recommended recently as a possibly safer option of returning OAuth2 Authorization Service response responses to the clients. Starting from CXF 3.1.9, if a client sends a "response_mode=form_post" parameter during the original redirect, CXF AuthorizationCodeService will return  an OOBAuthorizationResponse with its 'redirectUri' property set - which a JSP/etc handler will convert to an HTML form which will re-post the data to the client callback address.

...

Note that ServerAuthorizationGrant and Client can also be encrypted. 


The simplest strategy is to encrypt and decrypt the tokens with the symmetric/secret keys. Every new token can be encrypted with a unique secret key or all of them can be encrypted with a single secret key. The utilities provide few methods for creating secret keys with the default and advanced properties, in addition there are many examples around on how to create the keys with the specific properties.

...

Here is a typical code demonstrating how the encryption/decryption works: 


Code Block
SecretKey key = CryptoUtils.getSecretKey();

// create a new token, encrypt its state and return

ServerAccessToken token = new BearerAccessToken(client, 3600L);

String encryptedToken = ModelEncryptionSupport.encryptAccessToken(token, key);

token.setTokenKey(encryptedToken);

return token;

// decrypt a token given a token key

ModelEncryptionSupport.decryptAccessToken(this, encryptedToken, key);
 

JWT Tokens

Starting from CXF 3.1.8 some of CXF OAuthDataProvider implementations (EhCache, JCache and JPA2 based, as well as EhCache 2.x prior to CXF 3.3.0) support Access Token representations in JWT. This means that ServerAccessTokens created by data providers are converted to a sequence of JSON JWT claims and then JWS signed and/or JWE encrypted.

...

Additionally, in order to sign and/or encrypt, this provider can be injected with an instance of OAuthJoseJwtProducer or AccessTokenService endpoint where this provider is registered can be configured as follows:

 

Code Block
<jaxrs:server id="oauthServer1" address="https://localhost:${testutil.ports.jaxrs-oauth2-serviceJwt}/services">
    <jaxrs:serviceBeans>
        <ref bean="tokenService"/>
    </jaxrs:serviceBeans><serviceBeans>
    <!-- Sign -->
    <jaxrs:properties>
        <entry key="rs.security.signature.properties" value="org/apache/cxf/systest/jaxrs/security/alice.rs.properties"/>
        <entry key="rs.security.signature.key.password.provider" value-ref="keyPasswordProvider"/>
    </jaxrs:properties>
 </jaxrs:server>

Note that in this case Ehcache, JCache and JPA2 providers will still persist the complete ServerAccessToken representations - once JOSE sequence is created it becomes a new tokenId of the current ServerAccessToken, with the original tokenId becoming a JWT 'jti' claim.

...

One can configure the providers (Ehcache and JCache only at the moment, as well as EhCache 2.x prior to CXF 3.3.0) to persist access tokens only as these newly created JOSE sequences:

 

Code Block
<bean id="oauthProvider" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.OAuthDataProviderImpl">
       <property name="useJwtFormatForAccessTokens" value="true"/>
       <property name="storeJwtTokenKeyOnly" value="true"/>
</bean>

...

Resource server (RS) will need to make a decision how to validate this JWT token. It can continue validating it remotely with AccessTokenValidationService or TokenIntrsopectionService (see below for more info about these services) or if RS has an access to the keys used to sign/encrypt JWT then it can use a local JWT validation, example:

 

Code Block
<bean id="jwtTokenValidator" class="org.apache.cxf.rs.security.oauth2.filters.JwtAccessTokenValidator"/>
<bean id="oAuthFilterLocalValidation" class="org.apache.cxf.rs.security.oauth2.filters.OAuthRequestFilter">
    <property name="tokenValidator" ref="jwtTokenValidator"/>
</bean>
   
<jaxrs:server 
    depends-on="tls-config" 
    address="https://localhost:${testutil.ports.jaxrs-oauth2-filtersJwt}/securedLocalValidation">
    <jaxrs:serviceBeans>
        <ref bean="serviceBean"/>
    </jaxrs:serviceBeans>
    <jaxrs:providers>
        <ref bean="oAuthFilterLocalValidation"/>
    </jaxrs:providers>
    <jaxrs:properties>
         <entry key="rs.security.signature.in.properties" value="org/apache/cxf/systest/jaxrs/security/alice.rs.properties"/>
    </jaxrs:properties>
</jaxrs:server>

 


When to use JWT ? The pros are: might be easier to align with some newer OAuth2 related specifications, might be possible to avoid a remote validation call, possible OAuth2 server storage optimization. Cons: the extra cost of validating (or decrypting), access token value reported to and used by clients becomes larger. If JWS only is used - care should be taken to avoid putting some sensitive JWT claims given that JWS payload can be introspected. 

See JAX-RS JOSE wiki page for more information on how to sign and encrypt JSON Web Tokens.

 

on how to sign and encrypt JSON Web Tokens. Specifically, if you need to create JWT values in your custom providers, then have a look at  this section: one can delegate to or extend JoseJwtConsumer or JoseJwtProducer. Addtionally org.apache.cxf.rs.security.oauth2.provider.OAuthJoseJwtConsumer (and OAuthJoseJwtProducer) can help in cases where OAuth2 Client secret is used as a key for HMAC based signatures or encryptions, while OAuthServerJoseJwtConsumer (and OAuthServerJoseJwtProducer) can also use OAuth2 Client certificates.


Custom tokens

If needed, users can use their own custom token types, with the only restriction that the custom token type implementations have to extend org.apache.cxf.rs.security.oauth2.common.ServerAccessToken.

...

This service is available starting from CXF 3.1.8. It supports OAuth2 server configuration queries at ".well-known/oauth-authorization-server".

...

Please also see JAXRS OAuth2 Assertions section for more information.

 


Custom Grants

If you need to customize the way the well-known grant requests are handled then consider extending one of the grant handlers listed in the previous sub-sections.

...

CXF 3.1.7 ships JPA2 (JPAOAuthDataProvider and JPACodeDataProvider), Ehcache 2.x (DefaultEHCacheOAuthDataProvider and DefaultEHCacheCodeDataProvider) and JCache (JCacheOAuthDataProvider and JCacheCodeDataProvider) provider implementations which take care of all the persistence tasks: saving or removing registered clients, tokens and code grants. These providers can be easily customized.

...

If a 2-way TLS is used to authenticate a client, and the Client has a Base64 encoded representations of its X509Certificates available in its "applicationCertificates" property, then the AccessTokenService will do the additional comparison of these certificates against the ones available in the current TLS session.

New: Mutual TLS Profiles for OAuth2 Clients Also, OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens is completely supported since CXF 3.1.12. Note some parameters used in this draft may changeAfter the client authenticates to the token service, the token service will insert a digest of the client's certificate in the issued (JWT based) access token. On the resource server side, the OAuthRequestFilter will check the digest of the client certificate against the value stored in the token claim, and will throw a 401 exception if they do not match.

User Session Authenticity

...

The code in the previous section shows the client application code directly supporting OAuth2 dynamics (redirection, the access token acquisition). Starting from CXF 3.0.6 a simpler option is possible with the help of ClientCodeRequestFilter. This filter manages the initial redirection, exchanging code grants for tokens, persisting the request state, and then making the token and the state available to the application code, for example, the following code does not deal itself with teh the redirection or interacting with OAuth2 servers:

Code Block
java
java
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.rs.security.oauth2.client.ClientTokenContext;

@Path("reserve")
public class ReservationService {

private WebClient socialService;
private WebClient restaurantService;

@GET
@Path("table")
@Produces("text/html")
public Response reserve(@Context ClientTokenContext context) {
    // Check if token is available
    if (context.getToken() == null) {
       return redirectToFailureHandler(NO_CODE_GRANT);
    }
    // Prepare Authorization header
    socialService.authorization(context.getToken());
    
    // Get the state that was captured by the filter before redirecting the user to OAuth2 server
    ReservationRequest request = context.getState(ReservationRequest.class);
    
    // Work with the service on behalf of a user    
    Calendar c = null;
    try {
      c = socialService.get(Calendar.class);
    } catch (RuntimeException ex) {
      return redirectToFailureHandler(CALENDAR_ACCESS_PROBLEM);
    }
        
    CalendarEntry entry = c.getEntry(request.getHour());
    if (entry.getEventDescription() == null || entry.getEventDescription().trim().isEmpty()) { 
        String address = restaurantService.post(new Form().param("name", request.getReserveName()) 
                                         .param("phone", request.getContactPhone()) 
                                         .param("hour", Integer.toString(request.getHour())),
                                          String.class);
        if (address == null) {
            return redirectToFailureHandler(NO_RESERVATION);
        }
            
        // update the user's calendar
        Response response = socialService.form(new Form().param("hour", Integer.toString(request.getHour()))
                                         .param("description", "Table reserved at " + address));
        boolean calendarUpdated = response.getStatus() == 200 || response.getStatus() == 204;
            
        return Response.ok(new ReservationConfirmation(address, request.getHour(), calendarUpdated))
                           .build();
        } else {
            return redirectToFailureHandler(CALENDAR_BUSY);
        }
    }
}

...


The filter is configured as follows:

 


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.CustomClientTokenContextProvider"/>
       <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>

...

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).

...

Here is a configuration example: 


Code Block
languagexml
<beans>
<bean id="consumer" class="org.apache.cxf.rs.security.oauth2.client.Consumer">
   <property name="clientId" value="1"/>
   <property name="clientSecret" value="2"/>
</bean>
<bean id="bearerAuthSupplier" class="org.apache.cxf.rs.security.oauth2.client.BearerAuthSupplier">
   <!-- access token -->
   <property name="accessToken" value="12345678"/>
   <!-- refresh token and the info needed to use it to refersh the expired access token proactively or in response to 401 --> 
   <property name="refreshToken" value="87654321"/>
   <!-- 
       Set this property for the authenticator to check the access token expiry date and refresh the token proactively.
       Note that this property can also become effective after the first token refresh as it is not known in advance when 
       the injected access token will expire
   -->
   <property name="refreshEarly" value="true"/>
   <!-- client OAuth2 id and secret - needed to use a refresh token grant --> 
   <property name="consumer" ref="consumer"/>
   <!-- address of OAuth2 token service that supports a refresh token grant
   <property name="accessTokenServiceUri" value="https://server/oauth2/accessToken"/>
</bean>
<conduit name="*.http-conduit" xmlns="http://cxf.apache.org/transports/http/configuration">
  <authSupplier>
     <ref bean="bearerAuthSupplier"/>
  </authSupplier>
</conduit>
</beans>

 


At the moment only BearerAuthSupplier supporting bearer access tokens is available; authenticators supporting other well known token types will be provided in the future.

org.apache.cxf.rs.security.oauth2.client.CodeAuthSupplier is also shipped. It is similar to BearerAuthSupplier except that it is initailized with an authorization code grant obtained out of band, uses this grant to get the tokens and then delegates to BearerAuthSupplier. Example:

 


Code Block
languagexml
<beans>
<bean id="consumer" class="org.apache.cxf.rs.security.oauth2.client.Consumer">
   <property name="clientId" value="1"/>
   <property name="clientSecret" value="2"/>
</bean>
<bean id="codeAuthSupplier" class="org.apache.cxf.rs.security.oauth2.client.CodeAuthSupplier">
   <!-- authorization code -->
   <property name="code" value="12345678"/>

   <!-- Set this property for the authenticator to check the access token expiry date and refresh the token proactively -->
   <property name="refreshEarly" value="true"/>
   <!-- client OAuth2 id and secret - needed to use a refresh token grant --> 
   <property name="consumer" ref="consumer"/>
   <!-- address of OAuth2 token service that supports a refresh token grant
   <property name="accessTokenServiceUri" value="https://server/oauth2/accessToken"/>
</bean>
<conduit name="*.http-conduit" xmlns="http://cxf.apache.org/transports/http/configuration">
  <authSupplier>
     <ref bean="codeAuthSupplier"/>
  </authSupplier>
</conduit>
</beans>

 


Additionally, a basic JAX-RS 2.0 ClientRequestFilter, org.apache.cxf.rs.security.oauth2.client.BearerClientFilter, is shipped and is initialized with an "accessToken" property only. It might be used in cases where only a non-expiring access token is available.

...

OAuth2 and OIDC

CXF shipis ships OIDC RP and IDP service code which depends on its OAuth2 and JOSE implementations. See this page for more information.

...