Skip to content

Commit

Permalink
Merge pull request #323 from eclipse-ee4j/3.0.0-prepare
Browse files Browse the repository at this point in the history
Merge 3.0.0 prepare to master
  • Loading branch information
arjantijms authored Jun 23, 2022
2 parents 299e0d4 + 8a8a42f commit 04b3bf2
Show file tree
Hide file tree
Showing 105 changed files with 3,137 additions and 1,460 deletions.
5 changes: 3 additions & 2 deletions impl/pom.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation.
Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
Expand Down Expand Up @@ -37,7 +38,7 @@
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>5.1.1</version>
<version>5.1.4</version>
<extensions>true</extensions>
<configuration>
<instructions>
Expand Down Expand Up @@ -82,7 +83,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<version>3.2.2</version>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@
import jakarta.security.enterprise.CallerPrincipal;

public class WrappingCallerPrincipal extends CallerPrincipal {

private static final long serialVersionUID = 1L;

private final Principal wrapped;

public WrappingCallerPrincipal(Principal wrapped) {
super(wrapped.getName());
this.wrapped = wrapped;
}

public Principal getWrapped() {
return wrapped;
}
Expand Down
142 changes: 116 additions & 26 deletions impl/src/main/java/org/glassfish/soteria/cdi/CdiExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import static org.glassfish.soteria.cdi.CdiUtils.addAnnotatedTypes;
import static org.glassfish.soteria.cdi.CdiUtils.getAnnotation;
import static org.glassfish.soteria.cdi.CdiUtils.getBeanReference;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
Expand All @@ -28,13 +29,39 @@
import java.util.logging.Level;
import java.util.logging.Logger;

import org.glassfish.soteria.SecurityContextImpl;
import org.glassfish.soteria.SoteriaServiceProviders;
import org.glassfish.soteria.cdi.spi.BeanDecorator;
import org.glassfish.soteria.cdi.spi.WebXmlLoginConfig;
import org.glassfish.soteria.identitystores.DatabaseIdentityStore;
import org.glassfish.soteria.identitystores.EmbeddedIdentityStore;
import org.glassfish.soteria.identitystores.LdapIdentityStore;
import org.glassfish.soteria.identitystores.annotation.EmbeddedIdentityStoreDefinition;
import org.glassfish.soteria.identitystores.hash.Pbkdf2PasswordHashImpl;
import org.glassfish.soteria.mechanisms.BasicAuthenticationMechanism;
import org.glassfish.soteria.mechanisms.CustomFormAuthenticationMechanism;
import org.glassfish.soteria.mechanisms.FormAuthenticationMechanism;
import org.glassfish.soteria.mechanisms.OpenIdAuthenticationMechanism;
import org.glassfish.soteria.mechanisms.openid.OpenIdIdentityStore;
import org.glassfish.soteria.mechanisms.openid.controller.AuthenticationController;
import org.glassfish.soteria.mechanisms.openid.controller.ConfigurationController;
import org.glassfish.soteria.mechanisms.openid.controller.JWTValidator;
import org.glassfish.soteria.mechanisms.openid.controller.NonceController;
import org.glassfish.soteria.mechanisms.openid.controller.ProviderMetadataController;
import org.glassfish.soteria.mechanisms.openid.controller.StateController;
import org.glassfish.soteria.mechanisms.openid.controller.TokenController;
import org.glassfish.soteria.mechanisms.openid.controller.UserInfoController;
import org.glassfish.soteria.mechanisms.openid.domain.OpenIdContextImpl;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.event.Observes;
import jakarta.enterprise.inject.spi.AfterBeanDiscovery;
import jakarta.enterprise.inject.spi.Annotated;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.enterprise.inject.spi.BeforeBeanDiscovery;
import jakarta.enterprise.inject.spi.DefinitionException;
import jakarta.enterprise.inject.spi.Extension;
import jakarta.enterprise.inject.spi.ProcessBean;
import jakarta.security.enterprise.authentication.mechanism.http.AutoApplySession;
Expand All @@ -43,25 +70,13 @@
import jakarta.security.enterprise.authentication.mechanism.http.FormAuthenticationMechanismDefinition;
import jakarta.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism;
import jakarta.security.enterprise.authentication.mechanism.http.LoginToContinue;
import jakarta.security.enterprise.authentication.mechanism.http.OpenIdAuthenticationMechanismDefinition;
import jakarta.security.enterprise.authentication.mechanism.http.RememberMe;
import jakarta.security.enterprise.identitystore.DatabaseIdentityStoreDefinition;
import jakarta.security.enterprise.identitystore.IdentityStore;
import jakarta.security.enterprise.identitystore.IdentityStoreHandler;
import jakarta.security.enterprise.identitystore.LdapIdentityStoreDefinition;

import org.glassfish.soteria.SecurityContextImpl;
import org.glassfish.soteria.SoteriaServiceProviders;
import org.glassfish.soteria.cdi.spi.BeanDecorator;
import org.glassfish.soteria.cdi.spi.WebXmlLoginConfig;
import org.glassfish.soteria.identitystores.DatabaseIdentityStore;
import org.glassfish.soteria.identitystores.EmbeddedIdentityStore;
import org.glassfish.soteria.identitystores.LdapIdentityStore;
import org.glassfish.soteria.identitystores.annotation.EmbeddedIdentityStoreDefinition;
import org.glassfish.soteria.identitystores.hash.Pbkdf2PasswordHashImpl;
import org.glassfish.soteria.mechanisms.BasicAuthenticationMechanism;
import org.glassfish.soteria.mechanisms.CustomFormAuthenticationMechanism;
import org.glassfish.soteria.mechanisms.FormAuthenticationMechanism;

public class CdiExtension implements Extension {

private static final Logger LOGGER = Logger.getLogger(CdiExtension.class.getName());
Expand All @@ -71,6 +86,8 @@ public class CdiExtension implements Extension {
// This could be extended later to support multiple
private List<Bean<IdentityStore>> identityStoreBeans = new ArrayList<>();
private Bean<HttpAuthenticationMechanism> authenticationMechanismBean;
private List<Bean<?>> extraBeans = new ArrayList<>();

private boolean httpAuthenticationMechanismFound;

public void register(@Observes BeforeBeanDiscovery beforeBean, BeanManager beanManager) {
Expand All @@ -82,15 +99,27 @@ public void register(@Observes BeforeBeanDiscovery beforeBean, BeanManager beanM
CustomFormAuthenticationMechanism.class,
SecurityContextImpl.class,
IdentityStoreHandler.class,
Pbkdf2PasswordHashImpl.class
Pbkdf2PasswordHashImpl.class,

// OpenID types
AuthenticationController.class,
ConfigurationController.class,
NonceController.class,
ProviderMetadataController.class,
StateController.class,
TokenController.class,
UserInfoController.class,
OpenIdContextImpl.class,
OpenIdIdentityStore.class,
OpenIdAuthenticationMechanism.class,
JWTValidator.class
);
}

public <T> void processBean(@Observes ProcessBean<T> eventIn, BeanManager beanManager) {

ProcessBean<T> event = eventIn; // JDK8 u60 workaround

Class<?> beanClass = event.getBean().getBeanClass();

Optional<EmbeddedIdentityStoreDefinition> optionalEmbeddedStore = getAnnotation(beanManager, event.getAnnotated(), EmbeddedIdentityStoreDefinition.class);
optionalEmbeddedStore.ifPresent(embeddedIdentityStoreDefinition -> {
logActivatedIdentityStore(EmbeddedIdentityStore.class, beanClass);
Expand Down Expand Up @@ -148,8 +177,6 @@ public <T> void processBean(@Observes ProcessBean<T> eventIn, BeanManager beanMa
basicAuthenticationMechanismDefinition)));
});



Optional<FormAuthenticationMechanismDefinition> optionalFormMechanism = getAnnotation(beanManager, event.getAnnotated(), FormAuthenticationMechanismDefinition.class);
optionalFormMechanism.ifPresent(formAuthenticationMechanismDefinition -> {
logActivatedAuthenticationMechanism(FormAuthenticationMechanismDefinition.class, beanClass);
Expand Down Expand Up @@ -183,11 +210,43 @@ public <T> void processBean(@Observes ProcessBean<T> eventIn, BeanManager beanMa

authMethod.setLoginToContinue(
LoginToContinueAnnotationLiteral.eval(customFormAuthenticationMechanismDefinition.loginToContinue()));

return authMethod;
});
});

Optional<OpenIdAuthenticationMechanismDefinition> opentionalOpenIdMechanism = getAnnotation(beanManager, event.getAnnotated(), OpenIdAuthenticationMechanismDefinition.class);
opentionalOpenIdMechanism.ifPresent(definition -> {
logActivatedAuthenticationMechanism(OpenIdAuthenticationMechanismDefinition.class, beanClass);

validateOpenIdParametersFormat(definition);

authenticationMechanismBean = new CdiProducer<HttpAuthenticationMechanism>()
.scope(ApplicationScoped.class)
.beanClass(HttpAuthenticationMechanism.class)
.types(HttpAuthenticationMechanism.class)
.addToId(OpenIdAuthenticationMechanism.class)
.create(e -> getBeanReference(OpenIdAuthenticationMechanism.class));

identityStoreBeans.add(new CdiProducer<IdentityStore>()
.scope(ApplicationScoped.class)
.beanClass(IdentityStore.class)
.types(IdentityStore.class)
.addToId(OpenIdIdentityStore.class)
.create(e -> getBeanReference(OpenIdIdentityStore.class))
);

extraBeans.add(new CdiProducer<OpenIdAuthenticationMechanismDefinition>()
.scope(ApplicationScoped.class)
.beanClass(OpenIdAuthenticationMechanismDefinition.class)
.types(OpenIdAuthenticationMechanismDefinition.class)
.addToId("OpenId Definition")
.create(e -> definition)
);
});



if (event.getBean().getTypes().contains(HttpAuthenticationMechanism.class)) {
// enabled bean implementing the HttpAuthenticationMechanism found
httpAuthenticationMechanismFound = true;
Expand All @@ -207,19 +266,19 @@ public void afterBean(final @Observes AfterBeanDiscovery afterBeanDiscovery, Bea
decorator.decorateBean(identityStoreBean, IdentityStore.class, beanManager));
}
}

if (authenticationMechanismBean == null && loginConfig.getAuthMethod() != null) {

if ("basic".equalsIgnoreCase(loginConfig.getAuthMethod())) {
authenticationMechanismBean = new CdiProducer<HttpAuthenticationMechanism>()
.scope(ApplicationScoped.class)
.beanClass(BasicAuthenticationMechanism.class)
.types(Object.class, HttpAuthenticationMechanism.class, BasicAuthenticationMechanism.class)
.addToId(BasicAuthenticationMechanismDefinition.class)
.create(e ->
.create(e ->
new BasicAuthenticationMechanism(
new BasicAuthenticationMechanismDefinitionAnnotationLiteral(loginConfig.getRealmName())));

httpAuthenticationMechanismFound = true;
} else if ("form".equalsIgnoreCase(loginConfig.getAuthMethod())) {
authenticationMechanismBean = new CdiProducer<HttpAuthenticationMechanism>()
Expand All @@ -232,8 +291,8 @@ public void afterBean(final @Observes AfterBeanDiscovery afterBeanDiscovery, Bea

authMethod.setLoginToContinue(
new LoginToContinueAnnotationLiteral(
loginConfig.getFormLoginPage(),
true, null,
loginConfig.getFormLoginPage(),
true, null,
loginConfig.getFormErrorPage())
);

Expand All @@ -247,7 +306,25 @@ public void afterBean(final @Observes AfterBeanDiscovery afterBeanDiscovery, Bea
afterBeanDiscovery.addBean(
decorator.decorateBean(authenticationMechanismBean, HttpAuthenticationMechanism.class, beanManager));
}


for (Bean<?> bean : extraBeans) {
afterBeanDiscovery.addBean(bean);
}

if (extraBeans.isEmpty()) {
// Publish empty definition to prevent injection errors. The helper components will not work, but
// will not cause definition error. This is quite unlucky situation, but when definition is on an
// alternative bean we don't know before this moment whether the bean is enabled or not.

// Probably can circumvent this using programmatic lookup or Instance injection
afterBeanDiscovery.addBean()
.scope(Dependent.class)
.beanClass(OpenIdAuthenticationMechanismDefinition.class)
.types(OpenIdAuthenticationMechanismDefinition.class)
.id("Null OpenId Definition")
.createWith(cc -> null);
}

afterBeanDiscovery.addBean(
decorator.decorateBean(
new CdiProducer<IdentityStoreHandler>()
Expand Down Expand Up @@ -291,4 +368,17 @@ private void checkForWrongUseOfInterceptors(Annotated annotated, Class<?> beanCl
}
}
}

private void validateOpenIdParametersFormat(OpenIdAuthenticationMechanismDefinition definition) {
for (String extraParameter : definition.extraParameters()) {
String[] parts = extraParameter.split("=");
if (parts.length != 2) {
throw new DefinitionException(
OpenIdAuthenticationMechanismDefinition.class.getSimpleName()
+ ".extraParameters() value '" + extraParameter
+ "' is not of the format key=value"
);
}
}
}
}
Loading

0 comments on commit 04b3bf2

Please sign in to comment.