Configuration for the OAuth client support in CAS server version 3.5.0

Configuration for the OAuth client support in CAS server version 3.5.0

I. How to use OAuth client support in CAS applications ?

1) Information returned by OAuth authentication

Once you have configured (see information below) your CAS server to support OAuth client, users will be able from the CAS login page to authenticate at OAuth provider(s) like Facebook instead of authenticating directly in CAS server (login page).

In CAS server, after this kind of delegated authentication, users have a specific Authentication information.

The Authentication object has the attribute AuthenticationManager.AUTHENTICATION_METHOD_ATTRIBUTE (authenticationMethod) setted to org.jasig.cas.support.oauth.authentication.handler.support.OAuthAuthenticationHandler.

The Principal object of the Authentication object has :

  • an id which is the name of the provider + # + the identifier of the user for this provider (example : FacebookProvider#0000000001).

  • attributes populated by the data retrieved from the OAuth provider (first name, last name, birthdate...)

2) How to send profile attributes to CAS client applications

In CAS applications, through service ticket validation, some of these information will be pushed to the CAS client and therefore to the application itself.

The identifier of the user is always pushed to the CAS client. For user attributes, it involves both the configuration at the server and the way of validating service tickets.

On CAS server side, to push attributes to the CAS client, it should be configured in the deployerConfigContext.xml file for the wanted service :

 

<bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl"> <property name="registeredServices"> <list> <bean class="org.jasig.cas.services.RegisteredServiceImpl"> <property name="id" value="0" /> <property name="name" value="HTTP" /> <property name="description" value="Only Allows HTTP Urls" /> <property name="serviceId" value="http://**" /> <property name="evaluationOrder" value="10000001" /> <property name="allowedAttributes"> <list> <!-- facebook --> <value>name</value> <value>first_name</value> <value>middle_name</value>

...

On CAS client side, to receive attributes, you need to use SAML validation or a customized CAS validation.


II. How to add OAuth client support in CAS server ?

1) Add dependency

First step is to add the dependency to the OAuth cas support module in the CAS server webapp pom.xml :

<dependency> <groupId>org.jasig.cas</groupId> <artifactId>cas-server-support-oauth</artifactId> <version>${project.version}</version> </dependency>

2) Add the OAuth providers needed

An OAuth provider is an OAuth server which can authenticate user (like Google, Yahoo...) instead of a CAS server. If you want to delegate the CAS authentication to Twitter for example, you have to add an OAuth provider for Twitter. OAuh providers are defined in the ScribeUP library (except the CAS one) :

All the OAuth providers must be declared in applicationContext.xml :

 

<bean id="facebook1" class="org.scribe.up.provider.impl.FacebookProvider"> <property name="key" value="the_key_for_facebook1" /> <property name="secret" value="the_secret_for_facebook1" /> <property name="callbackUrl" value="http://mycasserver/login" /> </bean> <bean id="twitter1" class="org.scribe.up.provider.impl.TwitterProvider"> <property name="key" value="the_key_for_twitter1" /> <property name="secret" value="the_secret_for_twitter1" /> <property name="callbackUrl" value="http://mycasserver/login" /> </bean> <bean id="google1" class="org.scribe.up.provider.impl.GoogleProvider"> <property name="key" value="the_key_for_google1" /> <property name="secret" value="the_secret_for_google1" /> <property name="callbackUrl" value="http://mycasserver/login" /> </bean> <bean id="yahoo1" class="org.scribe.up.provider.impl.YahooProvider"> <property name="key" value="the_key_for_yahoo1" /> <property name="secret" value="the_secret_for_yahoo1" /> <property name="callbackUrl" value="http://mycasserver/login" /> </bean> <bean id="linkedin1" class="org.scribe.up.impl.LinkedInProvider"> <property name="key" value="the_key_for_linkedin1" /> <property name="secret" value="the_secret_for_linkedin1" /> <property name="callbackUrl" value="http://mycasserver/login" /> </bean> <bean id="github1" class="org.scribe.up.provider.impl.GitHubProvider"> <property name="key" value="the_key_for_github1" /> <property name="secret" value="the_secret_for_github1" /> <property name="callbackUrl" value="http://mycasserver/login" /> </bean> <bean id="caswrapper1" class="org.jasig.cas.support.oauth.provider.impl.CasWrapperProvider20"> <property name="key" value="the_key_for_caswrapper1" /> <property name="secret" value="the_secret_for_caswrapper1" /> <property name="callbackUrl" value="http://mycasserver/login" /> <property name="serverUrl" value="http://mycasserverwithoauthwrapper/oauth2.0" /> </bean>

 

For each OAuth provider, the CAS server is considered an OAuth client and therefore should be declared to the OAuth provider. After declaration, a key and a secret is given by the OAuth provider which has to be defined in the beans (the_key_for_xxx and the_secret_for_xxx values for key and secret properties). The callbackUrl property must be set to the login url of the CAS server.
For the CAS OAuth wrapping, the serverUrl property must be set to the OAuth wrapping url of the other CAS server which is using OAuth wrapping.

3) Add the OAuth action in webflow

In the login-webflow.xml file, the OAuthAction must be added at the beginning of the webflow. Its role is to intercept callback calls from OAuth providers (like Facebook, Twitter...) after OAuth authentication :

<action-state id="oauthAction"> <evaluate expression="oauthAction" /> <transition on="success" to="sendTicketGrantingTicket" /> <transition on="error" to="ticketGrantingTicketExistsCheck" /> </action-state>

This OAuthAction has to be defined in cas-servlet.xml with all the OAuth providers needed :

 

<bean id="oauthAction" class="org.jasig.cas.support.oauth.web.flow.OAuthAction"> <property name="centralAuthenticationService" ref="centralAuthenticationService" /> <property name="providers"> <list> <ref bean="facebook1" /> <ref bean="twitter1" /> <ref bean="google1" /> <ref bean="yahoo1" /> <ref bean="linkedin1" /> <ref bean="github1" /> <ref bean="caswrapper1" /> </list> </property> </bean>

 

This OAuthAction uses the centralAuthenticationService bean to play the CAS authentication and references all the identity providers.

4) Add the principal resolver and the handler for OAuth authentication

To be able to authenticate user in CAS server after OAuth authentication by the OAuth provider, you have to add an OAuthAuthenticationHandler in the list of authenticationHandlers in deployerConfigContext.xml :

<property name="authenticationHandlers"> <list> <bean class="org.jasig.cas.support.oauth.authentication.handler.support.OAuthAuthenticationHandler"> <property name="providers"> <list> <ref bean="facebook1" /> <ref bean="twitter1" /> <ref bean="google1" /> <ref bean="yahoo1" /> <ref bean="linkedin1" /> <ref bean="github1" /> <ref bean="caswrapper1" /> </list> </property> </bean> </list> </property>

And also add an OAuthCredentialsToPrincipalResolver in the list of credentialsToPrincipalResolvers in the deployerConfigContext.xml :

<property name="credentialsToPrincipalResolvers"> <list> <bean class="org.jasig.cas.support.oauth.authentication.principal.OAuthCredentialsToPrincipalResolver" /> </list> </property>

5) Add the metadata populator for OAuth authentication

To be able to retrieve the attributes of the user profile, an OAuthAuthenticationMetaDataPopulator needs to be defined in the list of authenticationMetaDataPopulators in deployerConfigContext.xml :

<bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl"> <property name="authenticationMetaDataPopulators"> <list> <bean class="org.jasig.cas.support.oauth.authentication.OAuthAuthenticationMetaDataPopulator" /> </list> </property>

6) Add links on the login page to authenticate on OAuth providers

To start authentication on an OAuth provider, links must be added on the login page casLoginView.jsp (ProviderTypeUrl are automatically created by the OAuthAction) :

<a href="${FacebookProviderUrl}">Authenticate with Facebook</a> <br /> <br /> <a href="${TwitterProviderUrl}">Authenticate with Twitter</a><br /> <br /> <a href="${GoogleProviderUrl}">Authenticate with Google</a><br /> <br /> <a href="${YahooProviderUrl}">Authenticate with Yahoo</a><br /> <br /> <a href="${LinkedInProviderUrl}">Authenticate with LinkedIn</a><br /> <br /> <a href="${GitHubProviderUrl}">Authenticate with GitHub</a><br /> <br /> <a href="${CasWrapperProvider20Url}">Authenticate with another CAS server using OAuth v2.0 protocol wrapper</a><br /> <br />

III. Technical presentation of the OAuth client mode

1) Dependencies

a) org.scribe / scribe-up / 1.0.0

This module is based on an open source library called Scribe UP for « Scribe User Profile » : it's a web-oriented extension to Scribe to get user profile after OAuth authentication process.
Source code is here : https://github.com/leleuj/scribe-up. It's available under Apache 2 licence.
The Scribe UP library is based on Scribe (for OAuth communication) and Jackson (for JSON parsing).

b) org.jasig.cas / cas-server-core / ${project.version}

2) Classes

a) OAuthAuthenticationMetaDataPopulator (org.jasig.cas.support.oauth.authentication)

This class is a meta data populator for OAuth authentication. As attributes are stored in OAuthCredentials, they are added to the returned principal.

b) OAuthAuthenticationHandler (org.jasig.cas.support.oauth.authentication.handler.support)

This handler authenticates OAuth credential : it uses them to get an access token to get the user profile returned by the provider for an authenticated user.

c) OAuthCredentials (org.jasig.cas.support.oauth.authentication.principal)

This class represents an OAuth credential and (after authentication) a user identifier and attributes.

d) OAuthCredentialsToPrincipalResolver (org.jasig.cas.support.oauth.authentication.principal)

This class resolves the principal id regarding the OAuth credentials : principal id is the type of the provider # the user identifier.

e) CasWrapperApi20 (org.jasig.cas.support.oauth.provider.impl)

This class represents the OAuth API implementation for the CAS OAuth wrapper.

f) CasWrapperProvider20 (org.jasig.cas.support.oauth.provider.impl)

This class is the OAuth provider to authenticate user in CAS wrapping OAuth protocol.

g) OAuthAction (org.jasig.cas.support.oauth.web.flow)

This class represents an action in the webflow to retrieve OAuth information on the callback url which is the webflow url (/login). The oauth_provider and the other OAuth parameters are expected after OAuth authentication. Providers are defined by configuration. The service is stored and retrieved from web session after OAuth authentication.