Apereo CAS Surrogate Authentication API providing core interfaces and classes for surrogate authentication functionality
—
This module provides data classes and parsing interfaces for managing surrogate authentication requests and integrating with CAS's credential handling framework. These components bridge the gap between user input, credential processing, and the core surrogate authentication service.
A data class representing a complete surrogate authentication request with all necessary context information.
@ToString
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
@Getter
@NoArgsConstructor(force = true)
@EqualsAndHashCode
@RequiredArgsConstructor
@SuperBuilder
public class SurrogateAuthenticationRequest implements Serializable {
/**
* The authentication credential containing user information
*/
private final MutableCredential credential;
/**
* The original username attempting authentication
*/
private final String username;
/**
* The target username to impersonate
*/
private final String surrogateUsername;
/**
* Whether surrogate user selection is available/required
*/
private final boolean selectable;
/**
* Has surrogate username?.
*
* @return true/false
*/
public boolean hasSurrogateUsername() {
return StringUtils.isNotBlank(this.surrogateUsername);
}
}A credential trait for marking credentials with surrogate authentication context.
@ToString
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
@Getter
@NoArgsConstructor(force = true)
@EqualsAndHashCode
@RequiredArgsConstructor
public class SurrogateCredentialTrait implements CredentialTrait {
/**
* The target surrogate username
*/
private final String surrogateUsername;
}Interface for parsing credentials to extract surrogate authentication requests.
@FunctionalInterface
public interface SurrogateCredentialParser {
/**
* Default implementation bean name.
*/
String BEAN_NAME = "surrogateCredentialParser";
/**
* Parse surrogate authentication request.
*
* @param credential the credential to parse
* @return the surrogate authentication request, or empty if no surrogate context found
*/
Optional<SurrogateAuthenticationRequest> parse(MutableCredential credential);
}import org.apereo.cas.authentication.surrogate.SurrogateAuthenticationRequest;
import org.apereo.cas.authentication.MutableCredential;
// Using builder pattern
SurrogateAuthenticationRequest request = SurrogateAuthenticationRequest.builder()
.credential(mutableCredential)
.username("admin")
.surrogateUsername("targetUser")
.selectable(true)
.build();
// Check if surrogate username is present
if (request.hasSurrogateUsername()) {
String target = request.getSurrogateUsername();
String original = request.getUsername();
System.out.println("User " + original + " wants to impersonate " + target);
}
// Using RequiredArgsConstructor (Lombok-generated)
SurrogateAuthenticationRequest request2 = new SurrogateAuthenticationRequest(
credential, "admin", "targetUser", false
);import org.apereo.cas.authentication.surrogate.SurrogateCredentialParser;
import org.apereo.cas.authentication.surrogate.SurrogateAuthenticationRequest;
import org.apereo.cas.authentication.MutableCredential;
import java.util.Optional;
public class CustomSurrogateCredentialParser implements SurrogateCredentialParser {
@Override
public Optional<SurrogateAuthenticationRequest> parse(MutableCredential credential) {
// Check if credential contains surrogate context
String username = credential.getId();
// Example: Parse username+surrogate format like "admin+targetUser"
if (username != null && username.contains("+")) {
String[] parts = username.split("\\+", 2);
if (parts.length == 2) {
String originalUser = parts[0];
String surrogateUser = parts[1];
return Optional.of(SurrogateAuthenticationRequest.builder()
.credential(credential)
.username(originalUser)
.surrogateUsername(surrogateUser)
.selectable(false)
.build());
}
}
return Optional.empty();
}
}import org.apereo.cas.authentication.surrogate.SurrogateCredentialTrait;
import org.apereo.cas.authentication.MutableCredential;
// Add surrogate trait to credential
MutableCredential credential = // ... get credential
SurrogateCredentialTrait trait = new SurrogateCredentialTrait("targetUser");
// Add trait to credential (depends on credential implementation)
credential.getCredentialTraits().add(trait);
// Access trait later
Optional<SurrogateCredentialTrait> surrogateTrait = credential.getCredentialTraits()
.stream()
.filter(SurrogateCredentialTrait.class::isInstance)
.map(SurrogateCredentialTrait.class::cast)
.findFirst();
if (surrogateTrait.isPresent()) {
String surrogateUsername = surrogateTrait.get().getSurrogateUsername();
// Process surrogate authentication
}Both SurrogateAuthenticationRequest and SurrogateCredentialTrait support JSON serialization via Jackson annotations:
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
// Serialize request
SurrogateAuthenticationRequest request = // ... create request
String json = mapper.writeValueAsString(request);
// Deserialize request
SurrogateAuthenticationRequest restored = mapper.readValue(json, SurrogateAuthenticationRequest.class);These classes depend on types from:
import org.apereo.cas.authentication.MutableCredential;
import org.apereo.cas.authentication.CredentialTrait;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import org.apache.commons.lang3.StringUtils;
import java.io.Serial;
import java.io.Serializable;
import java.util.Optional;Install with Tessl CLI
npx tessl i tessl/maven-org-apereo-cas--cas-server-support-surrogate-api