Apereo CAS Surrogate Authentication API providing core interfaces and classes for surrogate authentication functionality
—
The SurrogateAuthenticationService interface provides the core functionality for surrogate authentication operations in CAS. It defines methods for checking impersonation permissions, retrieving allowed accounts, handling wildcard permissions, and managing authentication attributes.
The primary interface for surrogate authentication logic.
@FunctionalInterface
public interface SurrogateAuthenticationService {
/**
* Gets a collection of account names a surrogate can authenticate as.
*
* @param username The username of the surrogate
* @param service the service
* @return collection of usernames
* @throws Throwable the throwable
*/
Collection<String> getImpersonationAccounts(String username, Optional<? extends Service> service) throws Throwable;
/**
* Checks whether a principal can authenticate as a surrogate user.
*
* @param surrogate The username of the surrogate
* @param principal the principal
* @param service the service
* @return true if the given surrogate can authenticate as the user
* @throws Throwable the throwable
*/
default boolean canImpersonate(String surrogate, Principal principal, Optional<? extends Service> service) throws Throwable {
return false;
}
/**
* Is wildcarded account authorized?.
*
* @param surrogate the surrogate
* @param principal the principal
* @param service the service
* @return true /false
* @throws Throwable the throwable
*/
default boolean isWildcardedAccount(String surrogate, Principal principal, Optional<? extends Service> service) throws Throwable {
Collection<String> accounts = getImpersonationAccounts(principal.getId(), service);
return isWildcardedAccount(accounts, service);
}
/**
* Is wildcarded account accepted and found in the given accounts?.
*
* @param accounts the accounts
* @param service the service
* @return true /false
*/
default boolean isWildcardedAccount(Collection<String> accounts, Optional<? extends Service> service) {
return accounts.size() == 1 && accounts.contains(SurrogateAuthenticationService.WILDCARD_ACCOUNT);
}
/**
* Collect surrogate attributes.
*
* @param builder the builder
* @param surrogateUser the surrogate user
* @param principal the principal
*/
default void collectSurrogateAttributes(AuthenticationBuilder builder, String surrogateUser, String principal) {
LOGGER.debug("Recording surrogate username [{}] as an authentication attribute", surrogateUser);
builder.addAttribute(SurrogateAuthenticationService.AUTHENTICATION_ATTR_SURROGATE_USER, surrogateUser);
builder.addAttribute(SurrogateAuthenticationService.AUTHENTICATION_ATTR_SURROGATE_PRINCIPAL, principal);
builder.addAttribute(SurrogateAuthenticationService.AUTHENTICATION_ATTR_SURROGATE_ENABLED, Boolean.TRUE);
}
}Important constants used throughout the surrogate authentication system.
public interface SurrogateAuthenticationService {
/**
* An authorized account may be tagged as a wildcard, meaning
* that the account has special permissions to impersonate anyone.
*/
String WILDCARD_ACCOUNT = "*";
/**
* Default bean name.
*/
String BEAN_NAME = "surrogateAuthenticationService";
/**
* Surrogate username attribute in the authentication payload.
*/
String AUTHENTICATION_ATTR_SURROGATE_USER = "surrogateUser";
/**
* Original credential attribute in the authentication payload.
*/
String AUTHENTICATION_ATTR_SURROGATE_PRINCIPAL = "surrogatePrincipal";
/**
* Indicates that surrogate authn is enabled and activated.
*/
String AUTHENTICATION_ATTR_SURROGATE_ENABLED = "surrogateEnabled";
/**
* Logger instance.
*/
Logger LOGGER = LoggerFactory.getLogger(SurrogateAuthenticationService.class);
}import org.apereo.cas.authentication.surrogate.SurrogateAuthenticationService;
import org.apereo.cas.authentication.principal.Principal;
import org.apereo.cas.authentication.principal.Service;
import java.util.*;
public class SimpleSurrogateAuthenticationService implements SurrogateAuthenticationService {
private final Map<String, List<String>> surrogateMap;
public SimpleSurrogateAuthenticationService(Map<String, List<String>> surrogateMap) {
this.surrogateMap = surrogateMap;
}
@Override
public Collection<String> getImpersonationAccounts(String username, Optional<? extends Service> service) throws Throwable {
return surrogateMap.getOrDefault(username, Collections.emptyList());
}
@Override
public boolean canImpersonate(String surrogate, Principal principal, Optional<? extends Service> service) throws Throwable {
Collection<String> accounts = getImpersonationAccounts(principal.getId(), service);
return accounts.contains(surrogate) || isWildcardedAccount(accounts, service);
}
}// Service that grants wildcard permissions to administrators
public class AdminSurrogateAuthenticationService implements SurrogateAuthenticationService {
private final Set<String> administrators;
public AdminSurrogateAuthenticationService(Set<String> administrators) {
this.administrators = administrators;
}
@Override
public Collection<String> getImpersonationAccounts(String username, Optional<? extends Service> service) throws Throwable {
if (administrators.contains(username)) {
return Collections.singletonList(SurrogateAuthenticationService.WILDCARD_ACCOUNT);
}
return Collections.emptyList();
}
@Override
public boolean canImpersonate(String surrogate, Principal principal, Optional<? extends Service> service) throws Throwable {
return administrators.contains(principal.getId());
}
}import org.apereo.cas.authentication.AuthenticationBuilder;
// During authentication flow
SurrogateAuthenticationService service = // ... get service instance
AuthenticationBuilder builder = // ... authentication builder
// Collect surrogate attributes for authentication context
service.collectSurrogateAttributes(builder, "targetUser", "adminUser");
// The builder now contains:
// - surrogateUser: "targetUser"
// - surrogatePrincipal: "adminUser"
// - surrogateEnabled: trueThis interface depends on types from:
import org.apereo.cas.authentication.AuthenticationBuilder;
import org.apereo.cas.authentication.principal.Principal;
import org.apereo.cas.authentication.principal.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Optional;Install with Tessl CLI
npx tessl i tessl/maven-org-apereo-cas--cas-server-support-surrogate-api