Table of Contents

Single Sign On (CAS) Configuration

Configuration of the CAS Infrastructure on the Errigal IDMS is outlined on the bitbucket repo

https://bitbucket.org/errigal/cas-overlay-template/overview


Overview

Errigal's Single Sign On Implementation uses https://www.apereo.org/projects/cas, the WAR overlay project is used and Errigal's modifications are stored in bitbucket.

CAS authenticates selected Services against a number of Authentication Handlers. The configuration of these are outlined in the Configuration section.

From a high level, the authentication process is:

This process is described here https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol.html but the main points are copied below.

The CAS protocol is a simple and powerful ticket-based protocol developed exclusively for CAS. A complete protocol specification may be found here.

It involves one or many clients and one server. Clients are embedded in CASified applications (called “CAS services”) whereas the CAS server is a standalone component:

The CAS server is responsible for authenticating users and granting accesses to applications The CAS clients protect the CAS applications and retrieve the identity of the granted users from the CAS server. The key concepts are:

The TGT (Ticket Granting Ticket), stored in the CASTGC cookie, represents a SSO session for a user The ST (Service Ticket), transmitted as a GET parameter in urls, stands for the access granted by the CAS server to the CASified application for a specific user. Specification versions

The current CAS protocol specification is 3.x. The actual protocol specification is available at CAS-Protocol-Specification, which is hereby implemented by the Apereo CAS Server as the official reference implementation. It’s mainly a capture of the most common enhancements built on top of the CAS protocol revision 2.0. Among all features, the most noticeable update between versions 2.0 and 3.0 is the ability to return the authentication/user attributes through the new /p3/serviceValidate response (in addition to the /serviceValidate endpoint, already existing for CAS 2.0 protocol).


Troubleshooting

Exception "javax.net.ssl.SSLException: Received fatal alert: protocol_version" (SnmpManager)

Exception:

2018-11-30 07:32:06,013 [ajp-bio-8012-exec-37] ERROR util.CommonUtils  - Received fatal alert: protocol_version
 javax.net.ssl.SSLException: Received fatal alert: protocol_version
        at org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:328)
        at org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:305)
        at org.jasig.cas.client.validation.AbstractCasProtocolUrlBasedTicketValidator.retrieveResponseFromServer(AbstractCasProtocolUrlBasedTicketValidator.java:50)
        at org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator.validate(AbstractUrlBasedTicketValidator.java:207)
        at com.errigal.snmpmanager.ShiroCasRealm.authenticate(ShiroCasRealm.groovy:26)
        at org.apache.shiro.grails.RealmWrapper.getAuthenticationInfo(RealmWrapper.groovy:59)
        at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doMultiRealmAuthentication(ModularRealmAuthenticator.java:219)
        at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:269)
        at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
        at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
        at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:270)
        at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)
        at org.apache.shiro.web.filter.authc.AuthenticatingFilter.executeLogin(AuthenticatingFilter.java:53)
        at org.apache.shiro.cas.CasFilter.onAccessDenied(CasFilter.java:85)
        at org.apache.shiro.web.filter.AccessControlFilter.onAccessDenied(AccessControlFilter.java:133)
        at org.apache.shiro.web.filter.AccessControlFilter.onPreHandle(AccessControlFilter.java:162)
        at org.apache.shiro.web.filter.PathMatchingFilter.isFilterChainContinued(PathMatchingFilter.java:203)
        at org.apache.shiro.web.filter.PathMatchingFilter.preHandle(PathMatchingFilter.java:178)
        at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:131)
        at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
        at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
        at org.jasig.cas.client.session.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:76)
        at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
        at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
        at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
        at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
        at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
        at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
        at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
        at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
        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)
2018-11-30 07:32:06,013 [ajp-bio-8012-exec-37] INFO  app.realm  - Unable to authenticate with com.errigal.snmpmanager.ShiroCasRealm - javax.net.ssl.SSLException: Received fatal alert: protocol_version
 2018-11-30 07:32:06,506 [ajp-bio-8012-exec-33] INFO  snmpmanager.AuthController  - SSOFAILURE - check the grails and cas server logs, redirecting to fallback login

Resolution:

*Config.groovy Changes

The following parameters are required in the deployed *Config.groovy, e.g. SnmpManagerConfig.groovy, for SSO to work

grails.serverURL='https://nocportal.extenetsystems.com/SnmpManager'
enableSingleSignOn = true
security.shiro.cas.serverUrl = 'https://nocportal.extenetsystems.com/cas'

Accessing Specific Handlers

To access an application on a specific handler, you need to instantiate the fallback URL

http://qaapps1.err:8082/SnmpManager/auth/login?fallback=true

You are then free to access the application handler as normal

Disabling SSO

SSO can be disabled via *Config.groovy, set

enableSingleSignOn = false

and restart the application. Note if restarting in production, the customer needs to be notified, alarms acknowledge etc.

JMX (Visual VM)

Accessible via port 9418

Distributed Ticket Cache

The distributed ticket cache is an in memory, distributed hazelcast instance, please see the bitbucket configuration page.

All logging is prepended with com.hazelcast., for example, when you start up the second handler in the cluster, you should see logging like

2016-08-16 05:38:33,721 INFO [com.hazelcast.nio.tcp.TcpIpConnectionManager] - [ccicerrigalapps1]:5701 [dev] [3.6.2] Established socket connection between /10.30.95.51:5701 and /10.30.95.52:57788

2016-08-16 05:38:40,710 INFO [com.hazelcast.cluster.ClusterService] - [ccicerrigalapps1]:5701 [dev] [3.6.2]

Members [2] {
        Member [ccicerrigalapps1]:5701 this
        Member [ccicerrigalapps2]:5701
}

Authentication is failing

Application Not Authorized to Use CAS

If you attempt to log into a CAS managed service and you receive the error

Application Not Authorized to Use CAS The application you attempted to authenticate to is not authorized to use CAS

This means that the application you are trying to access is not configured as a service. The service is defined in as the service parameter of the URL

https://qalb1.err/cas/login?service=https://qalb1.err/SnmpManager/shiro-cas

These services are configured as JSON files in /usr/local/conf/cas/services. Before adding any more files here

If you are adding a service you should note :

Ticket Logging

When a Ticket Granting Ticket is created, the following logging is expected

2016-08-16 05:46:50,466 INFO [org.jasig.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - Audit trail record BEGIN
=============================================================
WHO: admin
WHAT: Supplied credentials: [admin]
ACTION: AUTHENTICATION_SUCCESS
APPLICATION: CAS
WHEN: Tue Aug 16 05:46:50 EDT 2016
CLIENT IP ADDRESS: 212.17.60.121
SERVER IP ADDRESS: scnoc.crowncastle.com
=============================================================


2016-08-16 05:46:50,474 INFO [org.jasig.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - Audit trail record BEGIN
=============================================================
WHO: audit:unknown
WHAT: TGT-**********************************************R3CSks5QLN-ccicerrigalapps1
ACTION: TICKET_GRANTING_TICKET_CREATED
APPLICATION: CAS
WHEN: Tue Aug 16 05:46:50 EDT 2016
CLIENT IP ADDRESS: 212.17.60.121
SERVER IP ADDRESS: scnoc.crowncastle.com
=============================================================

A Service Ticket for the same user looks like:

2016-08-16 05:46:50,502 INFO [org.jasig.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - Audit trail record BEGIN
=============================================================
WHO: admin
WHAT: ST-3-bOuFCpfRHx926yFSR7UD-ccicerrigalapps1 for http://localhost:8080/NocPortal/shiro-cas
ACTION: SERVICE_TICKET_CREATED
APPLICATION: CAS
WHEN: Tue Aug 16 05:46:50 EDT 2016
CLIENT IP ADDRESS: 212.17.60.121
SERVER IP ADDRESS: scnoc.crowncastle.com
=============================================================

Self Signed Certs

If you are setting up a CAS instance on QA for example, you will need a self signed cert. If your system is publicly accessible, a cert from a CA like godaddy is recommended as there should be less configuration or trouble shooting, as used in https://idmsqa.errigal.com/

For information on creating self signed certs see

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" 
                scheme="https" secure="true" SSLEnabled="true"
           keystoreFile="/home/john/.keystore" keystorePass="n******1"
           clientAuth="false" sslProtocol="TLS"
        />

Integrate Single Sign On in Grails 3

Dependencies

Used in Support Page project using Grails 3.2.6 on March 2017

  compile 'org.grails.plugins:spring-security-core:3.1.1'
  compile 'org.grails.plugins:spring-security-cas:3.0.0'

Documentation

Create User Domain

You need to create User Domain using Spring Security.

Run following command

grails s2-quickstart com.yourapp User Role

Bootstrap


@Secure on your controllers

By default, you have to specify @Secure annotation to all controller.

You can change this by editing staticRules in application.groovy http://grails-plugins.github.io/grails-spring-security-core/v3/index.html#requestMappings

Application.yml

CAS Plugin document mentions that proxyCallbackUrl and proxyReceptorUrl should be set but It isn't in our Single Sign On Implementation

---
grails:
   plugin:
      springsecurity:
         cas:
            loginUri: /login
            serviceUrl: http://10.5.5.8:8088/Support/login/cas
            serverUrlPrefix: http://10.5.5.8:8080/cas

Update CAS Login Page

If you need to change Logo and Poweredby Image, open cas-overlay-template and edit top.jsp which is located in src/main/webapp/WEB_INF/view/default/ui/includes


Exposing Grails Application On Domain

On the load balancer:

/etc/httpd/conf/mod-jk.conf

add:
JkMount /search/ SnmpManagerLoadBalancer
JkMount /search/* SnmpManagerLoadBalancer
JkMount /search SnmpManagerLoadBalancer
/etc/httpd/conf/workers.conf

add the SnmpManagerLoadBalancer to worker.list

At the end:
worker.SnmpManagerLoadBalancer.balance_workers=SnmpManagerWorker1

And where the workers are:
worker.SnmpManagerLoadBalancer.type=lb
worker.SnmpManagerLoadBalancer.sticky_session=1
worker.SnmpManagerWorker1.reference=worker.ajptemplate
worker.SnmpManagerWorker1.host=qaapps1.err
worker.SnmpManagerWorker1.port=8096
worker.SnmpManagerWorker1.reply_timeout=600000

Finally, restart the HTTPD so that the new settings take effect:

sudo service httpd restart

To debug, tail the following logs:

/var/log/httpd/error_log
/var/log/httpd/mod_jk.log