diff --git a/impl/pom.xml b/impl/pom.xml index 5483146f..c9ddc779 100755 --- a/impl/pom.xml +++ b/impl/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 javax.security.enterprise @@ -63,8 +63,8 @@ - javax.security.enterprise - javax.security.enterprise-api + jakarta.security.enterprise + jakarta.security.enterprise-api ${api_dependency_version} diff --git a/impl/src/main/java/org/glassfish/soteria/cdi/AnyAnnotationLiteral.java b/impl/src/main/java/org/glassfish/soteria/cdi/AnyAnnotationLiteral.java index c559e27a..dc033f0b 100644 --- a/impl/src/main/java/org/glassfish/soteria/cdi/AnyAnnotationLiteral.java +++ b/impl/src/main/java/org/glassfish/soteria/cdi/AnyAnnotationLiteral.java @@ -48,6 +48,6 @@ * */ @SuppressWarnings("all") -class AnyAnnotationLiteral extends AnnotationLiteral implements Any { +public class AnyAnnotationLiteral extends AnnotationLiteral implements Any { private static final long serialVersionUID = 1L; } diff --git a/impl/src/main/java/org/glassfish/soteria/cdi/AutoApplySessionInterceptor.java b/impl/src/main/java/org/glassfish/soteria/cdi/AutoApplySessionInterceptor.java index 579bb48f..1c04707b 100644 --- a/impl/src/main/java/org/glassfish/soteria/cdi/AutoApplySessionInterceptor.java +++ b/impl/src/main/java/org/glassfish/soteria/cdi/AutoApplySessionInterceptor.java @@ -50,7 +50,6 @@ import java.security.Principal; import javax.annotation.Priority; -import javax.el.ELProcessor; import javax.interceptor.AroundInvoke; import javax.interceptor.Interceptor; import javax.interceptor.InvocationContext; diff --git a/impl/src/main/java/org/glassfish/soteria/cdi/CdiProducer.java b/impl/src/main/java/org/glassfish/soteria/cdi/CdiProducer.java index 63802e8a..35a79792 100644 --- a/impl/src/main/java/org/glassfish/soteria/cdi/CdiProducer.java +++ b/impl/src/main/java/org/glassfish/soteria/cdi/CdiProducer.java @@ -128,54 +128,54 @@ public boolean isNullable() { return false; } - protected CdiProducer active(boolean active) { + public CdiProducer active(boolean active) { return this; } - protected CdiProducer name(String name) { + public CdiProducer name(String name) { this.name = name; return this; } - protected CdiProducer create(Function, T> create) { + public CdiProducer create(Function, T> create) { this.create = create; return this; } - protected CdiProducer beanClass(Class beanClass) { + public CdiProducer beanClass(Class beanClass) { this.beanClass = beanClass; return this; } - protected CdiProducer types(Type... types) { + public CdiProducer types(Type... types) { this.types = asSet(types); return this; } - protected CdiProducer beanClassAndType(Class beanClass) { + public CdiProducer beanClassAndType(Class beanClass) { beanClass(beanClass); types(beanClass); return this; } - protected CdiProducer qualifiers(Annotation... qualifiers) { + public CdiProducer qualifiers(Annotation... qualifiers) { this.qualifiers = asSet(qualifiers); return this; } - protected CdiProducer scope(Class scope) { + public CdiProducer scope(Class scope) { this.scope = scope; return this; } - protected CdiProducer addToId(Object object) { + public CdiProducer addToId(Object object) { id = id + " " + object.toString(); return this; } @SafeVarargs - protected static Set asSet(T... a) { + public static Set asSet(T... a) { return new HashSet<>(asList(a)); } diff --git a/impl/src/main/java/org/glassfish/soteria/cdi/DefaultAnnotationLiteral.java b/impl/src/main/java/org/glassfish/soteria/cdi/DefaultAnnotationLiteral.java index c5d0f3d8..3056ab74 100644 --- a/impl/src/main/java/org/glassfish/soteria/cdi/DefaultAnnotationLiteral.java +++ b/impl/src/main/java/org/glassfish/soteria/cdi/DefaultAnnotationLiteral.java @@ -48,6 +48,6 @@ * */ @SuppressWarnings("all") -class DefaultAnnotationLiteral extends AnnotationLiteral implements Default { +public class DefaultAnnotationLiteral extends AnnotationLiteral implements Default { private static final long serialVersionUID = 1L; } diff --git a/impl/src/main/java/org/glassfish/soteria/cdi/DefaultIdentityStoreHandler.java b/impl/src/main/java/org/glassfish/soteria/cdi/DefaultIdentityStoreHandler.java index 53836caf..73a4a926 100644 --- a/impl/src/main/java/org/glassfish/soteria/cdi/DefaultIdentityStoreHandler.java +++ b/impl/src/main/java/org/glassfish/soteria/cdi/DefaultIdentityStoreHandler.java @@ -40,18 +40,12 @@ package org.glassfish.soteria.cdi; -import javax.security.enterprise.CallerPrincipal; -import javax.security.enterprise.credential.Credential; -import javax.security.enterprise.identitystore.CredentialValidationResult; -import javax.security.enterprise.identitystore.IdentityStore; -import javax.security.enterprise.identitystore.IdentityStoreHandler; - import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toList; import static javax.security.enterprise.identitystore.CredentialValidationResult.INVALID_RESULT; import static javax.security.enterprise.identitystore.CredentialValidationResult.NOT_VALIDATED_RESULT; -import static javax.security.enterprise.identitystore.CredentialValidationResult.Status.VALID; import static javax.security.enterprise.identitystore.CredentialValidationResult.Status.INVALID; +import static javax.security.enterprise.identitystore.CredentialValidationResult.Status.VALID; import static javax.security.enterprise.identitystore.IdentityStore.ValidationType.PROVIDE_GROUPS; import static javax.security.enterprise.identitystore.IdentityStore.ValidationType.VALIDATE; import static org.glassfish.soteria.cdi.CdiUtils.getBeanReferencesByType; @@ -62,6 +56,11 @@ import java.util.List; import java.util.Set; +import javax.security.enterprise.credential.Credential; +import javax.security.enterprise.identitystore.CredentialValidationResult; +import javax.security.enterprise.identitystore.IdentityStore; +import javax.security.enterprise.identitystore.IdentityStoreHandler; + /** * diff --git a/impl/src/main/java/org/glassfish/soteria/cdi/LdapIdentityStoreDefinitionAnnotationLiteral.java b/impl/src/main/java/org/glassfish/soteria/cdi/LdapIdentityStoreDefinitionAnnotationLiteral.java index 0b437f92..4095805f 100644 --- a/impl/src/main/java/org/glassfish/soteria/cdi/LdapIdentityStoreDefinitionAnnotationLiteral.java +++ b/impl/src/main/java/org/glassfish/soteria/cdi/LdapIdentityStoreDefinitionAnnotationLiteral.java @@ -311,7 +311,7 @@ public String readTimeoutExpression() { @Override public String url() { - return url; + return hasDeferredExpressions? evalELExpression(url) : url; } @Override diff --git a/impl/src/main/java/org/glassfish/soteria/cdi/LoginToContinueInterceptor.java b/impl/src/main/java/org/glassfish/soteria/cdi/LoginToContinueInterceptor.java index 2fb4a9aa..4acf9dea 100644 --- a/impl/src/main/java/org/glassfish/soteria/cdi/LoginToContinueInterceptor.java +++ b/impl/src/main/java/org/glassfish/soteria/cdi/LoginToContinueInterceptor.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ - +// Portions Copyright [2018] Payara Foundation and/or affiliates package org.glassfish.soteria.cdi; import static java.lang.Boolean.TRUE; @@ -85,12 +85,14 @@ public class LoginToContinueInterceptor implements Serializable { private static final long serialVersionUID = 1L; - @Inject - private BeanManager beanManager; + private final BeanManager beanManager; + private final Bean interceptedBean; @Inject - @Intercepted - private Bean interceptedBean; + public LoginToContinueInterceptor(BeanManager beanManager, @Intercepted Bean interceptedBean) { + this.beanManager = beanManager; + this.interceptedBean = interceptedBean; + } @AroundInvoke public Object intercept(InvocationContext invocationContext) throws Exception { diff --git a/impl/src/main/java/org/glassfish/soteria/cdi/RememberMeInterceptor.java b/impl/src/main/java/org/glassfish/soteria/cdi/RememberMeInterceptor.java index 51c15297..d9d121a3 100644 --- a/impl/src/main/java/org/glassfish/soteria/cdi/RememberMeInterceptor.java +++ b/impl/src/main/java/org/glassfish/soteria/cdi/RememberMeInterceptor.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ - +// Portions Copyright [2018] Payara Foundation and/or affiliates package org.glassfish.soteria.cdi; import static javax.interceptor.Interceptor.Priority.PLATFORM_BEFORE; @@ -84,12 +84,14 @@ public class RememberMeInterceptor implements Serializable { private static final long serialVersionUID = 1L; - @Inject - private BeanManager beanManager; + private final BeanManager beanManager; + private final Bean interceptedBean; @Inject - @Intercepted - private Bean interceptedBean; + public RememberMeInterceptor(BeanManager beanManager, @Intercepted Bean interceptedBean) { + this.beanManager = beanManager; + this.interceptedBean = interceptedBean; + } @AroundInvoke public Object intercept(InvocationContext invocationContext) throws Exception { diff --git a/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreConfigurationException.java b/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreConfigurationException.java index 320d56a3..c77cb9ea 100644 --- a/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreConfigurationException.java +++ b/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreConfigurationException.java @@ -42,15 +42,17 @@ public class IdentityStoreConfigurationException extends IdentityStoreException { - public IdentityStoreConfigurationException(String message, Throwable cause) { - super(message,cause); - } + private static final long serialVersionUID = 1L; - public IdentityStoreConfigurationException(Throwable cause) { - super(cause); - } + public IdentityStoreConfigurationException(String message, Throwable cause) { + super(message, cause); + } - public IdentityStoreConfigurationException(String message) { - super(message); - } + public IdentityStoreConfigurationException(Throwable cause) { + super(cause); + } + + public IdentityStoreConfigurationException(String message) { + super(message); + } } diff --git a/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreException.java b/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreException.java index 8f6dd58d..53ef3895 100644 --- a/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreException.java +++ b/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreException.java @@ -42,15 +42,17 @@ public class IdentityStoreException extends RuntimeException { - public IdentityStoreException(String message, Throwable cause) { - super(message,cause); - } + private static final long serialVersionUID = 1L; - public IdentityStoreException(Throwable cause) { - super(cause); - } + public IdentityStoreException(String message, Throwable cause) { + super(message, cause); + } - public IdentityStoreException(String message) { - super(message); - } + public IdentityStoreException(Throwable cause) { + super(cause); + } + + public IdentityStoreException(String message) { + super(message); + } } diff --git a/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreRuntimeException.java b/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreRuntimeException.java index a98d5541..cef585bc 100644 --- a/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreRuntimeException.java +++ b/impl/src/main/java/org/glassfish/soteria/identitystores/IdentityStoreRuntimeException.java @@ -42,15 +42,17 @@ public class IdentityStoreRuntimeException extends IdentityStoreException { - public IdentityStoreRuntimeException(String message, Throwable cause) { - super(message,cause); - } + private static final long serialVersionUID = 1L; - public IdentityStoreRuntimeException(Throwable cause) { - super(cause); - } + public IdentityStoreRuntimeException(String message, Throwable cause) { + super(message, cause); + } - public IdentityStoreRuntimeException(String message) { - super(message); - } + public IdentityStoreRuntimeException(Throwable cause) { + super(cause); + } + + public IdentityStoreRuntimeException(String message) { + super(message); + } } diff --git a/impl/src/main/java/org/glassfish/soteria/identitystores/LdapIdentityStore.java b/impl/src/main/java/org/glassfish/soteria/identitystores/LdapIdentityStore.java index 800aadae..8020e2ca 100644 --- a/impl/src/main/java/org/glassfish/soteria/identitystores/LdapIdentityStore.java +++ b/impl/src/main/java/org/glassfish/soteria/identitystores/LdapIdentityStore.java @@ -41,65 +41,56 @@ package org.glassfish.soteria.identitystores; +import static java.lang.String.format; +import static java.util.Arrays.asList; +import static java.util.Collections.emptySet; +import static java.util.Collections.list; +import static java.util.Collections.unmodifiableSet; +import static javax.naming.Context.INITIAL_CONTEXT_FACTORY; +import static javax.naming.Context.PROVIDER_URL; +import static javax.naming.Context.SECURITY_AUTHENTICATION; +import static javax.naming.Context.SECURITY_CREDENTIALS; +import static javax.naming.Context.SECURITY_PRINCIPAL; +import static javax.naming.directory.SearchControls.ONELEVEL_SCOPE; +import static javax.naming.directory.SearchControls.SUBTREE_SCOPE; +import static javax.security.enterprise.identitystore.CredentialValidationResult.INVALID_RESULT; +import static javax.security.enterprise.identitystore.CredentialValidationResult.NOT_VALIDATED_RESULT; +import static javax.security.enterprise.identitystore.IdentityStore.ValidationType.PROVIDE_GROUPS; +import static javax.security.enterprise.identitystore.LdapIdentityStoreDefinition.LdapSearchScope.ONE_LEVEL; +import static javax.security.enterprise.identitystore.LdapIdentityStoreDefinition.LdapSearchScope.SUBTREE; +import static org.glassfish.soteria.Utils.isEmpty; + +import java.util.HashSet; +import java.util.Hashtable; +import java.util.List; +import java.util.Set; + import javax.naming.AuthenticationException; import javax.naming.CommunicationException; -import javax.naming.InterruptedNamingException; -import javax.naming.InvalidNameException; -import javax.naming.NamingEnumeration; -import javax.naming.NamingException; -import javax.naming.NamingSecurityException; import javax.naming.NameNotFoundException; +import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.InvalidSearchControlsException; import javax.naming.directory.InvalidSearchFilterException; -import javax.naming.directory.NoSuchAttributeException; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.LdapContext; import javax.naming.ldap.LdapName; -import javax.naming.ldap.Rdn; import javax.security.enterprise.credential.Credential; import javax.security.enterprise.credential.UsernamePasswordCredential; import javax.security.enterprise.identitystore.CredentialValidationResult; import javax.security.enterprise.identitystore.IdentityStore; import javax.security.enterprise.identitystore.IdentityStorePermission; import javax.security.enterprise.identitystore.LdapIdentityStoreDefinition; -import java.util.*; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static java.lang.String.format; -import static java.util.Arrays.asList; -import static java.util.Collections.*; -import static java.util.logging.Level.FINEST; -import static javax.naming.Context.*; -import static javax.naming.directory.SearchControls.ONELEVEL_SCOPE; -import static javax.naming.directory.SearchControls.SUBTREE_SCOPE; -import static javax.security.enterprise.identitystore.CredentialValidationResult.INVALID_RESULT; -import static javax.security.enterprise.identitystore.CredentialValidationResult.NOT_VALIDATED_RESULT; -import static javax.security.enterprise.identitystore.LdapIdentityStoreDefinition.LdapSearchScope; +import javax.security.enterprise.identitystore.LdapIdentityStoreDefinition.LdapSearchScope; public class LdapIdentityStore implements IdentityStore { private static final String DEFAULT_USER_FILTER = "(&(%s=%s)(|(objectclass=user)(objectclass=person)(objectclass=inetOrgPerson)(objectclass=organizationalPerson))(!(objectclass=computer)))"; private static final String DEFAULT_GROUP_FILTER = "(&(%s=%s)(|(objectclass=group)(objectclass=groupofnames)(objectclass=groupofuniquenames)))"; - private static final Logger LOGGER = Logger.getLogger("LDAP_IDSTORE_DEBUG"); - -// static { -// LOGGER.setLevel(FINEST); -// } - - private static void debug(String method, String message, Throwable thrown) { - if (thrown != null) { - LOGGER.logp(FINEST, LdapIdentityStore.class.getName(), method, message, thrown); - } - else { - LOGGER.logp(FINEST, LdapIdentityStore.class.getName(), method, message); - } - } private final LdapIdentityStoreDefinition ldapIdentityStoreDefinition; private final Set validationTypes; @@ -157,7 +148,7 @@ private CredentialValidationResult validateCallerAndGetGroups(LdapContext search closeContext(callerContext); Set groups = null; - if (validationTypes().contains(ValidationType.PROVIDE_GROUPS)) { + if (validationTypes().contains(PROVIDE_GROUPS)) { groups = retrieveGroupsForCallerDn(searchContext, callerDn); } @@ -192,8 +183,7 @@ public Set getCallerGroups(CredentialValidationResult validationResult) } private Set retrieveGroupsForCallerDn(LdapContext searchContext, String callerDn) { - - if (callerDn == null || callerDn.isEmpty()) { + if (isEmpty(callerDn)) { return emptySet(); } @@ -328,6 +318,7 @@ private SearchControls getCallerSearchControls() { controls.setSearchScope(convertScopeValue(ldapIdentityStoreDefinition.callerSearchScope())); controls.setCountLimit((long)ldapIdentityStoreDefinition.maxResults()); controls.setTimeLimit(ldapIdentityStoreDefinition.readTimeout()); + return controls; } @@ -337,19 +328,20 @@ private SearchControls getGroupSearchControls() { controls.setCountLimit((long)ldapIdentityStoreDefinition.maxResults()); controls.setTimeLimit(ldapIdentityStoreDefinition.readTimeout()); controls.setReturningAttributes(new String[]{ldapIdentityStoreDefinition.groupNameAttribute()}); + return controls; } private static int convertScopeValue(LdapSearchScope searchScope) { - if (searchScope == LdapSearchScope.ONE_LEVEL) { + if (searchScope == ONE_LEVEL) { return ONELEVEL_SCOPE; } - else if (searchScope == LdapSearchScope.SUBTREE) { + + if (searchScope == SUBTREE) { return SUBTREE_SCOPE; } - else { - return ONELEVEL_SCOPE; - } + + return ONELEVEL_SCOPE; } private LdapContext createSearchLdapContext() { diff --git a/impl/src/main/java/org/glassfish/soteria/identitystores/hash/Pbkdf2PasswordHashImpl.java b/impl/src/main/java/org/glassfish/soteria/identitystores/hash/Pbkdf2PasswordHashImpl.java index b43774e4..72565cc9 100644 --- a/impl/src/main/java/org/glassfish/soteria/identitystores/hash/Pbkdf2PasswordHashImpl.java +++ b/impl/src/main/java/org/glassfish/soteria/identitystores/hash/Pbkdf2PasswordHashImpl.java @@ -176,8 +176,6 @@ private static class EncodedPasswordHash { private byte[] hash; private String encoded; - private EncodedPasswordHash() {}; - EncodedPasswordHash(byte[] hash, byte[] salt, String algorithm, int iterations) { this.algorithm = algorithm; this.iterations = iterations; diff --git a/impl/src/main/java/org/glassfish/soteria/mechanisms/BasicAuthenticationMechanism.java b/impl/src/main/java/org/glassfish/soteria/mechanisms/BasicAuthenticationMechanism.java index 31eaacfb..178e7531 100644 --- a/impl/src/main/java/org/glassfish/soteria/mechanisms/BasicAuthenticationMechanism.java +++ b/impl/src/main/java/org/glassfish/soteria/mechanisms/BasicAuthenticationMechanism.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ - +// Portions Copyright [2018] Payara Foundation and/or affiliates package org.glassfish.soteria.mechanisms; import static java.lang.String.format; @@ -77,7 +77,7 @@ public BasicAuthenticationMechanism(BasicAuthenticationMechanismDefinition basic public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMsgContext) throws AuthenticationException { String[] credentials = getCredentials(request); - if (!isEmpty(credentials)) { + if (!isEmpty(credentials) && credentials.length > 1) { IdentityStoreHandler identityStoreHandler = CDI.current().select(IdentityStoreHandler.class).get(); diff --git a/impl/src/main/java/org/glassfish/soteria/mechanisms/jaspic/HttpBridgeServerAuthModule.java b/impl/src/main/java/org/glassfish/soteria/mechanisms/jaspic/HttpBridgeServerAuthModule.java index 3f30e008..dbea8195 100644 --- a/impl/src/main/java/org/glassfish/soteria/mechanisms/jaspic/HttpBridgeServerAuthModule.java +++ b/impl/src/main/java/org/glassfish/soteria/mechanisms/jaspic/HttpBridgeServerAuthModule.java @@ -37,17 +37,14 @@ * only if the new code is made subject to such option by the copyright * holder. */ +// Portions Copyright 2022 Payara Foundation and/or its affiliates package org.glassfish.soteria.mechanisms.jaspic; -import static javax.security.enterprise.AuthenticationStatus.NOT_DONE; -import static javax.security.enterprise.AuthenticationStatus.SEND_FAILURE; -import static org.glassfish.soteria.mechanisms.jaspic.Jaspic.fromAuthenticationStatus; -import static org.glassfish.soteria.mechanisms.jaspic.Jaspic.setLastAuthenticationStatus; - +import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; -import javax.enterprise.inject.spi.CDI; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.message.AuthException; @@ -64,107 +61,172 @@ import javax.servlet.http.HttpServletResponse; import org.glassfish.soteria.cdi.spi.CDIPerRequestInitializer; +import org.glassfish.soteria.mechanisms.BasicAuthenticationMechanism; +import org.glassfish.soteria.mechanisms.CustomFormAuthenticationMechanism; +import org.glassfish.soteria.mechanisms.FormAuthenticationMechanism; import org.glassfish.soteria.mechanisms.HttpMessageContextImpl; +import static javax.security.enterprise.AuthenticationStatus.NOT_DONE; +import static javax.security.enterprise.AuthenticationStatus.SEND_FAILURE; +import org.glassfish.soteria.cdi.CdiUtils; +import static org.glassfish.soteria.mechanisms.jaspic.Jaspic.fromAuthenticationStatus; +import static org.glassfish.soteria.mechanisms.jaspic.Jaspic.setLastAuthenticationStatus; + /** - * * @author Arjan Tijms - * */ public class HttpBridgeServerAuthModule implements ServerAuthModule { - private CallbackHandler handler; - private final Class[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class }; - private final CDIPerRequestInitializer cdiPerRequestInitializer; - - public HttpBridgeServerAuthModule(CDIPerRequestInitializer cdiPerRequestInitializer) { - this.cdiPerRequestInitializer = cdiPerRequestInitializer; + private final static Map mappings = new HashMap<>(); + + static { + mappings.put("Basic", BasicAuthenticationMechanism.class.getName()); + mappings.put("Form", FormAuthenticationMechanism.class.getName()); + mappings.put("CustomForm", CustomFormAuthenticationMechanism.class.getName()); + mappings.put("JWT", "fish.payara.microprofile.jwtauth.eesecurity.JWTAuthenticationMechanism"); + mappings.put("Certificate", "fish.payara.security.realm.mechanisms.CertificateAuthenticationMechanism"); + mappings.put("OAuth2", "fish.payara.security.oauth2.OAuth2AuthenticationMechanism"); + mappings.put("OIDC", "fish.payara.security.openid.OpenIdAuthenticationMechanism"); + mappings.put("TwoIdentityStore", "fish.payara.security.authentication.twoIdentityStore.TwoIdentityStoreAuthenticationMechanism"); + } + + private final Class[] supportedMessageTypes = new Class[]{HttpServletRequest.class, HttpServletResponse.class}; + + private final CDIPerRequestInitializer cdiPerRequestInitializer; + + private final Map> mechanismClassCache = new ConcurrentHashMap<>(3); + + private CallbackHandler handler; + + public HttpBridgeServerAuthModule(CDIPerRequestInitializer cdiPerRequestInitializer) { + this.cdiPerRequestInitializer = cdiPerRequestInitializer; + } + + @Override + public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, + @SuppressWarnings("rawtypes") Map options) throws AuthException { + this.handler = handler; + // options not supported. + } + + /** + * A Servlet Container Profile compliant implementation should return HttpServletRequest and HttpServletResponse, so + * the delegation class {@link ServerAuthContext} can choose the right SAM to delegate to. + */ + @Override + public Class[] getSupportedMessageTypes() { + return supportedMessageTypes; + } + + @Override + public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { + + HttpMessageContext msgContext = new HttpMessageContextImpl(handler, messageInfo, clientSubject); + + if (cdiPerRequestInitializer != null) { + cdiPerRequestInitializer.init(msgContext.getRequest()); + } + + AuthenticationStatus status = NOT_DONE; + setLastAuthenticationStatus(msgContext.getRequest(), status); + + try { + HttpAuthenticationMechanism mechanismInstance = getMechanism(msgContext); + status = mechanismInstance + .validateRequest( + msgContext.getRequest(), + msgContext.getResponse(), + msgContext); + } catch (AuthenticationException e) { + // In case of an explicit AuthException, status will + // be set to SEND_FAILURE, for any other (non checked) exception + // the status will be the default NOT_DONE + setLastAuthenticationStatus(msgContext.getRequest(), SEND_FAILURE); + throw (AuthException) new AuthException("Authentication failure in HttpAuthenticationMechanism").initCause(e); + } + + setLastAuthenticationStatus(msgContext.getRequest(), status); + + return fromAuthenticationStatus(status); + } + + private HttpAuthenticationMechanism getMechanism(HttpMessageContext ctx) throws AuthException { + String mechanism = getMechanismName(ctx.getRequest()); + Class mechanismClass = findMechanismClass(mechanism); + return CdiUtils.getBeanReference(mechanismClass); // CDI.current() is in context of HttpBridgeServerAuthModule, not the app itself! + } + + private String getMechanismName(HttpServletRequest request) { + return request.getServletContext().getInitParameter("fish.payara.security.mechanism"); + } + + /** + * Define the HttpAuthenticationMechanism to use. based on the 'fish.payara.security.mechanism' context parameter if specified. + * + * @param mechanism + * @return + * @throws ClassNotFoundException + */ + private Class findMechanismClass(String mechanism) throws AuthException { + if (mechanism == null) { + return HttpAuthenticationMechanism.class; } - - @Override - public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, @SuppressWarnings("rawtypes") Map options) throws AuthException { - this.handler = handler; - // options not supported. + String mappedName = mappings.getOrDefault(mechanism, mechanism); + try { + return mechanismClassCache.computeIfAbsent(mappedName, this::loadMechanismClass); + } catch (RuntimeException e) { + throw new AuthException(e.getMessage()); } - /** - * A Servlet Container Profile compliant implementation should return HttpServletRequest and HttpServletResponse, so - * the delegation class {@link ServerAuthContext} can choose the right SAM to delegate to. - */ - @Override - public Class[] getSupportedMessageTypes() { - return supportedMessageTypes; + } + + private Class loadMechanismClass(String mechanism) { + try { + Class mechanismClass = Thread.currentThread().getContextClassLoader().loadClass(mechanism); + if (HttpAuthenticationMechanism.class.isAssignableFrom(mechanismClass)) { + return (Class) mechanismClass; + } else { + throw new IllegalArgumentException("Provided authentication class does not implement HttpAuthentication Mechanism: " + mechanism); + } + } catch (ClassNotFoundException e) { + throw new RuntimeException("HTTP Authentication mechanism class not found " + e.getMessage()); } + } - @Override - public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { - - HttpMessageContext msgContext = new HttpMessageContextImpl(handler, messageInfo, clientSubject); - - if (cdiPerRequestInitializer != null) { - cdiPerRequestInitializer.init(msgContext.getRequest()); + @Override + public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException { + HttpMessageContext msgContext = new HttpMessageContextImpl(handler, messageInfo, null); + + try { + HttpAuthenticationMechanism mechanismInstance = getMechanism(msgContext); + AuthenticationStatus status = mechanismInstance + .secureResponse( + msgContext.getRequest(), + msgContext.getResponse(), + msgContext); + AuthStatus authStatus = fromAuthenticationStatus(status); + if (authStatus == AuthStatus.SUCCESS) { + return AuthStatus.SEND_SUCCESS; } - - AuthenticationStatus status = NOT_DONE; - setLastAuthenticationStatus(msgContext.getRequest(), status); - - try { - status = CDI.current() - .select(HttpAuthenticationMechanism.class).get() - .validateRequest( - msgContext.getRequest(), - msgContext.getResponse(), - msgContext); - } catch (AuthenticationException e) { - // In case of an explicit AuthException, status will - // be set to SEND_FAILURE, for any other (non checked) exception - // the status will be the default NOT_DONE - setLastAuthenticationStatus(msgContext.getRequest(), SEND_FAILURE); - throw (AuthException) new AuthException("Authentication failure in HttpAuthenticationMechanism").initCause(e); + return authStatus; + } catch (AuthenticationException e) { + throw (AuthException) new AuthException("Secure response failure in HttpAuthenticationMechanism").initCause(e); + } finally { + if (cdiPerRequestInitializer != null) { + cdiPerRequestInitializer.destroy(msgContext.getRequest()); } - - setLastAuthenticationStatus(msgContext.getRequest(), status); - - return fromAuthenticationStatus(status); } - @Override - public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException { - HttpMessageContext msgContext = new HttpMessageContextImpl(handler, messageInfo, null); - - try { - AuthenticationStatus status = CDI.current() - .select(HttpAuthenticationMechanism.class).get() - .secureResponse( - msgContext.getRequest(), - msgContext.getResponse(), - msgContext); - AuthStatus authStatus = fromAuthenticationStatus(status); - if (authStatus == AuthStatus.SUCCESS) { - return AuthStatus.SEND_SUCCESS; - } - return authStatus; - } catch (AuthenticationException e) { - throw (AuthException) new AuthException("Secure response failure in HttpAuthenticationMechanism").initCause(e); - } finally { - if (cdiPerRequestInitializer != null) { - cdiPerRequestInitializer.destroy(msgContext.getRequest()); - } - } + } - } + /** + * Called in response to a {@link HttpServletRequest#logout()} call. + */ + @Override + public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException { + HttpMessageContext msgContext = new HttpMessageContextImpl(handler, messageInfo, subject); - /** - * Called in response to a {@link HttpServletRequest#logout()} call. - * - */ - @Override - public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException { - HttpMessageContext msgContext = new HttpMessageContextImpl(handler, messageInfo, subject); - - CDI.current() - .select(HttpAuthenticationMechanism.class).get() - .cleanSubject(msgContext.getRequest(), msgContext.getResponse(), msgContext); - } + getMechanism(msgContext).cleanSubject(msgContext.getRequest(), msgContext.getResponse(), msgContext); + } } diff --git a/impl/src/main/java/org/glassfish/soteria/mechanisms/jaspic/Jaspic.java b/impl/src/main/java/org/glassfish/soteria/mechanisms/jaspic/Jaspic.java index cad18a0e..574763ef 100644 --- a/impl/src/main/java/org/glassfish/soteria/mechanisms/jaspic/Jaspic.java +++ b/impl/src/main/java/org/glassfish/soteria/mechanisms/jaspic/Jaspic.java @@ -47,10 +47,8 @@ import java.security.AccessController; import java.security.Principal; import java.security.PrivilegedAction; -import java.util.List; import java.util.Set; -import javax.security.enterprise.AuthenticationStatus; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; @@ -61,6 +59,7 @@ import javax.security.auth.message.callback.GroupPrincipalCallback; import javax.security.auth.message.config.AuthConfigFactory; import javax.security.auth.message.module.ServerAuthModule; +import javax.security.enterprise.AuthenticationStatus; import javax.security.enterprise.authentication.mechanism.http.AuthenticationParameters; import javax.servlet.ServletContext; import javax.servlet.ServletException; diff --git a/impl/src/main/java/org/glassfish/soteria/servlet/SamRegistrationInstaller.java b/impl/src/main/java/org/glassfish/soteria/servlet/SamRegistrationInstaller.java index d1197a3c..1b143ee1 100644 --- a/impl/src/main/java/org/glassfish/soteria/servlet/SamRegistrationInstaller.java +++ b/impl/src/main/java/org/glassfish/soteria/servlet/SamRegistrationInstaller.java @@ -37,6 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ +// Portions Copyright 2022 Payara Foundation and/or its affiliates package org.glassfish.soteria.servlet; @@ -121,7 +122,7 @@ public void onStartup(Set> c, ServletContext ctx) throws ServletExcepti } registerServerAuthModule(new HttpBridgeServerAuthModule(cdiPerRequestInitializer), ctx); - + // Add a listener so we can process the context destroyed event, which is needed // to de-register the SAM correctly. ctx.addListener(this); diff --git a/pom-p.xml b/pom-p.xml new file mode 100755 index 00000000..c2c788fc --- /dev/null +++ b/pom-p.xml @@ -0,0 +1,175 @@ + + + + 4.0.0 + + org.glassfish.soteria + 1.1-b01.payara-p5-SNAPSHOT + javax.security.enterprise + + jar + + Soteria Reference Implementation + Reference Implementation for Java EE Security API + + + + org.glassfish.soteria.* + + + + + + javax.security.enterprise + javax.security.enterprise-api + ${api_dependency_version} + + + junit + junit + 4.11 + test + + + + + + + org.glassfish.build + spec-version-maven-plugin + 1.2 + + + ${non_final} + impl + ${api_package} + ${impl_namespace} + ${spec_version} + ${new_spec_version} + ${spec_impl_version} + ${spec_build} + ${impl_version} + ${new_impl_version} + ${impl_build} + + + + + + set-spec-properties + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${spec.bundle.symbolic-name} + ${spec.bundle.version} + ${spec.extension.name} + ${spec.implementation.version} + + ${spec_version}.99.${spec_build} + ${packages.export} + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + org.glassfish.build + + + spec-version-maven-plugin + + + [1.2,) + + + + set-spec-properties + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 978e9f2e..137d5b95 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ org.glassfish.soteria parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 pom 2015 @@ -67,7 +67,6 @@ impl - test @@ -86,7 +85,7 @@ the dependency changes. --> 01 - 1.1-b01-SNAPSHOT + 1.0.2 ${spec_impl_version} @@ -108,9 +107,18 @@ release 01 - 1.0 + 1.0.2 + + tests + + true + + + test + + @@ -152,6 +160,21 @@ + + org.apache.maven.plugins + maven-release-plugin + 3.0.0-M7 + + forked-path + false + @{project.version} + ${arguments} + false + payara-artifacts,release + true + true + + org.apache.maven.plugins maven-surefire-plugin @@ -237,24 +260,7 @@ - - org.apache.maven.plugins - maven-release-plugin - 2.5.3 - - forked-path - false - @{project.version} - ${release.arguments} - - - - org.apache.maven.scm - maven-scm-provider-gitexe - 1.8.1 - - - + diff --git a/test/app-custom-identity-store-handler/pom.xml b/test/app-custom-identity-store-handler/pom.xml index 321ed381..f643a8ee 100644 --- a/test/app-custom-identity-store-handler/pom.xml +++ b/test/app-custom-identity-store-handler/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-custom-identity-store-handler @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-custom-rememberme/pom.xml b/test/app-custom-rememberme/pom.xml index b3e6fe99..ebf8956b 100644 --- a/test/app-custom-rememberme/pom.xml +++ b/test/app-custom-rememberme/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-custom-rememberme @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-custom-session/pom.xml b/test/app-custom-session/pom.xml index f4a27420..c50456d2 100644 --- a/test/app-custom-session/pom.xml +++ b/test/app-custom-session/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-custom-session @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-custom/pom.xml b/test/app-custom/pom.xml index 0932d3d0..9e33263c 100644 --- a/test/app-custom/pom.xml +++ b/test/app-custom/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-custom @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-db/pom.xml b/test/app-db/pom.xml index 7f38311a..b612bea0 100644 --- a/test/app-db/pom.xml +++ b/test/app-db/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-db @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-jaxrs/pom.xml b/test/app-jaxrs/pom.xml index cb434aad..ed16008f 100644 --- a/test/app-jaxrs/pom.xml +++ b/test/app-jaxrs/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-jaxrs @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-ldap/pom.xml b/test/app-ldap/pom.xml index 666d5cb1..f431fb6d 100644 --- a/test/app-ldap/pom.xml +++ b/test/app-ldap/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-ldap @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-ldap/src/main/java/org/glassfish/soteria/test/Servlet.java b/test/app-ldap/src/main/java/org/glassfish/soteria/test/Servlet.java index 4aca89a4..6d99ed9e 100644 --- a/test/app-ldap/src/main/java/org/glassfish/soteria/test/Servlet.java +++ b/test/app-ldap/src/main/java/org/glassfish/soteria/test/Servlet.java @@ -56,7 +56,7 @@ * */ @LdapIdentityStoreDefinition( - url = "ldap://localhost:33389/", + url = "#{'ldap://localhost:33389/'}", // usage of expression just for test callerBaseDn = "ou=caller,dc=jsr375,dc=net", groupSearchBase = "ou=group,dc=jsr375,dc=net" ) diff --git a/test/app-ldap2/pom.xml b/test/app-ldap2/pom.xml index 17271ccc..cedb4bcc 100644 --- a/test/app-ldap2/pom.xml +++ b/test/app-ldap2/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 ../pom.xml @@ -65,7 +65,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-ldap3/pom.xml b/test/app-ldap3/pom.xml index 9dc75e1a..38842a5f 100644 --- a/test/app-ldap3/pom.xml +++ b/test/app-ldap3/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 ../pom.xml @@ -65,7 +65,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-mem-basic/pom.xml b/test/app-mem-basic/pom.xml index 41302fbb..d070aedd 100644 --- a/test/app-mem-basic/pom.xml +++ b/test/app-mem-basic/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-mem-basic @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-mem-customform/pom.xml b/test/app-mem-customform/pom.xml index 3d456a75..15a636b5 100644 --- a/test/app-mem-customform/pom.xml +++ b/test/app-mem-customform/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-mem-customform @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-mem-form/pom.xml b/test/app-mem-form/pom.xml index 640024ec..a24c8621 100644 --- a/test/app-mem-form/pom.xml +++ b/test/app-mem-form/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-mem-form @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-mem/pom.xml b/test/app-mem/pom.xml index 9bf898bb..d631a0b1 100644 --- a/test/app-mem/pom.xml +++ b/test/app-mem/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-mem @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-multiple-store-backup/pom.xml b/test/app-multiple-store-backup/pom.xml index cb7abf65..d04662c4 100644 --- a/test/app-multiple-store-backup/pom.xml +++ b/test/app-multiple-store-backup/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-multiple-store-backup @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-multiple-store/pom.xml b/test/app-multiple-store/pom.xml index 88dc6843..1ec7b030 100644 --- a/test/app-multiple-store/pom.xml +++ b/test/app-multiple-store/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-multiple-store @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-securitycontext-auth/pom.xml b/test/app-securitycontext-auth/pom.xml index c0dec370..e97059ec 100644 --- a/test/app-securitycontext-auth/pom.xml +++ b/test/app-securitycontext-auth/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-securitycontext-auth @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-securitycontext-customprincipal/pom.xml b/test/app-securitycontext-customprincipal/pom.xml index 03726203..d70c457a 100644 --- a/test/app-securitycontext-customprincipal/pom.xml +++ b/test/app-securitycontext-customprincipal/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-securitycontext-customprincipal @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/app-securitycontext/pom.xml b/test/app-securitycontext/pom.xml index ebe8c933..201a76e9 100644 --- a/test/app-securitycontext/pom.xml +++ b/test/app-securitycontext/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 app-securitycontext @@ -64,7 +64,7 @@ org.glassfish.soteria.test common - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 diff --git a/test/common/pom.xml b/test/common/pom.xml index 443592bd..50682fe9 100644 --- a/test/common/pom.xml +++ b/test/common/pom.xml @@ -46,7 +46,7 @@ org.glassfish.soteria.test parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 common diff --git a/test/pom.xml b/test/pom.xml index 02ad235e..45db3dce 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -47,7 +47,7 @@ org.glassfish.soteria parent - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 org.glassfish.soteria.test @@ -157,7 +157,29 @@ + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + none + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + @@ -171,8 +193,8 @@ provided - javax.security.enterprise - javax.security.enterprise-api + jakarta.security.enterprise + jakarta.security.enterprise-api ${api_dependency_version} provided @@ -195,7 +217,7 @@ org.glassfish.soteria javax.security.enterprise - 1.1-b01-SNAPSHOT + 1.1-b01.payara-p6 @@ -365,8 +387,8 @@ fish.payara.arquillian - arquillian-payara-server-4-managed - 1.0.Beta2 + arquillian-payara-server-remote + 2.5 test