1

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

  • Spring version - 5.3.13
  • Spring Security version - 5.5.3
  • Omnifaces version - 3.11.2
  • Jakarta EE version - 8
  • Wildfly application container - 23
  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:

  • Do I need to just rip out the old Authentication system that uses Java EE spec?
  • Do I override some part of Spring security so that it is aware of Java EE and JSF?
  • Does JSF need to be configured to talk to Spring security?
  • Is there something higher level abstracted away in the Wildfly application server that needs to be configured?

tl;dr

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

Thanks

tomaytotomato
  • 3,788
  • 16
  • 64
  • 119
  • Please see the preface of the question; because Java EE is antiquated, not flexible and we need to extract authentication outside a monolithic application. – tomaytotomato Dec 17 '21 at 15:04
  • 3
    "because Java EE is antiquated" 1: not even a little bit. 2: why would anyone want to mix spring and javaEE? – K.Nicholas Dec 17 '21 at 15:17
  • 1
    "we need to extract authentication outside a monolithic application" - you can do that perfectly well with Java EE Security. You can install an authentication mechanism inside the app that authenticates with some remote server, or you can even have that authentication mechanism and/or identity store outside the app. – Arjan Tijms Dec 17 '21 at 15:51

1 Answers1

1

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

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
  • Thanks, that PR is not merged. Is there any other "concrete" alternatives to integrate OAuth2 to Java EE? – tomaytotomato Dec 17 '21 at 16:28
  • @tomaytotomato yes, there's a concrete one available from Payara at: https://github.com/payara/ecosystem-security-connectors/tree/master/oauth2 and at maven coordinates `fish.payara.security.connectors:security-connector-oauth2-client` – Arjan Tijms Dec 17 '21 at 21:34
  • I also did one years ago, but tbh I haven't tried this one in ages (my projects now all use JWT), but in case it may be helpful still: https://github.com/omnifaces/soteria-google-oauth-client – Arjan Tijms Dec 17 '21 at 21:36
  • I tried to use the security connector Oauth2 Open ID client but it throws this error: `Error getting ServerAuthContext for authContextId default-host and security domain jaspitest: javax.security.auth.message.AuthException` Does Wildfly23 need special dependencies/configuration from Payara framework? I just have a basic security realm with "jaspitest" – tomaytotomato Dec 21 '21 at 14:56
  • In general, WildFly quite unfortunately and against the Jakarta Security spec, needs a special setting. However, if your current setup already uses Jakarta Security, then this setting would already have been set. See https://stackoverflow.com/questions/70225352/why-does-this-simple-jakarta-security-example-from-soteria-work-on-payara-but-no – Arjan Tijms Dec 21 '21 at 15:57