2
votes

I use Apereo Cas 5.1.1 (Central Authentication Service) for such "architecture":

Client browser  -->  CAS Server  -->  Active Directory (LDAP)
 MS Windows 7         Red Hat              Microsoft

Introduction:

CAS Server URL is:

http://dev.domain.com:8080/cas

We create service user with userPrincipalName [email protected] and next registered SPN: HTTP/[email protected]. We generated keytab file, which works with kinit -V -t -k HTTP/[email protected] command also.

CAS Server use SPNEGO to provide promptless SSO authentication. (org.apereo.cas:cas-server-support-spnego-webflow in Maven POM).

Problem:

For some reason it always use NTLM authentication instead of Kerberos. How to force browser and CAS to use first Kerberos?

Details

Here is cas.properties file content we use:

cas.server.name: http://10.xxx.xxx.xxx:8080
cas.server.prefix: http://10.xxx.xxx.xxx:8080/cas

server.port=8080

cas.adminPagesSecurity.ip=127\.0\.0\.1

cas.log.dir=/app/log
logging.config: file:/etc/cas/config/log4j2.xml
cas.serviceRegistry.initFromJson=true

cas.authn.spnego.kerberosConf=/etc/cas/config/krb5.conf
cas.authn.spnego.mixedModeAuthentication=true
cas.authn.spnego.jcifsServicePrincipal=HTTP/[email protected]
[email protected]
### cas.authn.spnego.jcifsNetbiosWins=true
cas.authn.spnego.loginConf=file:/etc/cas/config/login.conf
cas.authn.spnego.ntlmAllowed=false
### cas.authn.spnego.hostNamePatternString=.+
cas.authn.spnego.jcifsUsername=sysDev
### cas.authn.spnego.useSubjectCredsOnly=false
### cas.authn.spnego.jcifsDomainController=
### cas.authn.spnego.hostNameClientActionStrategy=hostnameSpnegoClientAction
cas.authn.spnego.kerberosKdc=10.yyy.yyy.yyy ### ip found by command nslookup -type=srv _kerberos._tcp.domain.com
### cas.authn.spnego.alternativeRemoteHostAttribute=alternateRemoteHeader
cas.authn.spnego.jcifsDomain=DOMAIN.COM
### cas.authn.spnego.ipsToCheckPattern=127.+
cas.authn.spnego.kerberosDebug=true
### cas.authn.spnego.send401OnAuthenticationFailure=true
cas.authn.spnego.kerberosRealm=DOMAIN.COM
cas.authn.spnego.ntlm=false
### cas.authn.spnego.principalWithDomainName=false
cas.authn.spnego.jcifsServicePassword=<password for sysDev provided as plain text>
cas.authn.spnego.jcifsPassword=<password for sysDev provided as plain text>
### cas.authn.spnego.spnegoAttributeName=distinguishedName
### cas.authn.spnego.name=

cas.authn.spnego.principal.principalAttribute=sAMAccountName
### cas.authn.spnego.principal.returnNull=false

cas.authn.spnego.ldap.ldapUrl=ldap://10.yyy.yyy.yyy
### cas.authn.spnego.ldap.connectionStrategy=
cas.authn.spnego.ldap.baseDn=DC=domain,DC=com
cas.authn.spnego.ldap.bindDn=CN=sysDev,DC=domain,DC=com
#cas.authn.spnego.ldap.bindCredential=
# cas.authn.spnego.ldap.providerClass=org.ldaptive.provider.unboundid.UnboundIDProvider
cas.authn.spnego.ldap.failFast=false
cas.authn.spnego.ldap.subtreeSearch=true
cas.authn.spnego.ldap.useSsl=false
cas.authn.spnego.ldap.searchFilter=cn={host}
### cas.authn.spnego.ldap.searchFilter=%[email protected] ### is it better then above???

There are some commented properties to ease review the configuration.

The result is like this:

First, every authentication log looks the same like this:

2017-09-22 10:30:56,074 INFO [org.apereo.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: audit:unknown
WHAT: [event=success,timestamp=Fri Sep 22 10:30:56 CEST 2017,source=RankedAuthenticationProviderWebflowEventResolver]
ACTION: AUTHENTICATION_EVENT_TRIGGERED
APPLICATION: CAS
WHEN: Fri Sep 22 10:30:56 CEST 2017
CLIENT IP ADDRESS: 10.aaa.aaa.aaa
SERVER IP ADDRESS: 10.xxx.xxx.xxx
=============================================================
2017-09-22 10:30:56,136 WARN [org.apereo.cas.authentication.PolicyBasedAuthenticationManager] - <Authentication has failed. Credentials may be incorrect or CAS cannot find authentication handler that supports [unknown] of type [SpnegoCredential], which suggests a configuration problem.>
2017-09-22 10:30:56,138 INFO [org.apereo.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: unknown
WHAT: Supplied credentials: [unknown]
ACTION: AUTHENTICATION_FAILED
APPLICATION: CAS
WHEN: Fri Sep 22 10:30:56 CEST 2017
(...)

So browser doesn't send username to CAS Server.

When DEBUG level log is enabled, then we can see:

2017-09-22 12:13:18,232 DEBUG [org.apereo.cas.web.flow.InitializeLoginAction] - <Initialized login sequence>
2017-09-22 12:13:18,232 DEBUG [org.springframework.webflow.engine.Transition] - <Exiting state 'initializeLoginForm'>
2017-09-22 12:13:18,232 DEBUG [org.springframework.webflow.engine.ActionState] - <Entering state 'startSpnegoAuthenticate' of flow 'login'>
2017-09-22 12:13:18,232 DEBUG [org.springframework.webflow.execution.ActionExecutor] - <Executing [EvaluateAction@595ba047 expression = negociateSpnego, resultExpression = [null]]>
2017-09-22 12:13:18,232 DEBUG [org.springframework.webflow.execution.ActionExecutor] - <Executing org.apereo.cas.web.flow.SpnegoNegociateCredentialsAction@54c68eda>
2017-09-22 12:13:18,232 DEBUG [org.apereo.cas.web.flow.SpnegoNegociateCredentialsAction] - <Authorization header [Negotiate TlRMTVNTUAABAAAAl4II4gAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==], User Agent header [Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3)]>
2017-09-22 12:13:18,233 DEBUG [org.springframework.webflow.execution.ActionExecutor] - <Finished executing org.apereo.cas.web.flow.SpnegoNegociateCredentialsAction@54c68eda; result = success>
2017-09-22 12:13:18,233 DEBUG [org.springframework.webflow.execution.ActionExecutor] - <Finished executing [EvaluateAction@595ba047 expression = negociateSpnego, resultExpression = [null]]; result = success>
2017-09-22 12:13:18,233 DEBUG [org.springframework.webflow.engine.Transition] - <Executing [Transition@49e5cb05 on = success, to = spnego]>
2017-09-22 12:13:18,233 DEBUG [org.springframework.webflow.engine.Transition] - <Exiting state 'startSpnegoAuthenticate'>
2017-09-22 12:13:18,233 DEBUG [org.springframework.webflow.engine.ActionState] - <Entering state 'spnego' of flow 'login'>
2017-09-22 12:13:18,233 DEBUG [org.springframework.webflow.execution.ActionExecutor] - <Executing [EvaluateAction@5ed25881 expression = spnego, resultExpression = [null]]>
2017-09-22 12:13:18,233 DEBUG [org.springframework.webflow.execution.ActionExecutor] - <Executing org.apereo.cas.web.flow.SpnegoCredentialsAction@7c4ac70a>
2017-09-22 12:13:18,233 DEBUG [org.apereo.cas.web.flow.SpnegoCredentialsAction] - <SPNEGO Authorization header located as [Negotiate TlRMTVNTUAABAAAAl4II4gAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==]>
2017-09-22 12:13:18,233 DEBUG [org.apereo.cas.web.flow.SpnegoCredentialsAction] - <SPNEGO Authorization header found with [56] bytes>
2017-09-22 12:13:18,233 DEBUG [org.apereo.cas.web.flow.SpnegoCredentialsAction] - <Obtained token: [NTLMSSP^@^A^@^@^@��^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^F^A�^]^@^@^@^O]. Creating SPNEGO credential...>
2017-09-22 12:13:18,234 DEBUG [org.apereo.cas.authentication.adaptive.DefaultAdaptiveAuthenticationPolicy] - <Located client IP address as [<ip adress>]>
2017-09-22 12:13:18,234 DEBUG [org.apereo.cas.authentication.adaptive.DefaultAdaptiveAuthenticationPolicy] - <User agent [Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3)] is authorized to proceed>
2017-09-22 12:13:18,234 DEBUG [org.apereo.cas.authentication.adaptive.DefaultAdaptiveAuthenticationPolicy] - <Adaptive authentication policy has authorized client [<ip adress>] to proceed.>
2017-09-22 12:13:18,234 DEBUG [org.apereo.cas.web.support.WebUtils] - <Evaluating request to determine if warning cookie should be generated>
2017-09-22 12:13:18,235 DEBUG [org.apereo.cas.web.flow.resolver.impl.ServiceTicketRequestWebflowEventResolver] - <Located ticket-granting ticket [null] from the request context>
2017-09-22 12:13:18,235 DEBUG [org.apereo.cas.web.flow.resolver.impl.ServiceTicketRequestWebflowEventResolver] - <Located service [null] from the request context>
2017-09-22 12:13:18,235 DEBUG [org.apereo.cas.web.flow.resolver.impl.ServiceTicketRequestWebflowEventResolver] - <Provided value for [renew] request parameter is [null]>
2017-09-22 12:13:18,235 DEBUG [org.apereo.cas.web.flow.resolver.impl.ServiceTicketRequestWebflowEventResolver] - <Request is not eligible to be issued service tickets just yet>
2017-09-22 12:13:18,236 DEBUG [org.apereo.cas.web.support.WebUtils] - <Evaluating request to determine if warning cookie should be generated>
2017-09-22 12:13:18,236 DEBUG [org.apereo.cas.authentication.RegisteredServiceAuthenticationHandlerResolver] - <Authentication handlers used for this transaction are [HttpBasedServiceCredentialsAuthenticationHandlerJcifsSpnegoAuthenticationHandler]>
2017-09-22 12:13:18,237 DEBUG [org.apereo.cas.support.spnego.authentication.handler.support.JcifsSpnegoAuthenticationHandler] - <Processing SPNEGO authentication>
2017-09-22 12:13:18,240 INFO [org.apereo.cas.authentication.PolicyBasedAuthenticationManager] - <[JcifsSpnegoAuthenticationHandler] failed authenticating [unknown]>
(...)
2017-09-22 12:13:18,241 WARN [org.apereo.cas.authentication.PolicyBasedAuthenticationManager] - <Authentication has failed. Credentials may be incorrect or CAS cannot find authentication handler that supports [unknown] of type [SpnegoCredential], which suggests a configuration problem.>
(...)
>
2017-09-22 12:13:18,243 DEBUG [org.apereo.cas.web.flow.resolver.impl.InitialAuthenticationAttemptWebflowEventResolver] - <1 errors, 0 successes>
org.apereo.cas.authentication.AuthenticationException: 1 errors, 0 successes
        at org.apereo.cas.authentication.PolicyBasedAuthenticationManager.evaluateProducedAuthenticationContext(PolicyBasedAuthenticationManager.java:173) ~[cas-server-core-authentication-5.1.1.jar:5.1.1]
        at org.apereo.cas.authentication.PolicyBasedAuthenticationManager.authenticateInternal(PolicyBasedAuthenticationManager.java:153) ~[cas-server-core-authentication-5.1.1.jar:5.1.1]
        at org.apereo.cas.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:140) ~[cas-server-core-authentication-5.1.1.jar:5.1.1]
        at org.apereo.cas.authentication.AbstractAuthenticationManager$$FastClassBySpringCGLIB$$12a86894.invoke(<generated>) ~[cas-server-core-authentication-5.1.1.jar:5.1.1]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.3.8.RELEASE.jar:4.3.8.RELEASE]

Please notice that the NTLM ticket is used firstly - Negotiate TlR... (TlR points to NTLM). Why there is no log info about Kerberos usage?

Question

How to force using Kerberos firstly with Apereo CAS 5?

Additional questions:

  1. Red Hat machine is outside Active Directory domain, but client machine, client user is from domain - could this be a problem?
  2. Is bindDn should point to CN of user which has registered SPN?
  3. Is there a way to test if CAS server read properly loginConf and krb.conf files?
  4. How can I debug problems with this configuration?
1
Is dev.domain.com a CNAME? If it is, change it into an A record. Many web browsers, particularly Chrome and Firefox, don't always work well with Kerberos when the FQDN portion of the service instance is a CNAME. When Kerberos fails, NTLM is the fallback under many (but not all) scenarios.T-Heron
Yes, this was problem with DNS configuration - I've talk to administrator, who made necessary changes. Thanks for your comment. I can accept this if you write answer here.jsosnowski

1 Answers

2
votes

Is dev.domain.com a CNAME? If it is, change it into an A record. Many web browsers, particularly Chrome and Firefox, don't always work well with Kerberos when the FQDN portion of the service instance is a CNAME. When Kerberos fails, NTLM is the fallback under many (but not all) scenarios.