Skip to content

Repository files navigation

Works on Apereo CAS V 8.0.1.2 - https://github.com/apereo/cas

For older versions of CAS, please check the branch corresponding to your CAS version :

  • for CAS 7.3.x, check branch 7.3.x
  • for CAS 7.2.x, check branch 7.2.x

Require esup-otp-api $\ge$ v2.2.3

Config

cas.properties

add the following:

# MFA Esup Otp Authentication
cas.authn.mfa.triggers.global.global-provider-id=mfa-esupotp

# Add translations, you will need to check what are the default from CAS "Message Bundles" properties
cas.messageBundle.baseNames=classpath:custom_messages,classpath:messages,classpath:esupotp_message

# Add your esup-otp-api in Content-Security-Policy:
cas.http-web-request.header.content-security-policy=script-src 'self' 'unsafe-inline' 'unsafe-eval' https://esup-otp-api.univ-ville.fr/; object-src 'none'; worker-src 'self' blob: 'unsafe-inline' 

If you want to trust devices for 7 days, you can add this in cas.properties

cas.authn.mfa.trusted.core.device-registration-enabled=true                                                                                                                                         
cas.authn.mfa.trusted.core.auto-assign-device-name=true
cas.authn.mfa.trusted.device-fingerprint.cookie.max-age=P7D

with auto-assign-device-name, user will not have to choose a name for his device in a web form, it will be automatically assigned.

esupotp.properties

Create esupotp.properties in same directory as cas.properties

##
# Esup Otp Authentication
#
esupotp.rank=0
esupotp.urlApi=http://my-api.com:8081
esupotp.usersSecret=changeit
esupotp.apiPassword=changeit
esupotp.byPassIfNoEsupOtpMethodIsActive=false
esupotp.otpManagerUrl=https://esup-otp-manager.univ.fr/
esupotp.failureMode=CLOSED

In esupotp.properties you can also use usual Multifactor Authentication Bypass configurations described here https://apereo.github.io/cas/8.0.x/mfa/Configuring-Multifactor-Authentication-Bypass.html

So for example you can setup bypass with groovy script :

esupotp.bypass.groovy.location=file:/etc/cas/config/mfaGroovyBypass.groovy

/etc/cas/config/mfaGroovyBypass.groovy :

import java.util.*

def boolean run(authentication, principal, registeredService, provider, logger, httpRequest, ... other_args) {

    if(registeredService.id == 10 && "cn=for.appli-sensible.supervisor,ou=groups,dc=univ-ville,dc=fr" in principal.attributes.memberOf) {
      return true;
    }

    return false;
}

cas/build.gradle

add

...

dependencies {
    ...
    implementation "org.esup-portail:esup-otp-cas:v2.3.0-cas_v8.0.x"
}

log4j2.xml

add

<AsyncLogger name="org.esupportail.cas.adaptors.esupotp" level="debug" additivity="false" includeLocation="true">
    <AppenderRef ref="casConsole"/>
    <AppenderRef ref="casFile"/>
</AsyncLogger>

If you want to use an untagged version, you can use jitpack.io :

Add in cas/build.gradle

...
repositories {
    ...
    maven {
        url "https://jitpack.io"
    }
}
...

dependencies {
    ...
    implementation "com.github.EsupPortail:esup-otp-cas:master"
}

TIPS: Look for https://jitpack.io/#EsupPortail/esup-otp-cas and check the available version you can use

If you want to package locally, with JDK 21 :

./gradlew clean build

publishing on central maven repository

This part is only for developers, if you want to publish on central maven repository, you need to have a sonatype account and be a member of the group org.esup-portail.

esup-otp-cas use jrelease plugin to publish on maven central repository.

You have to configure also your ~/.jreleaser/config.yml file with your sonatype credentials.

See https://jreleaser.org/guide/latest/examples/maven/maven-central.html#_gradle

Next, to publish on central maven repository, with JDK 21, and after setting version on gradle.properties :

./gradlew clean build publish jreleaserFullRelease

development environment with docker

You can use docker to setup a development environment with CAS and esup-otp-cas.

For that, run

docker compose -f src/etc/docker-compose.yml up

Next, you can access esup-otp-manager on http://localhost:4000/ It will be redirected to CAS for authentication on http://localhost:8080/cas/login?service=http://localhost:4000/

You can use login/password :

  • admin/pass
  • joe/pass
  • jack/pass

Note that some ports on your host must be free :

  • 8080 for CAS,
  • 3000 for esup-otp-api,
  • 4000 for esup-otp-manager
  • 3980 for openldap
  • 27017 for mongodb
  • 5005 for remote debugging of CAS

-> you can debug CAS with remote debugging on port 5005, and you can set breakpoints in esup-otp-cas code to see how it works.

If you want to reset the environment (rebuild esup-otp-api/esup-otp-manager, reset mongodb and rebuild esup-otp-cas with your changes...), you can run

docker compose -f src/etc/docker-compose.yml down -v
docker compose -f src/etc/docker-compose.yml up --build

If you wan to reset only the esup-otp-api database on mongodb (that contains users, otp methods, backup codes...), you can run

docker compose -f src/etc/docker-compose.yml exec mongodb mongosh --eval "db.getSiblingDB('test-otp').dropDatabase()"

Optional Playwright end-to-end tests

You can also run an optional Docker profile that executes a Playwright scenario against the local stack.

The scenario covers:

  • access to esup-otp-mamanager on http://localhost:4000/ with the CAS redirect,
  • login with joe/pass,
  • activation of backup codes in esup-otp-manager,
  • memorizing one backup code,
  • logout of esup-otp-mamanager (and CAS),
  • (re)login with joe/pass and access to the MFA challenge,
  • validation with the saved backup code and successful authentication,
  • deactivation of backup codes.

Run it with:

docker compose -f src/etc/docker-compose.yml --profile playwright up

This profile is optional and uses the same host ports as the development stack (4000, 8080, 3000, 3980, 27017). After the run, inspect the HTML report under src/etc/docker/playwright/playwright-report/; the recorded .webm videos are attached there as report artifacts.

If you want to only rerun the Playwright tests without restarting the whole stack, you can run (--build is useful if you want to rebuild the image with your latest code changes):

docker compose -f src/etc/docker-compose.yml --profile playwright run --rm playwright --build

It can be useful to reinitialize the esup-otp-api database before running the tests, to ensure a clean state with known users and OTP methods:

docker compose -f src/etc/docker-compose.yml exec mongodb mongosh --eval "db.getSiblingDB('test-otp').dropDatabase()"

Screenshots

ESUP-OTP-CAS - Phone Authentication

ESUP-OTP-CAS - Grid Authentication

About

Cas module using esup-otp-api

Resources

Stars

9 stars

Watchers

9 watching

Forks

Releases

Packages

Used by

Contributors

Languages