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:
- Red Hat machine is outside Active Directory domain, but client machine, client user is from domain - could this be a problem?
- Is
bindDn
should point to CN of user which has registered SPN? - Is there a way to test if CAS server read properly
loginConf
andkrb.conf
files? - How can I debug problems with this configuration?