tomaytotomato
tomaytotomato

Reputation: 4028

Integrating Spring Security with Jakarta EE 8 Security and JSF?

A current application running in Wildfly (Jboss) uses its own Authentication system that internally verifies passwords and credentials on its Database.

This system is no longer viable for the future as we migrate to a microservices pattern, therefore requiring a distributed login system using OpenId Connect protocol for Authentication initially, authorization will come later.

This has been implemented fine with a new Spring boot microservice using Spring security and Spring OAuth2 client, however integrating those libraries with the old Jakarta EE application is proving a challenge.

Implementation

  1. There is an existing Authentication system using Java EE HttpAuthenticationMechanism with a AuthenticatedUser bean which acts like a principal.
  2. I added Spring security and OAuth2 client to the Java EE application. It works fine and redirects people to an AWS Cognito SSO page and redirects back with authorization code after they login.

Here is a diagram summarizing what is currently hacked together

enter image description here

Testing

I created two basic JSF pages with backing beans, one secured with old Javax Security rules defined in web.xml and the other defined in Spring security configuration bean.

With the Spring secured page, I can get the Security context in the bean (I think this uses ThreadLocal)

e.g. Helloworld Backing Bean

@Named
@ViewScoped
public class HelloWorldBacking implements Serializable
{
    private static final long serialVersionUID = 1L;
    
    public String getAuthDetails() {
        SecurityContext context = SecurityContextHolder.getContext();
        Authentication authentication = context.getAuthentication();
        return authentication.getName();
    }
}

Spring Security Config

@Configuration
@EnableWebSecurity
@PropertySource("classpath:application.properties")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    private final String clientSecret;
    private final String clientId;
    private final String issuerUri;

    @Autowired
    public SecurityConfiguration(@Value("${oauth.issuer-uri}") String issuerUri,
                                 @Value("${oauth.client-id}") String clientId,
                                 @Value("${oauth.client-secret}") String clientSecret) {
        this.issuerUri = issuerUri;
        this.clientId = clientId;
        this.clientSecret = clientSecret;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
                .and()
                .csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .and()
                .cors()
                .and()
                .authorizeRequests()
                .antMatchers("/helloworld-spring").hasAuthority("Admin")
                .and()
                .oauth2Login()
                .and()
                .oauth2ResourceServer()
                .jwt();
    }
    ...

However if I don't protect that JSF page with Spring security I cannot get any context.

Problem

When a JSF page has been secured with the old security way, it seems to go down a different path with contexts that are all managed by CDI.

I want to integrate Spring security principal into all parts of the JSF app. So that JSF is aware of it in its context.

Debugging

When debugging some existing pages, it appears that both Auth systems are activated but are divergent and not aware of each other.

Solutions?

As someone who has been spoiled by the luxury of spring boot auto configuration, I am a bit stuck on what to do.

Potentially its an easy fix with just overriding a class, or:

tl;dr

How do I get Spring security to pass its security context to JSF in a Jakarta EE application?

Thanks

Upvotes: 1

Views: 1620

Answers (1)

Arjan Tijms
Arjan Tijms

Reputation: 38163

A current application running in Wildfly (Jboss) uses its own Authentication system that internally verifies passwords and credentials on its Database.

From your diagram, it looks like it's not "its own Authentication system", but it uses Java EE Security. There's no need to replace this with anything Spring.

The best way to make this work is to keep it as is. Java EE Security was specifically designed to work with JSF, and the two integrate together quite well. Bringing your own security system into the mix here is probably asking for problems later.

p.s.

OpenId Connect is currently being included in what's now called Jakarta EE Security, see https://github.com/jakartaee/security/pull/185

Java EE Security on WildFly works really well with the MicroProfile APIs, which includes a JWT Authentication Mechanism. See for example

Upvotes: 1

Related Questions