hey,
I'm a bit late to the party. I encountered the same behaviour on CAS 6.4.6.2 and 6.5.1
"TGT is saved into couchdb but ST is not saved; TS is saved only inside TGT." -> this was my first thought as well, but the STs are saved as well and since their "ephemeral" purpose they are deleted right away, but not from inside the TGC (this one is correct)
The CouchDB ticket registry must adhere to a similar logic as the DefaultTicketRegistry, and here the difference would be deleting from CouchDB vs something non-existing in a map like structure
In order to make the single logout functionality to work I did the following
1) a custom ticket registry extended from CouchDbTicketRegistry(CAS), with try catch,
ofc a best solution would be to override completely the
deleteSingleTicket since there the exceptions are not correctly treated in case if a document is not found
-------------------------------------------------------------
public class CouchDBTicketRegistry extends CouchDbTicketRegistry {
private static final Logger LOGGER = LoggerFactory.getLogger(CouchDBTicketRegistry.class);
public CouchDBTicketRegistry(TicketRepository couchDb, int conflictRetries) {
super(couchDb, conflictRetries);
}
@Override
public boolean deleteSingleTicket(final String ticketIdToDelete) {
try {
return super.deleteSingleTicket(ticketIdToDelete); // this will throw the error
} catch (Exception e) {
LOGGER.error("Error deleting ticket {}", ticketIdToDelete, e);
return false;
}
}
}
-----------------------------------------------------------
2) the way to inject the custom ticket registry with spring boot
-----------------------------------------------------------
@Configuration
@EnableConfigurationProperties(CasConfigurationProperties.class)
@ComponentScan("..........")
public class CouchDBTicketRegistryAutoConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(CouchDBTicketRegistryAutoConfiguration.class);
private final CasConfigurationProperties casProperties;
private final Optional<TicketRepository> ticketRepository;
public CouchDBTicketRegistryAutoConfiguration(CasConfigurationProperties casProperties, Optional<TicketRepository> ticketRepository) { //The Optional wrapping is in case the cas-server-support-couchdb-ticket-registry is not present or you will disable this functionality with spring.autoconfigure.exclude
LOGGER.info("injecting '{}' into CAS", this.getClass().getSimpleName());
this.ticketRepository = ticketRepository;
this.casProperties = casProperties;
}
@RefreshScope
@Bean(name = {"couchDbTicketRegistry", "ticketRegistry"}) // with this you override the default ticket registry and the one provided by CAS, they both are with ConditionalOnMissingBean, don't know why they have 2 different names
public TicketRegistry ticketRegistry() {
if (ticketRepository.isPresent()) {
final var couchDb = casProperties.getTicket().getRegistry().getCouchDb();
final var c = new CouchDBTicketRegistry(ticketRepository.get(), couchDb.getRetries());
c.setCipherExecutor(CoreTicketUtils.newTicketRegistryCipherExecutor(couchDb.getCrypto(), "couch-db"));
return c;
}
return null;
}
}
------------------------------------------------------------
3) in spring.factories of your custom CAS declare: org.springframework.boot.autoconfigure.EnableAutoConfiguration=a.b.b.CouchDBTicketRegistryAutoConfiguration
To view this discussion on the web visit
https://groups.google.com/a/apereo.org/d/msgid/cas-user/09af8c3c-357d-41d3-9c24-dad9ff679d4cn%40apereo.org.