OpenAM and Spring Boot 3 Integration via OpenAM Cookie
Original article: https://github.com/OpenIdentityPlatform/OpenAM/wiki/OpenAM-and-Spring-Boot-3-Integration-via-OpenAM-Cookie
Introduction
In the following article, we will set up OpenAM as an Identity Provider for a Spring Boot Application. In the previous article, we set up a Spring Boot application authentication via OpenAM with SAMLv2 protocol. In the following article, we will set up authentication via OpenAM cookie.
Prerequisites
OpenAM and Spring Boot applications should share same domain. In the following example, OpenAM host is openam.example.org and Spring Boot application host is app.example.org.
To test the example on the local machine, add the following lines to your hosts file:
127.0.0.1 openam.example.org app.example.org
OpenAM Configuration
Open OpenAM administration console. In the top menu go to Configure → Global Services → Platform. Set Cookie Domains as the common domain for the both applications: example.org

Spring Application Configuration
Create a new Spring Boot application and add the following Maven repositories and add the following dependencies:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--security dependencies-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
Add the following settings to the application.yml file
server:
  port: 8081
Create a controller and two endpoints: index and protected-openam. The index endpoint will be accessible for anyone and protected-openam endpoint will be accessible for OpenAM authenticated users.
@Controller
public class SampleController {
    @GetMapping
    public String index() {
        return "index";
    }
    @GetMapping("/protected-openam")
    public String cookieProtected(Model model,  @AuthenticationPrincipal String principal) {
        model.addAttribute("userName", principal);
        model.addAttribute("method", "OpenAM Cookie");
        return "protected";
    }
}
Create the following templates for controllers:
index.html
<!DOCTYPE html><html>
<body>
<h1>OpenAM Spring Security Integration</h1>
<h2>Test Authentication</h2>
<ul>
    <li><a href="/protected-openam">OpenAM Cookie</a></li>
</ul>
</body>
</html>
protected.html
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org">
<body>
<h1>Protected resource</h1>
<a href="/">Back</a></li>
<p><span th:text="${userName}"/> user authenticated with <span th:text="${method}"/></p>
</body>
</html>
Create Spring Security configuration class:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
    @Bean
    public SecurityFilterChain securityOpenAmFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher("/protected-openam", OpenAmAuthenticationFilter.OPENAM_AUTH_URI)
                .addFilterAt(new OpenAmAuthenticationFilter(), RememberMeAuthenticationFilter.class)
                .authorizeHttpRequests((authorize) ->
                        authorize.anyRequest().fullyAuthenticated())
                .exceptionHandling(e ->
                        e.authenticationEntryPoint((request, response, authException) ->
                                response.sendRedirect(OpenAmAuthenticationFilter.OPENAM_AUTH_URI)));
        return http.build();
    }
}
Create OpenAM authentication filter:
public class OpenAmAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    private final String openAmUrl = "http://openam.example.org:8080/openam";
    private final String openAuthUrl = openAmUrl.concat("/XUI/#login");
    private final String openAmUserInfoUrl = openAmUrl.concat("/json/users?_action=idFromSession");
    private final String openAmCookieName = "iPlanetDirectoryPro";
    private final String redirectUrl = "http://app.example.org:8081/protected-openam";
    public static final String OPENAM_AUTH_URI = "/openam-auth";
    public OpenAmAuthenticationFilter() {
        super(OPENAM_AUTH_URI, new OpenAmAuthenticationManager());
        setSecurityContextRepository(new HttpSessionSecurityContextRepository());
    }
    private final AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException {
        Optional<Cookie> openamCookie = Arrays.stream(request.getCookies())
                .filter(c -> c.getName().equals(openAmCookieName)).findFirst();
        if(openamCookie.isEmpty()) {
           response.sendRedirect(openAuthUrl + "&goto=" + URLEncoder.encode(redirectUrl, StandardCharsets.UTF_8));
           return null;
        } else {
            String userId = getUserIdFromSession(openamCookie.get().getValue());
            if (userId == null) {
                throw new BadCredentialsException("invalid session!");
            }
            OpenAmAuthenticationToken token = new OpenAmAuthenticationToken(userId);
            token.setDetails(authenticationDetailsSource.buildDetails(request));
            return this.getAuthenticationManager().authenticate(token);
        }
    }
    protected String getUserIdFromSession(String sessionId) {
        RestTemplate restTemplate = new RestTemplate();
        ParameterizedTypeReference<Map<String, String>> responseType =
                new ParameterizedTypeReference<>() {};
        HttpHeaders headers = new HttpHeaders();
        headers.add(openAmCookieName, sessionId);
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<?> entity = new HttpEntity<>(headers);
        ResponseEntity<Map<String, String>> response = restTemplate.exchange(openAmUserInfoUrl, HttpMethod.POST, entity, responseType);
        Map<String, String> body = response.getBody();
        if (body == null) {
            return null;
        }
        return body.get("id");
    }
}
Create OpenAM authentication manager
public class OpenAmAuthenticationManager implements AuthenticationManager {
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        if(authentication instanceof OpenAmAuthenticationToken) {
            authentication.setAuthenticated(true);
            return authentication;
        }
        authentication.setAuthenticated(false);
        return authentication;
    }
}
and OpenAM authentication token class:
public class OpenAmAuthenticationToken extends AbstractAuthenticationToken {
    private final String username;
    public OpenAmAuthenticationToken(String username) {
        super(Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")));
        this.username = username;
    }
    @Override
    public Object getCredentials() {
        return "";
    }
    @Override
    public Object getPrincipal() {
        return username;
    }
}
Test Solution
Create the demo user for the top level realm for testing purposes. Open OpenAM console, open the top level realm. In the left menu click the Subjects element. In the list of subject click the New button.

Fill the attributes and press the OK  button.
Logout form OpenAM.
Run the Spring application an open its URL in a browser: http://app.example.org:8081.

Click the OpenAM Cookie link. You will be redirected to the OpenAM authentication page.

Enter desired credentials and press the Log In button. After successful authentication you will be redirected to the Spring Boot application page as an authenticated user.

PS. Thanks to https://www.tune-it.ru/web/adpashnin/blog/-/blogs/spring-security-i-openam for the idea for this manual.