mbohun
5/11/2015 - 1:22 AM

jasig CAS upgrade + OpenID setup

jasig CAS upgrade + OpenID setup

In our project based until today on jasig cas 4.0.3 and pac4j 1.4.2-SNAPSHOT, after simply bumping jasig cas version from 4.0.3 to 4.0.4 (the latest stable as of today 2015-08-13)

bash-3.2$ git diff
diff --git a/pom.xml b/pom.xml
index 9c79ae9..35cc2e0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -159,10 +159,16 @@
           <version>${pac4j.version}</version>
       </dependency>

+       <!-- NOTE: as of cas.version 4.0.4 we need to include this -->
+       <dependency>
+           <groupId>org.restlet.jee</groupId>
+           <artifactId>org.restlet</artifactId>
+           <version>2.1.0</version>
+       </dependency>
    </dependencies>

    <properties>
-        <cas.version>4.0.3</cas.version>
+        <cas.version>4.0.4</cas.version>
       <pac4j.version>1.4.2-SNAPSHOT</pac4j.version>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
@@ -189,5 +195,9 @@
               <enabled>false</enabled>
           </snapshots>
       </repository>
+       <repository>
+           <id>sonatype-forge</id>
+           <url>https://repository.sonatype.org/content/groups/forge/</url>
+       </repository>
    </repositories>
</project>

rebuilding and redeploying, cas crashed on deploy with the following exception:

2015-08-13 03:57:01,656 ERROR [org.springframework.web.servlet.DispatcherServlet] - <Context initialization failed>
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientAction' defined in ServletContext resource [/WEB-INF/cas-servlet.xml]: Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: org/pac4j/core/client/Mechanism
        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:288)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1051)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:955)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
        at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:651)
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:602)
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:665)
        at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:521)
        at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:462)
        at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
        at javax.servlet.GenericServlet.init(GenericServlet.java:158)
        at org.jasig.cas.web.init.SafeDispatcherServlet.init(SafeDispatcherServlet.java:76)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1279)
        at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1192)
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5210)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5493)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:632)
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1073)
        at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1857)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoClassDefFoundError: org/pac4j/core/client/Mechanism
        at org.jasig.cas.support.pac4j.web.flow.ClientAction.<clinit>(ClientAction.java:91)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:121)
        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:280)
        ... 35 more
Caused by: java.lang.ClassNotFoundException: org.pac4j.core.client.Mechanism
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1718)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1569)
        ... 43 more
2015-08-13 03:57:01,667 ERROR [org.jasig.cas.web.init.SafeDispatcherServlet] - <SafeDispatcherServlet:
The Spring DispatcherServlet we wrap threw on init.
But for our having caught this error, the servlet would not have initialized.>
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientAction' defined in ServletContext resource [/WEB-INF/cas-servlet.xml]: Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: org/pac4j/core/client/Mechanism
        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:288)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1051)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:955)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
          at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
        at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:651)
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:602)
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:665)
        at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:521)
        at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:462)
        at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
        at javax.servlet.GenericServlet.init(GenericServlet.java:158)
        at org.jasig.cas.web.init.SafeDispatcherServlet.init(SafeDispatcherServlet.java:76)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1279)
        at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1192)
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5210)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5493)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:632)
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1073)
        at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1857)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoClassDefFoundError: org/pac4j/core/client/Mechanism
        at org.jasig.cas.support.pac4j.web.flow.ClientAction.<clinit>(ClientAction.java:91)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:121)
        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:280)
        ... 35 more
Caused by: java.lang.ClassNotFoundException: org.pac4j.core.client.Mechanism
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1718)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1569)
        ... 43 more

conclussion/assumption:
If you want to use jasig cas >= 4.0.4 you HAVE TO use/upgrade pac4j to 1.7.1.

new cas.properties added in ala-cas-2.0

These are the new properties that were added to cas.properties to support the register+login with Facebook/Google/Twitter credentials:


# ...

# TODO: maybe given the number of arguments we should use "named" arguments:
# call sp_create_user(@email := ?,
#                     @firstname := ?,
#                     @lastname := ?,
#                     @password := ?,
#                     @city := ?,
#                     @organisation := ?,
#                     @primaryUserType := ?,
#                     @secondaryUserType := ?,
#                     @ausstate := ?,
#                     @telephone := ?)                                                                                                  #                     
userStore.create.sql.query=call sp_create_user(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

# https://jasig.github.io/cas/4.0.x/installation/Configuring-Authentication-Components.html#long-term-authentication
rememberMeDuration=1209600

# automatic registration ALA user password     
user.create.password=

# OAuth callback URL
pac4j.callback.url=https://nci-cas4.ala.org.au/cas/login

#facebook
pac4j.facebook.consumer.key=
pac4j.facebook.consumer.secret=

# google
pac4j.google.consumer.key=
pac4j.google.consumer.secret=

# twitter
pac4j.twitter.consumer.key=
pac4j.twitter.consumer.secret=

# github
pac4j.github.consumer.key=
pac4j.github.consumer.secret=

# linkedin
pac4j.linkedin.consumer.key=
pac4j.linkedin.consumer.secret=

# windows live
pac4j.windows.consumer.key=
pac4j.windows.consumer.secret=

# yahoo OAuth and OpenID 
pac4j.yahoo.consumer.key=
pac4j.yahoo.consumer.secret=

redirect behaviour on cas logout

  1. the redirect on logout is by deafult DISABLED in jasig cas-4.0.x in order to enable it, set the cas.logout.followServiceRedirects property in the cas.properties to true:
##                                                                                                                               
# CAS Logout Behavior                               
# WEB-INF/cas-servlet.xml
#
# Specify whether CAS should redirect to the specified service parameter on /logout requests
cas.logout.followServiceRedirects=true
  1. ALA specific NOTE: All the existing ALA applications (cas clients) are passing the URL for redirection in an argument named url (the grails apps are passing appUrl that is getting translated to url by the ala-auth-plugin) HOWEVER jasig cas-4.0.x expects the redirect to on logout URL to be passed in an argument named service.
  • create (or copy) basic jasig cas-4.0.1 maven overlay pom.xml file

  • build it: mvn clean package

  • test: deploy the generated target/cas.war file and test if you can login with the test/demo static username password credentials (casuser/Mellon); make sure cas is able to find cas.properties and log4j.xml file; for deployment I scp the generated cas.war file onto my dev vm into the /tmp dir, then run a modified ansible script that installs cas.war from /tmp instead of the maven repository

  • extract all the xml files in WEB-INF/ from the generated target/cas.war file and add them to src/main/webapp/WEB-INF; we do know because this is an upgrade from cas-3.4.2 that we are going to customize (most of?) them as we progress; once we finished we can go back and remove/delete any unmodified files from the boilerplates.

  • extract cas.properties and store them somewhere on your test vm (for example /etc/cas/cas-4.0.1.properties and /etc/cas/cas-4.1.0.properties, etc.), exclude WEB-INF/cas.properties (and WEB-INF/classes/log4j.xml) from the maven overlay in your pom.xml

    • adjust the /etc/cas/cas-4.0.1.properties with your server name, hostname, db credentials, etc.
    • adjust the /etc/cas/cas-4.0.1.properties to load /etc/cas/log4j.xml
    • adjust the /etc/cas/log4j.xml log file paths for cas.log, for example: /var/log/tomcat7/cas.log
  • showstopper BUG fix/workaround: (might be tomcat specific and things will work OK in jetty) once i added cas-server-webapp-support as a dependency into the pom.xml cas threw an exception on deploy and wasn't working, after some googling i found a description of this bug (fortunatelly with a workaround); although the bug reports claim the bug was fixed that seems to be not the case, both of my cas boilerplates were affected (cas-4.0.1 and cas-4.1.0-SNAPSHOT)

  • next step is to replace the test/demo authenticator with org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler

  • cookie value encryption

  • showstopper BUG for jasig cas-4.1.0-SNAPSHOT hopefuly tomcat7 specific, and development/test will be able to progress with jetty-9.2.10; if you only include cas-server-support-saml in your pom.xml tomcat-7.0.52/cas.war throws an exception (possible reason/solution) on deployment/startup:

    ******************** Welcome to CAS ********************
    

CAS Version: 4.1.0-SNAPSHOT Java Home: /usr/lib/jvm/java-7-oracle/jre Java Vendor: Oracle Corporation Java Version: 1.7.0_80 OS Architecture: amd64 OS Name: Linux OS Version: 3.13.0-52-generic


log4j:WARN No appenders could be found for logger (org.jboss.logging). log4j:WARN Please initialize the log4j system properly. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. 2015-05-15 04:52:23,981 INFO [org.jasig.cas.services.DefaultServicesManagerImpl] - <Loaded 2 services.> 2015-05-15 04:52:29,888 WARN [org.springframework.web.context.support.XmlWebApplicationContext] - <Exception encountered during context initialization - cancelling refresh attempt org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shibboleth.ParserPool' defined in URL [jar:file:/var/lib/tomcat7/webapps/cas/WEB-INF/lib/cas-server-support-saml-4.1.0-SNAPSHOT.jar!/META-INF/spring/opensaml-config.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: com.sun.org.apache.xerces.internal.util.SecurityManager cannot be cast to org.apache.xerces.util.SecurityManager at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4973) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:632) at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1073) at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1857) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.IllegalArgumentException: com.sun.org.apache.xerces.internal.util.SecurityManager cannot be cast to org.apache.xerces.util.SecurityManager at org.apache.xerces.jaxp.DocumentBuilderFactoryImpl.setAttribute(Unknown Source) at net.shibboleth.utilities.java.support.xml.BasicParserPool.doInitialize(BasicParserPool.java:570) at net.shibboleth.utilities.java.support.component.AbstractInitializableComponent.initialize(AbstractInitializableComponent.java:61) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1702) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1641) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570) ... 27 more

2015-05-15 04:52:30,018 INFO [org.jasig.cas.util.AutowiringSchedulerFactoryBean] - May 15, 2015 4:52:30 AM org.apache.catalina.core.StandardContext startInternal SEVERE: Error listenerStart May 15, 2015 4:52:30 AM org.apache.catalina.core.StandardContext startInternal SEVERE: Context [/cas] startup failed due to previous errors

- another `cas-server-support-saml` BUG (**hopefully tomcat specific**, and will work in jetty); `ala-cas-1.3.1` uses `org.jasig.cas.authentication.SamlAuthenticationMetaDataPopulator`, adding this to:
- `cas-4.0.1` makes `cas.war` to crash silently (no error details) on startup/deployment
- `cas-4.1.0-SNAPSHOT` makes `cas.war` to crash with the above error/exception (same error, simply because `cas-server-support-saml` is included in `pom.xml` as a dependency)
- some good news: https://github.com/leleuj/cas-pac4j-oauth-demo (**git branch 4.0.x**) delegated authentication to another cas server (i used https://auth.ala.org.au/cas/login) works! (see the [alternative deployment diagram](https://gist.github.com/mbohun/38fa53c5fd03ecfd9bbc#file-ala-cas-upgrade-01-png))
- **more good news**: https://github.com/leleuj/cas-pac4j-oauth-demo (**git branch master**) delegated authentication to another cas server (i used https://auth.ala.org.au/cas/login) **AND** delegated authentication to twitter (OAuth1.0) works! (see the [alternative deployment diagram](https://gist.github.com/mbohun/38fa53c5fd03ecfd9bbc#file-ala-cas-upgrade-01-png))
- **more good news**: managed to get `cas-4.0.1/pac4j-1.4.2-SNAPSHOT` working with both: existing ala-cas sql authentication **AND** delegated authentication (with Twitter, Facebook, etc.)

####refactoring
- cleanup: [**No resolver configured for ALAClientAuthenticationHandler**](https://github.com/Jasig/cas/blob/4.0.x/cas-server-core/src/main/java/org/jasig/cas/authentication/PolicyBasedAuthenticationManager.java#L214) check if we can split `ALAClientAuthenticationHandler` from the "resolver" (at the moment non-existent, could be called `ALADelegateAuthenticationResolver`), and register them in the `PolicyBasedAuthenticationManager.handlerResolverMap` **NOTE:** this seems to be at the moment **NOT** supported by `cas-4.0.1` where they seem to be assuming that the cas client does want to receive **only** the attributes Facebook/Google/GitHub/Twitter/LinkedIn/etc sent (**BUT** that is clearly not what we want/need for ALA); however it would be nice to have the authentication and resolver code separated.

2015-06-04 04:43:43,008 INFO [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <ALAClientAuthenticationHandler successfully authenticated org.jasig.cas.support.pac4j.authentication.principal.ClientCredential@63881288> 2015-06-04 04:43:43,017 DEBUG [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <No resolver configured for ALAClientAuthenticationHandler. Falling back to handler principal martin.bohun@gmail.com> 2015-06-04 04:43:43,018 INFO [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <Authenticated martin.bohun@gmail.com with credentials [org.jasig.cas.support.pac4j.authentication.principal.ClientCredential@63881288].> 2015-06-04 04:43:43,018 DEBUG [org.jasig.cas.authentication.PolicyBasedAuthenticationManager] - <Attribute map for martin.bohun@gmail.com: {authority=ROLE_USER, email=martin.bohun@gmail.com, userid=2, lastname=Bohun, firstname=Martin}>


####resources
- [social buttons for Bootstrap](https://lipis.github.io/bootstrap-social), example:
![Alt text](https://lipis.github.io/bootstrap-social/assets/img/bootstrap-social.png "bootstrap social")

####misc
- connect to myslq db over a ssh tunnel:
- `ssh -f -i ~/.ssh/nci-key.pem ubuntu@nci-cas4.ala.org.au -L 3333:nci-cas4.ala.org.au:3306 -N`
- then point [MySQL Workbench](https://www.mysql.com/products/workbench) at `127.0.0.1:3333`
- test

```jsp
<a href="${FacebookClientUrl}">Authenticate with Facebook</a> <br />
<br />
<a href="${TwitterClientUrl}"><img src="images/sign-in-with-twitter-gray.png"></img></a><br />
<br />
<a href="${GitHubClientUrl}&scope=user:email">Authenticate with GitHub</a><br />
<br />
<a href="${Google2ClientUrl}">Authenticate with Google</a><br />
<br />
<a href="${LinkedIn2ClientUrl}">Authenticate with LinkedIn</a><br />
<br />
<!-- NOTE: in order to access the email address you need to request the OAuth scope 'wl.emails';
         pac4j 1.4.2-SNAPSHOT has currently (as of 2015-06-13) hardcoded scope 'wl.basic'
-->
<a href="${WindowsLiveClientUrl}&scope=wl.emails">Authenticate with Windows Live</a><br />
<br />

###Live DEMO

  1. add 130.56.244.15 nci-cas4.ala.org.au to your /etc/hosts file; (C:\Windows\System32\drivers\etc\hosts in Windows)
  2. go to https://nci-cas4.ala.org.au/userdetails and click on the My profile link under ALA accounts
  3. This will take you to the CAS login page, where you can either login or automatically register and login with your
  • Facebook
  • Google
  • Twitter
  • LinkedIn
  • Github
  • WindowsLive

Tested with the following versions of:

  • jasig cas:
    • 4.0.1 (latest stable as of today 2015-05-08, limited functionality because of pac4j-1.4.x)
    • 4.0.2 ( released 2015-06-13, limited functionality because of pac4j-1.4.x)
    • 4.0.3 ( released 2015-07-10, limited functionality because of pac4j-1.4.x)
    • 4.0.4-SNAPSHOT (as of 2015-07-16 cas-4.0.x is compatible with pac4j-1.7.x)
    • 4.1.0-SNAPSHOT (current dev version)
  • pac4j versions:
    • 1.4.1 (compatible with cas-4.0.1; limited functionality)
    • 1.4.2-SNAPSHOT ? (compatible with cas-4.0.1; seems to contain twitter/HTTPS fixes, etc.)
    • 1.6.0
    • 1.7.0
    • 1.7.1-SNAPSHOT ? became 1.8.0-SNAPSHOT
    • 1.8.0-SNAPSHOT ?

UPDATE as of 2015-07-16 jasig cas-4.0.x is compatible with pac4j-1.7 this is going to be released in jasig cas-4.0.4

NOTE about pac4j/cas compatibility: "pac4j 1.6 is not compatible with CAS server v4.0.0, it will be with CAS server v4.1.0. In your case, you need to inherit a new FixedYahooClient from the current YahooClient and change the endpoint using HTTPS." by leleuj 2014-12-27 source

NOTE about pac4j 1.4.x limited functionality (and implemented workarouds):

  • Twitter: no support for getting user's email address (workaround imlemented)
  • Windows Live: no support for getting user's email address (workaround implemented)
  • no SAML (no pac4j-saml); pac4j-saml was added only in later version of pac4j

###howto

  1. setup new cas boilerplate - jasig cas maven overlay project; build, deploy, and test it - make sure you can login with the (test/demo) static username and password (casuser/Mellon):
  1. replace the (test) static username password authentication handler with your existing JDBC authentication handler org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler (and passwordEncoder (custom? default?)) - deploy and verify the login
  1. add Delegate Authentication pac4j authentication handler org.jasig.cas.support.pac4j.authentication.handler.support.ClientAuthenticationHandler

####clients pac4j

3.1 TODO: add & test OpenID Connect (google deprecated OpenID, replacing it with OpenID Connect in April 2015) - https://developers.google.com/identity/protocols/OpenIDConnect

3.2 TODO: Nick suggested adding support for a login/registration with Australian Access Federation credentials - - https://github.com/ausaccessfed - AAF login page - AAF attributes we are mainly after the email stored in mail AFF core attribute - https://wiki.oasis-open.org/security/Saml2TechOverview - http://blog.samlsecurity.com/search?q=opensaml - http://docs.spring.io/spring-security-saml/docs/1.0.x/reference/html/chapter-quick-start.html - https://github.com/onelogin/java-saml - https://wiki.shibboleth.net/confluence/display/OpenSAML/Home - https://technical.bestgrid.org/index.php/Vladimir's_general_Shibboleth_notes - http://blog.samlsecurity.com/ - SAML tracer for Firefox - https://www.testshib.org

  1. jasig cas-4.x spring webflow customization

diff --git a/src/main/java/org/jasig/cas/web/flow/LogoutAction.java b/src/main/java/org/jasig/cas/web/flow/LogoutAction.java
index 8db7372..2db089e 100644
--- a/src/main/java/org/jasig/cas/web/flow/LogoutAction.java
+++ b/src/main/java/org/jasig/cas/web/flow/LogoutAction.java
@@ -72,7 +72,7 @@ public final class LogoutAction extends AbstractLogoutAction {
             }
         }
 
-        final String service = request.getParameter("service");
+        final String service = request.getParameter("url"); //NOTE: *ALL* the existing ALA apps (cas clients) do use parameter named "url"
         if (this.followServiceRedirects && service != null) {
             final RegisteredService rService = this.servicesManager.findServiceBy(new SimpleWebApplicationServiceImpl(service));
 
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index 4f6a3b5..aa4d552 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -47,7 +47,7 @@
     <filter-class>org.jasig.cas.security.RequestParameterPolicyEnforcementFilter</filter-class>
     <init-param>
       <param-name>parametersToCheck</param-name>
-      <param-value>ticket service renew gateway warn target SAMLart pgtUrl pgt pgtId pgtIou targetService</param-value>
+      <param-value>ticket url renew gateway warn target SAMLart pgtUrl pgt pgtId pgtIou targetService</param-value>^M
     </init-param>
     <init-param>
       <param-name>charactersToForbid</param-name>