CAS 5.2.2 with MFA using Google Authenticator / GAuth

1,726 views
Skip to first unread message

Janina Byky

unread,
Feb 15, 2018, 3:53:52 AM2/15/18
to CAS Community
Hello,

I'm trying to setup CAS 5.2.2 with Google Authenticator as second auth factor for specified services. CAS is running over LDAP (AD) and GAuth based on mongo. So far everything was great, build succeed, GAuth qrcode appears, user registers and now it's time for TOKEN form. I'm typing all scratch codes and those generated by Google Authenticator, but every single attempt is unsuccessful. Also there's no collection created to store tokens in mongo. Only GAuthRepository is created with proper values of registered users.

cas.properties

cas.authn.accept.users=

cas.authn.ldap[0].order=0
cas.authn.ldap[0].type=AUTHENTICATED
cas.authn.ldap[0].ldapUrl={CUT}
cas.authn.ldap[0].connectionStrategy=DEFAULT
cas.authn.ldap[0].useSsl=true
cas.authn.ldap[0].connectTimeout=15000
cas.authn.ldap[0].subtreeSearch=true
cas.authn.ldap[0].baseDn={CUT}
cas.authn.ldap[0].userFilter=(|(sAMAccountName={user})(userPrincipalName={user}))
cas.authn.ldap[0].bindDn={CUT}
cas.authn.ldap[0].bindCredential={CUT}
cas.authn.ldap[0].enhanceWithEntryResolver=true
cas.authn.ldap[0].principalAttributeId=sAMAccountName
cas.authn.ldap[0].principalAttributePassword=
cas.authn.ldap[0].usePasswordPolicy=true
cas.authn.ldap[0].principalAttributeList=sn,cn:commonName,givenName,sAMAccountName,memberOf
cas.authn.ldap[0].allowMultiplePrincipalAttributeValues=true
cas.authn.ldap[0].poolPassivator=NONE
cas.authn.ldap[0].minPoolSize=2
cas.authn.ldap[0].maxPoolSize=15


cas.authn.mfa.globalProviderId=mfa-gauth
cas.authn.mfa.globalFailureMode=CLOSED

cas.authn.mfa.gauth.issuer=TEST
cas.authn.mfa.gauth.codeDigits=6
cas.authn.mfa.gauth.timeStepSize=60
cas.authn.mfa.gauth.windowSize=3
cas.authn.mfa.gauth.label=TEST
cas.authn.mfa.gauth.rank=0

cas.authn.mfa.gauth.cleaner.enabled=true
cas.authn.mfa.gauth.cleaner.schedule.startDelay=20000
cas.authn.mfa.gauth.cleaner.schedule.repeatInterval=60000

cas.authn.mfa.gauth.bypass.type=DEFAULT

cas.authn.mfa.gauth.mongo.clientUri=${mongo.uri}
cas.authn.mfa.gauth.mongo.dropCollection=false
cas.authn.mfa.gauth.mongo.collection=GAuthRepository
cas.authn.mfa.gauth.mongo.tokenCollection=GoogleAuthenticatorMongoDbTokenRepository


pom.xml

        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-webapp${app.server}</artifactId>
            <version>${cas.version}</version>
            <type>war</type>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-support-ldap</artifactId>
            <version>${cas.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-support-saml</artifactId>
            <version>${cas.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-support-gauth</artifactId>
            <version>${cas.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apereo.cas</groupId>
            <artifactId>cas-server-support-gauth-mongo</artifactId>
            <version>${cas.version}</version>
        </dependency>


catalina.log

2018-02-15 09:31:13,952 DEBUG [org.apereo.cas.authentication.RegisteredServiceAuthenticationHandlerResolver] - <Authentication handlers used for this transaction are [GoogleAuthenticatorAuthenticationHandler,LdapAuthenticationHandler,HttpBasedServiceCredentialsAuthenticationHandler]>
2018-02-15 09:31:13,953 DEBUG [org.apereo.cas.adaptors.gauth.GoogleAuthenticatorAuthenticationHandler] - <Received OTP [253227]>
2018-02-15 09:31:13,954 DEBUG [org.apereo.cas.adaptors.gauth.GoogleAuthenticatorAuthenticationHandler] - <Received principal id [j.byky]>
2018-02-15 09:31:13,970 DEBUG [org.apereo.cas.authentication.PolicyBasedAuthenticationManager] - <[GoogleAuthenticatorAuthenticationHandler] exception details: [Failed to authenticate code 253227].>
2018-02-15 09:31:13,971 DEBUG [org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler] - <Credential is not one of username/password and is not accepted by handler [LdapAuthenticationHandler]>
2018-02-15 09:31:13,972 ERROR [org.apereo.cas.authentication.PolicyBasedAuthenticationManager] - <Authentication has failed. Credentials may be incorrect or CAS cannot find authentication handler that supports [[token=253227]] of type [GoogleAuthenticatorTokenCredential].>
2018-02-15 09:31:13,976 INFO [org.apereo.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: 253227
WHAT: Supplied credentials: [[token=253227]]
ACTION: AUTHENTICATION_SUCCESS
APPLICATION: CAS
WHEN: Thu Feb 15 09:31:13 CET 2018
CLIENT IP ADDRESS: 10.100.100.20
SERVER IP ADDRESS: 10.40.0.2
=============================================================

>
2018-02-15 09:31:13,978 ERROR [org.apereo.cas.web.flow.resolver.impl.AbstractCasWebflowEventResolver] - <1 errors, 0 successes>
org.apereo.cas.authentication.AuthenticationException: 1 errors, 0 successes
at org.apereo.cas.authentication.PolicyBasedAuthenticationManager.evaluateFinalAuthentication(PolicyBasedAuthenticationManager.java:400) ~[cas-server-core-authentication-5.2.2.jar:5.2.2]
at org.apereo.cas.authentication.PolicyBasedAuthenticationManager.authenticateInternal(PolicyBasedAuthenticationManager.java:380) ~[cas-server-core-authentication-5.2.2.jar:5.2.2]
at org.apereo.cas.authentication.PolicyBasedAuthenticationManager.authenticate(PolicyBasedAuthenticationManager.java:220) ~[cas-server-core-authentication-5.2.2.jar:5.2.2]
at org.apereo.cas.authentication.PolicyBasedAuthenticationManager$$FastClassBySpringCGLIB$$90e801d3.invoke(<generated>) ~[cas-server-core-authentication-5.2.2.jar:5.2.2]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85) ~[spring-aop-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.apereo.inspektr.audit.AuditTrailManagementAspect.handleAuditTrail(AuditTrailManagementAspect.java:134) ~[inspektr-audit-1.8.0.GA.jar:1.8.0.GA]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_162]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_162]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_162]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_162]
...

2018-02-15 09:31:13,982 INFO [org.apereo.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: 253227
WHAT: [event=error,timestamp=Thu Feb 15 09:31:13 CET 2018,source=OneTimeTokenAuthenticationWebflowEventResolver]
ACTION: AUTHENTICATION_EVENT_TRIGGERED
APPLICATION: CAS
WHEN: Thu Feb 15 09:31:13 CET 2018
CLIENT IP ADDRESS: 10.100.100.20
SERVER IP ADDRESS: 10.40.0.2
=============================================================


Can anybody tell me what I'm missing?

Janina Byky

unread,
Feb 19, 2018, 1:34:34 PM2/19/18
to CAS Community
I'm still getting this error when I use in memory storage. MongoDB is disabled.

Qrcode is generated, google app scans it, token field appears and any token that I type provides error.

2018-02-15 09:31:13,970 DEBUG [org.apereo.cas.authentication.PolicyBasedAuthenticationManager] - <[GoogleAuthenticatorAuthenticationHandler] exception details: [Failed to authenticate code 253227].>
2018-02-15 09:31:13,971 DEBUG [org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler] - <Credential is not one of username/password and is not accepted by handler [LdapAuthenticationHandler]>
2018-02-15 09:31:13,972 ERROR [org.apereo.cas.authentication.PolicyBasedAuthenticationManager] - <Authentication has failed. Credentials may be incorrect or CAS cannot find authentication handler that supports [[token=253227]] of type [GoogleAuthenticatorTokenCredential].>


Can anybody help me ?

Jeremy Van Rooyen

unread,
Feb 19, 2019, 2:13:18 AM2/19/19
to CAS Community, projek...@gmail.com
Hello,

I'm having the exact same issue as below.

Can anybody help with this or maybe point me in the right direction?

Regards
Jeremy

Mickaël

unread,
Feb 19, 2019, 3:30:29 AM2/19/19
to CAS Community, projek...@gmail.com
Hello,

Are you sure there is anything register in your Mongo database ? Scratch codes and token are store in DB for each user in 2 different tables.

It is strange to see that, normally "WHO" is the user, not the token :
WHO: 253227
WHAT: Supplied credentials: [[token=253227]]

For information, I am using gauth with MariaDB without any issue.

Mickaël

Jeremy Van Rooyen

unread,
Feb 21, 2019, 5:32:54 AM2/21/19
to CAS Community, projek...@gmail.com
Hi Mickaël,

Thanks for your reply.

So after playing around a bit more it seems like the on screen scratch codes is being stored in the mongodb and using that it allows me to authenticate perfectly.

The next question is how would one register via the qrcode using the Google Authenticator app on phone? Or am I not understanding something?

Kind Regards
Jeremy

Mickaël

unread,
Feb 21, 2019, 7:01:17 AM2/21/19
to CAS Community, projek...@gmail.com
Hi Jeremy,

It is a great news about the scratch codes.

I'm not sure to understand your question about qrcode. To register a device, it is possible and required when a service is registered on your CAS with "Google Authentication" as MFA.
So, at the first login without a registered device, user will be ask to scan the qrcode on the screen and save (or print) the scratch codes. After clilk on the next button, user should enter is token in the field to finish the registration and be redirected to the service.

Does it answer to your question Jeremy ?

My own question about this system, how to unregistered a device in case of change of device or loss ? I don't know URL to do that...

Sincerely,

Mickaël

Jeremy Van Rooyen

unread,
Feb 21, 2019, 7:53:33 AM2/21/19
to CAS Community, projek...@gmail.com
Hi Mickaël,


On Thursday, 21 February 2019 14:01:17 UTC+2, Mickaël wrote:
Hi Jeremy,

It is a great news about the scratch codes.

I'm not sure to understand your question about qrcode. To register a device, it is possible and required when a service is registered on your CAS with "Google Authentication" as MFA.

Do you mean that the service "Google Authentication" as MFA must be registered under the services configuration in json format?

 
So, at the first login without a registered device, user will be ask to scan the qrcode on the screen and save (or print) the scratch codes. After clilk on the next button, user should enter is token in the field to finish the registration and be redirected to the service.

This is what happens exactly the way you explain it here. So when I scan the qrcode with my phone it does not take the codes generated on the Google Authenticator app. It however does take the on screen codes.

I hope this clears up my question?

Mickaël

unread,
Feb 21, 2019, 9:50:42 AM2/21/19
to cas-...@apereo.org
Yes Jeremy, that's what I mean.
I'm using JPA for my service registry and the CAS manager webapp but it is the same way.

For the second part, are you invited to enter your token code displayed by your Google authenticator app?

If it doesn't work, perhaps your server is not at the good time. NTP can help you to fix it.

Sincerely,

Mickaël

--
- Website: https://apereo.github.io/cas
- Gitter Chatroom: https://gitter.im/apereo/cas
- List Guidelines: https://goo.gl/1VRrw7
- Contributions: https://goo.gl/mh7qDG
---
You received this message because you are subscribed to the Google Groups "CAS Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cas-user+u...@apereo.org.
To view this discussion on the web visit https://groups.google.com/a/apereo.org/d/msgid/cas-user/57f5e936-6e6e-422c-9fb1-5140e5408eda%40apereo.org.

Jeremy Van Rooyen

unread,
Feb 22, 2019, 2:45:52 AM2/22/19
to CAS Community
Thanks for your feedback Mickaël,

For the second part I'm presented by the qrcode and 5 scratch codes. When I scan the qrcode my Google Authenticator app on phone accepts it. 

Then I click on register and enter the token displayed by the Google Authenticator app and it says --> "Credentials are rejected/invalid and authentication attempt has failed."

This is what I see in the CAS log file:

DEBUG [org.apereo.cas.authentication.PolicyBasedAuthenticationManager] - <Attempting to authenticate credential [OneTimeTokenCredential(token=420195)]>
DEBUG [org.apereo.cas.authentication.PolicyBasedAuthenticationManager] - <Attempting authentication of [420195] using [GoogleAuthenticatorAuthenticationHandler]>
DEBUG [org.apereo.cas.adaptors.gauth.GoogleAuthenticatorAuthenticationHandler] - <Received OTP [420195]>
DEBUG [org.apereo.cas.adaptors.gauth.GoogleAuthenticatorAuthenticationHandler] - <Received principal id [jeremy]. Attempting to locate account in credential repository...>
DEBUG [org.apereo.cas.adaptors.gauth.GoogleAuthenticatorAuthenticationHandler] - <Attempting to locate OTP token [420195] in token repository for [jeremy]...>
DEBUG [org.apereo.cas.adaptors.gauth.GoogleAuthenticatorAuthenticationHandler] - <Attempting to authorize OTP token [420195]...>
 WARN [org.apereo.cas.adaptors.gauth.GoogleAuthenticatorAuthenticationHandler] - <Authorization of OTP token [420195] has failed>

It sounds to me that when I use the scratch codes it is stored in the mongodb and can be found in the token repository (stored in db), but not for the tokens used on Google Authenticator app? Not sure if my understanding is correct?

Thanks in advance
Jeremy 

Mickaël

unread,
Feb 22, 2019, 3:44:11 AM2/22/19
to cas-...@apereo.org
Jeremy, you don't tell me if the webapp server is at the good time and your smartphone too.
Token are time based, so if one of the device has not the good time, you will have problems.

Sincerely,

Mickaël

Jeremy Van Rooyen

unread,
Feb 22, 2019, 5:39:51 AM2/22/19
to CAS Community
Apologies Mickaël,

The webapp server and my smartphone's time is the same yes.

Kind Regards
Jeremy

Mickaël

unread,
Feb 22, 2019, 5:45:10 AM2/22/19
to cas-...@apereo.org
No problem.

Have you test with another app? I'm using andOTP but I don't think the problem is here.

Sincerely,

Mickaël

Jeremy Van Rooyen

unread,
Feb 22, 2019, 6:14:56 AM2/22/19
to CAS Community
I see your email was cut off :-)

You are using what and OTP?

Kind Regards
Jeremy

Mickaël

unread,
Feb 22, 2019, 7:01:32 AM2/22/19
to cas-...@apereo.org
andOTP is the name of the app I'm use. It is opensource.

Regards,

Mickaël

Jeremy Van Rooyen

unread,
Feb 22, 2019, 8:53:22 AM2/22/19
to CAS Community
Thanks Mickaël,

I think I will try with JPA - to store generated otp's in sql db and see what happens. I'm not sure that will solve it but it's worth a try.

Would you share your cas.properties so that I can compare configurations if possible?

Kind Regards
Jeremy

Jeremy Van Rooyen

unread,
Mar 1, 2019, 2:55:01 AM3/1/19
to CAS Community
Hi Mickaël,

Can you give me some guidance on the gauth-jpa configuration in the cas.properties file if possible?

Much appreciated.

Jeremy

Mickaël

unread,
Mar 4, 2019, 2:36:12 AM3/4/19
to cas-...@apereo.org
Hi Jeremy,

This is an extract for configuring CAS to use gauth with my server MySQL. This server is a MariaDB server on Debian 9.
The encryption key and signing key are generated at each start of the CAS server and sent to the log file catalina.out You can start it one time and copy/paste to your configuration file for the next startup.

cas.authn.mfa.gauth.crypto.encryption.key=XXXXXX
cas.authn.mfa.gauth.crypto.signing.key=XXXXXXX
cas.authn.mfa.gauth.issuer="Name of your service"
cas.authn.mfa.gauth.label="Something that describe the service"
cas.authn.mfa.gauth.jpa.autocommit=true
cas.authn.mfa.gauth.jpa.dialect=org.hibernate.dialect.MySQL5Dialect
cas.authn.mfa.gauth.jpa.ddlAuto=update
cas.authn.mfa.gauth.jpa.driverClass=com.mysql.cj.jdbc.Driver
cas.authn.mfa.gauth.jpa.healthQuery=SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_VARIABLES
cas.authn.mfa.gauth.jpa.password=YOUR_BDD_PASSWORD
cas.authn.mfa.gauth.jpa.url=jdbc:mysql://BDD_SERVER:3306/DATABASE_TO_STORE?serverTimezone=Europe/Paris
cas.authn.mfa.gauth.jpa.user=YOUR_BDD_USER

Sincerely, Mickaël

Jeremy Van Rooyen

unread,
Mar 4, 2019, 5:09:18 AM3/4/19
to CAS Community
Thank you for your feedback  Mickaël, much appreciated.

I configured cas to use mariadb as mentioned below and I still get the same issue as with mongodb.

Time on my server and app is exactly the same.

Its very strange though, scratch codes works fine but not generated OTP on Google Authenticator app after scanning the QR code.

This is the error that I get:

[org.apereo.cas.adaptors.gauth.GoogleAuthenticatorAuthenticationHandler] - <Authorization of OTP token [359062] has failed>
[org.apereo.cas.authentication.PolicyBasedAuthenticationManager] - <Authentication has failed. Credentials may be incorrect or CAS cannot find authentication handler that supports [OneTimeTokenCredential(
token=359062)] of type [GoogleAuthenticatorTokenCredential]. Examine the configuration to ensure a method of authentication is defined and analyze CAS logs at DEBUG level to trace the authentication event.>
[org.apereo.cas.authentication.PolicyBasedAuthenticationManager] - <[TEST] exception details: [Failed to authenticate code 359062].>
[org.apereo.cas.authentication.DefaultAuthenticationBuilder] - <Recording authentication handler failure under key [TEST]>

I'm not sure what I'm missing at all :-(

Kind Regards
Jeremy

Mickaël

unread,
Mar 4, 2019, 10:55:10 AM3/4/19
to CAS Community
Jeremy, have you a policy named [TEST] ?
What is your auth method ? LDAP, database, AD, other ?

Sincerely,

Mickaël

Jeremy Van Rooyen

unread,
Mar 5, 2019, 4:36:57 AM3/5/19
to CAS Community
Hi Mickaël,

I'm not sure what you mean by policy. I do have "[TEST]" as gauth issuer.

See below:

cas.authn.mfa.gauth.issuer=TEST
cas.authn.mfa.gauth.codeDigits=6
cas.authn.mfa.gauth.timeStepSize=60
cas.authn.mfa.gauth.windowSize=3
cas.authn.mfa.gauth.label=TEST
cas.authn.mfa.gauth.rank=0
cas.authn.mfa.gauth.bypass.type=DEFAULT

I use AD as my auth method.

Kind Regards
Jeremy

Mickaël

unread,
Mar 5, 2019, 6:25:18 AM3/5/19
to CAS Community
Hi Jeremy,

"Policy" is the word used in the logs you pasted.

Just a question, authentification works without gauth ?

Sincerely,
Mickaël

Jeremy Van Rooyen

unread,
Mar 5, 2019, 7:35:41 AM3/5/19
to CAS Community
Yes authentication works 100% without gauth.

Kind Regards
Jeremy

Mickaël

unread,
Mar 6, 2019, 3:33:15 AM3/6/19
to cas-...@apereo.org
Hi Jeremy,

Have you any record in the table GoogleAuthenticatorRegistrationRecord of your gauth's database ?

Sincerely,
Mickaël

Jeremy Van Rooyen

unread,
Mar 6, 2019, 4:05:32 AM3/6/19
to CAS Community
Hi Mickaël,

Yes I have see below:

MariaDB [gauth]> select * from GoogleAuthenticatorRegistrationRecord;

+----+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+----------------+
| id | registrationDate    | secretKey
                                                                                                                | username | validationCode |
+----+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+----------------+
|  1 | 2019-03-06 10:57:02 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | user    |         181111 |
+----+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+----------------+
1 row in set (0.00 sec)

Kind Regards
Jeremy
Reply all
Reply to author
Forward
0 new messages