Versions Compared

Key

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

...

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 the end user itself trying to access its own resources, etc.

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

...

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

See this JAX-RS service implementation for one possible approach.

Developing OAuth2 Servers

OAuth2 server is the core piece of the complete OAuth2-based solution. Typically it contains 2 3 services for:
1. Authorizing request tokens by asking the end users to let clients access some of their resources and returning the
grants back to the client (Authorization Service)
2. Exchanging the token grants for access tokens (Access Token Service)

3. Validating access tokens

 

CXF offers several JAX-RS service implementations that can be used to create the OAuth2 servers fast: 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 SAML2 one, etc, may only require an Access Token Service be operational.

All of these services rely on the custom OAuthDataProvider which persists the access tokens and converts the opaque scope values to the information that can be presented to the users. Additionally, AuthorizationCodeDataProvider is an an OAuthDataProvider which can keep temporary information about the authorization code grants which needs to be removed after the tokens are requested in exchange.

Note that some grants that do not require the redirection-based support, such as Client Credentials or SAML2 or JWT assertion grants, and may 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 AuthorizationCodeGrantService and ImplicitGrantService beans into it.

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

Writing your own AuthorizationCodeDataProvider is an OAuthDataProvider implementation is what is needed to get the OAuth2 server up and running. In many cases all you need to do is to 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 3.1.7 ships JPA2 (JPAOAuthDataProvider and JPACodeDataProvider), Ehcache (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. Custom implementations can also extend  AbstractOAuthDataProvider or AbstractCodeDataProvider  and only implement their abstract persistence related methods or further customize some of their code.ships several default provider implementations, see the section on wirting 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 the user resources. CXF offers 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.

One of the differences between the AuthorizationCode Authorization Code and Implicit flows is that in the latter case the grant is the actual access token which is returned as the URI fragment value to the client script running in the browser. The way the end user is asked to authorize the client request is similar between the two flows. In this section we will assume that the Authorization Code flow is being exercizedused.

A third-party client redirects the current user to AuthorizationCodeGrantService, for example, here is how a redirection may happen:

...

It can also be configured to reject the requests over un-secure insecure HTTP transport.

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. The other properties which are meant to be hidden are clientId, state, redirectUri, proposedScope.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 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 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 the user decision and can be used by view handlers when building the forms or by other OAuthAuthorizationData handlers.

...

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)

CXF 2.7.7 provides an initial support for public clients (such as various mobile devices).

Client can be 'public' if it has been registered as a public client with no client secret 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.

...

If a public client has not registered a redirect URI with the Authorization service then the authorization code can be returned out-of-band (OOB), see OOBAuthorizationResponse bean. By default, it is returned directly to the end user, unless a custom OOBResponseDeliverer is registered with AuthorizationCodeGrantService which may deliver it to the client via some custom back channel.

...

Secure code acquisition with redirect URI

The following extension is supported to help public clients with redirect URIs to accept the code securely staring from CXF 3.0.0-milestone2.

The 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_challenge' - the latter will be compared by AuthorizationCodeGrantHandler with the original 'code_verifier'. By default, the 'code_challenge' is expected to be equal to the original 'code_verifier', but the grant handler can be registered with the custom org.apache.cxf.rs.security.oauth2.grants.code.CodeVerifierTransformer - CXF ships a DigestCodeVerifierTransformer DigestCodeVerifier which implements a transformation mentioned in the extension.

 

AccessTokenService

The role of AccessTokenService is to exchange a token grant for a new access token which will be used by the client to access the end user's resources.
Here is an example request log:

...

Finally OAuthDataProvider may need to convert opaque scope values such as "readCalendar" into a list of OAuthPermissions. AuthorizationCodeGrantService and OAuth2 security filters will depend on it (assuming scopes are used in the first place). In the former case AuthorizationCodeGrantService will use this list to populate OAuthAuthorizationData - the reason this bean only sees Permissions is that some of the properties OAuthPermission keeps are of no interest to OAuthAuthorizationData handlers.

Default Providers

Starting from CXF 3.0.2 default Ehcache-based and encrypting  OAuthDataProvider and AuthorizationCodeDataProvider implementations are shipped.

org.apache.cxf.rs.security.oauth2.grants.code.DefaultEHCacheCodeDataProvider and org.apache.cxf.rs.security.oauth2.provider.DefaultEHCacheOAuthDataProvider use Ehcache to store grant, client, access and refresh token data.

org.apache.cxf.rs.security.oauth2.grants.code.DefaultEncryptingCodeDataProvider and org.apache.cxf.rs.security.oauth2.provider.DefaultEncryptingOAuthDataProvider use an auto-generated or provided Java symmetric SecretKey to store grant, access and refresh token data.

Users are encouraged to experiment with these default providers, customize them if needed and provide the feedback.

1.7 ships JPA2 (JPAOAuthDataProvider and JPACodeDataProvider), Ehcache (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.

Custom implementations can also extend  AbstractOAuthDataProvider or AbstractCodeDataProvider  and only implement their abstract persistence related methods or further customize some of their codeUsers implementing their own persistence strategy may consider extending org.apache.cxf.rs.security.oauth2.grants.code.AbstractAuthorizationCodeDataProvider or org.apache.cxf.rs.security.oauth2.provider.AbstractOAuthDataProvider - these classes might help with taking care of some basic data initialization and check routines.

OAuth Server JAX-RS endpoints

...

Redirection-based Authorization Code and Implicit flows depend on end users signing in if needed during the initial redirection, challenged with the client authorization form and returning their decision. By default, CXF will enforce the user session authenticity by keeping the session state in a servlet container's HTTPSession. If the alternative storage is preferred then you can register a new SessionAuthenticityTokenProvider (available from CXF 2.6.4) with either AuthorizationCodeGrantService or ImplicitGrantService beans.

CXF ships JoseSessionTokenProvider which uses CXF JOSE to create a compact JWS and/or JWE sequence capturing all the data which need to be available when the user returns an authorization form decision and this secure sequence becomes a session token.

Keeping the state in the session

...