You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by gp...@apache.org on 2012/03/28 00:06:39 UTC
[4/5] DELTASPIKE-127 credential based authentication
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecuredAnnotationAuthorizer.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecuredAnnotationAuthorizer.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecuredAnnotationAuthorizer.java
new file mode 100644
index 0000000..3e629ee
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecuredAnnotationAuthorizer.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.security.impl.authorization;
+
+import org.apache.deltaspike.core.api.provider.BeanProvider;
+import org.apache.deltaspike.security.api.authorization.AccessDecisionState;
+import org.apache.deltaspike.security.api.authorization.AccessDecisionVoter;
+import org.apache.deltaspike.security.api.authorization.AccessDecisionVoterContext;
+import org.apache.deltaspike.security.api.authorization.AccessDeniedException;
+import org.apache.deltaspike.security.api.authorization.SecurityViolation;
+import org.apache.deltaspike.security.api.authorization.annotation.Secured;
+import org.apache.deltaspike.security.api.authorization.annotation.Secures;
+import org.apache.deltaspike.security.spi.authorization.EditableAccessDecisionVoterContext;
+
+import javax.enterprise.context.Dependent;
+import javax.inject.Inject;
+import javax.interceptor.InvocationContext;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Authorizer implementation for the {@link @Secured} annotation
+ */
+@Dependent
+public class SecuredAnnotationAuthorizer
+{
+ @Inject
+ private AccessDecisionVoterContext voterContext;
+
+ @Secures @Secured({ })
+ public boolean doSecuredCheck(InvocationContext invocationContext) throws Exception
+ {
+ Secured secured = null;
+
+ List<Annotation> annotatedTypeMetadata = extractMetadata(invocationContext);
+
+ for (Annotation annotation : annotatedTypeMetadata)
+ {
+ if (Secured.class.isAssignableFrom(annotation.annotationType()))
+ {
+ secured = (Secured) annotation;
+ }
+ else if (voterContext instanceof EditableAccessDecisionVoterContext)
+ {
+ ((EditableAccessDecisionVoterContext) voterContext)
+ .addMetaData(annotation.annotationType().getName(), annotation);
+ }
+ }
+
+ if (secured != null)
+ {
+ Class<? extends AccessDecisionVoter>[] voterClasses = secured.value();
+
+ invokeVoters(invocationContext, Arrays.asList(voterClasses));
+ }
+
+ //needed by @SecurityBindingType
+ //X TODO check the use-cases for it
+ return true;
+ }
+
+ private List<Annotation> extractMetadata(InvocationContext invocationContext)
+ {
+ List<Annotation> result = new ArrayList<Annotation>();
+
+ Method method = invocationContext.getMethod();
+
+ result.addAll(SecurityUtils.getAllAnnotations(method.getAnnotations()));
+ result.addAll(SecurityUtils.getAllAnnotations(method.getDeclaringClass().getAnnotations()));
+
+ return result;
+ }
+
+ /**
+ * Helper for invoking the given {@link AccessDecisionVoter}s
+ *
+ * @param invocationContext current invocation-context (might be null in case of secured views)
+ * @param accessDecisionVoters current access-decision-voters
+ */
+ private void invokeVoters(InvocationContext invocationContext,
+ List<Class<? extends AccessDecisionVoter>> accessDecisionVoters)
+ {
+ if (accessDecisionVoters == null)
+ {
+ return;
+ }
+
+ AccessDecisionState voterState = AccessDecisionState.VOTE_IN_PROGRESS;
+ try
+ {
+ if (voterContext instanceof EditableAccessDecisionVoterContext)
+ {
+ ((EditableAccessDecisionVoterContext) voterContext).setState(voterState);
+ ((EditableAccessDecisionVoterContext) voterContext).setSource(invocationContext);
+ }
+
+ Set<SecurityViolation> violations;
+
+ AccessDecisionVoter voter;
+ for (Class<? extends AccessDecisionVoter> voterClass : accessDecisionVoters)
+ {
+ voter = BeanProvider.getContextualReference(voterClass, false);
+
+ violations = voter.checkPermission(voterContext);
+
+ if (violations != null && violations.size() > 0)
+ {
+ if (voterContext instanceof EditableAccessDecisionVoterContext)
+ {
+ voterState = AccessDecisionState.VIOLATION_FOUND;
+ for (SecurityViolation securityViolation : violations)
+ {
+ ((EditableAccessDecisionVoterContext) voterContext).addViolation(securityViolation);
+ }
+ }
+ throw new AccessDeniedException(violations);
+ }
+ }
+ }
+ finally
+ {
+ if (voterContext instanceof EditableAccessDecisionVoterContext)
+ {
+ if (AccessDecisionState.VOTE_IN_PROGRESS.equals(voterState))
+ {
+ voterState = AccessDecisionState.NO_VIOLATION_FOUND;
+ }
+
+ ((EditableAccessDecisionVoterContext) voterContext).setState(voterState);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityExtension.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityExtension.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityExtension.java
new file mode 100644
index 0000000..8805166
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityExtension.java
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.deltaspike.security.impl.authorization;
+
+import org.apache.deltaspike.core.api.metadata.builder.AnnotatedTypeBuilder;
+import org.apache.deltaspike.core.spi.activation.Deactivatable;
+import org.apache.deltaspike.core.util.ClassDeactivationUtils;
+import org.apache.deltaspike.core.util.ClassUtils;
+import org.apache.deltaspike.security.api.authorization.SecurityDefinitionException;
+import org.apache.deltaspike.security.api.authorization.annotation.Secures;
+import org.apache.deltaspike.security.spi.authentication.Authenticator;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.BeforeShutdown;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.enterprise.inject.spi.ProcessSessionBean;
+import javax.enterprise.inject.spi.SessionBeanType;
+import java.lang.annotation.Annotation;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Extension for processing typesafe security annotations
+ */
+public class SecurityExtension implements Extension, Deactivatable
+{
+ private static final SecurityInterceptorBinding INTERCEPTOR_BINDING = new SecurityInterceptorBindingLiteral();
+
+ //workaround for OWB
+ private static final Map<ClassLoader, SecurityMetaDataStorage> SECURITY_METADATA_STORAGE_MAPPING
+ = new ConcurrentHashMap<ClassLoader, SecurityMetaDataStorage>();
+
+ private Boolean isActivated = null;
+
+ //workaround for OWB
+ public static SecurityMetaDataStorage getMetaDataStorage()
+ {
+ ClassLoader classLoader = ClassUtils.getClassLoader(null);
+
+ SecurityMetaDataStorage securityMetaDataStorage = SECURITY_METADATA_STORAGE_MAPPING.get(classLoader);
+
+ if (securityMetaDataStorage == null)
+ {
+ securityMetaDataStorage = new SecurityMetaDataStorage();
+ SECURITY_METADATA_STORAGE_MAPPING.put(classLoader, securityMetaDataStorage);
+ }
+
+ return securityMetaDataStorage;
+ }
+
+ public static void removeMetaDataStorage()
+ {
+ ClassLoader classLoader = ClassUtils.getClassLoader(null);
+ SECURITY_METADATA_STORAGE_MAPPING.remove(classLoader);
+ }
+
+ protected void init(@Observes BeforeBeanDiscovery afterBeanDiscovery)
+ {
+ initActivation();
+ }
+
+ /**
+ * @param <X>
+ * @param event
+ * @param beanManager
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ public <X> void processAnnotatedType(@Observes ProcessAnnotatedType<X> event, final BeanManager beanManager)
+ {
+ if (!this.isActivated)
+ {
+ return;
+ }
+
+ AnnotatedTypeBuilder<X> builder = null;
+ AnnotatedType<X> type = event.getAnnotatedType();
+
+ boolean isSecured = false;
+
+ // Add the security interceptor to the class if the class is annotated
+ // with a security binding type
+ for (final Annotation annotation : type.getAnnotations())
+ {
+ if (SecurityUtils.isMetaAnnotatedWithSecurityBindingType(annotation))
+ {
+ builder = new AnnotatedTypeBuilder<X>().readFromType(type);
+ builder.addToClass(INTERCEPTOR_BINDING);
+ isSecured = true;
+ break;
+ }
+ }
+
+ // If the class isn't annotated with a security binding type, check if
+ // any of its methods are, and if so, add the security interceptor to the
+ // method
+ if (!isSecured)
+ {
+ for (final AnnotatedMethod<? super X> m : type.getMethods())
+ {
+ if (m.isAnnotationPresent(Secures.class))
+ {
+ registerAuthorizer(m, beanManager);
+ continue;
+ }
+
+ for (final Annotation annotation : m.getAnnotations())
+ {
+ if (SecurityUtils.isMetaAnnotatedWithSecurityBindingType(annotation))
+ {
+ if (builder == null)
+ {
+ builder = new AnnotatedTypeBuilder<X>().readFromType(type);
+ }
+ builder.addToMethod(m, INTERCEPTOR_BINDING);
+ isSecured = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // If either the bean or any of its methods are secured, register it
+ if (isSecured)
+ {
+ getMetaDataStorage().addSecuredType(type);
+ }
+
+ if (builder != null)
+ {
+ event.setAnnotatedType(builder.create());
+ }
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ public void validateBindings(@Observes AfterBeanDiscovery event, BeanManager beanManager)
+ {
+ if (!this.isActivated)
+ {
+ return;
+ }
+
+ SecurityMetaDataStorage metaDataStorage = getMetaDataStorage();
+
+ for (final AnnotatedType<?> type : metaDataStorage.getSecuredTypes())
+ {
+ // Here we simply want to validate that each type that is annotated with
+ // one or more security bindings has a valid authorizer for each binding
+
+ for (final Annotation annotation : type.getJavaClass().getAnnotations())
+ {
+ boolean found = false;
+
+ if (SecurityUtils.isMetaAnnotatedWithSecurityBindingType(annotation))
+ {
+ // Validate the authorizer
+ for (Authorizer auth : metaDataStorage.getAuthorizers())
+ {
+ if (auth.matchesBinding(annotation))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ event.addDefinitionError(new SecurityDefinitionException("Secured type " +
+ type.getJavaClass().getName() +
+ " has no matching authorizer method for security binding @" +
+ annotation.annotationType().getName()));
+ }
+ }
+ }
+
+ for (final AnnotatedMethod<?> method : type.getMethods())
+ {
+ for (final Annotation annotation : method.getAnnotations())
+ {
+ if (SecurityUtils.isMetaAnnotatedWithSecurityBindingType(annotation))
+ {
+ metaDataStorage.registerSecuredMethod(type.getJavaClass(), method.getJavaMember());
+ break;
+ }
+ }
+ }
+ }
+
+ // Clear securedTypes, we don't require it any more
+ metaDataStorage.resetSecuredTypes();
+ }
+
+ protected void cleanup(@Observes BeforeShutdown beforeShutdown)
+ {
+ removeMetaDataStorage();
+ }
+
+ /**
+ * Registers the specified authorizer method (i.e. a method annotated with
+ * the @Secures annotation)
+ *
+ * @param m
+ * @param beanManager
+ * @throws SecurityDefinitionException
+ */
+ private void registerAuthorizer(AnnotatedMethod<?> m, BeanManager beanManager)
+ {
+ if (!m.getJavaMember().getReturnType().equals(Boolean.class) &&
+ !m.getJavaMember().getReturnType().equals(Boolean.TYPE))
+ {
+ throw new SecurityDefinitionException("Invalid authorizer method [" +
+ m.getJavaMember().getDeclaringClass().getName() + "." +
+ m.getJavaMember().getName() + "] - does not return a boolean.");
+ }
+
+ // Locate the binding type
+ Annotation binding = null;
+
+ for (Annotation annotation : m.getAnnotations())
+ {
+ if (SecurityUtils.isMetaAnnotatedWithSecurityBindingType(annotation))
+ {
+ if (binding != null)
+ {
+ throw new SecurityDefinitionException("Invalid authorizer method [" +
+ m.getJavaMember().getDeclaringClass().getName() + "." +
+ m.getJavaMember().getName() + "] - declares multiple security binding types");
+ }
+ binding = annotation;
+ }
+ }
+
+ Authorizer authorizer = new Authorizer(binding, m, beanManager);
+ getMetaDataStorage().addAuthorizer(authorizer);
+ }
+
+ /**
+ * Ensures that any implementations of the Authenticator interface are not stateless session beans.
+ *
+ * @param event
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ public void validateAuthenticatorImplementation(@Observes ProcessSessionBean<Authenticator> event)
+ {
+ if (!this.isActivated)
+ {
+ return;
+ }
+
+ if (SessionBeanType.STATELESS.equals(event.getSessionBeanType()))
+ {
+ event.addDefinitionError(new IllegalStateException("Authenticator " +
+ event.getBean().getClass() + " cannot be a Stateless Session Bean"));
+ }
+ }
+
+ public void initActivation()
+ {
+ if (isActivated == null)
+ {
+ isActivated = ClassDeactivationUtils.isActivated(getClass());
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptor.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptor.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptor.java
new file mode 100644
index 0000000..277bac1
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptor.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.security.impl.authorization;
+
+import org.apache.deltaspike.security.spi.authorization.SecurityStrategy;
+
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+import java.io.Serializable;
+
+/**
+ * Interceptor for {@link SecurityInterceptorBinding} - details see {@link SecurityStrategy}
+ */
+@SecurityInterceptorBinding
+@Interceptor
+public class SecurityInterceptor implements Serializable
+{
+ private static final long serialVersionUID = -7094673146532371976L;
+
+ @Inject
+ private SecurityStrategy securityStrategy;
+
+ @AroundInvoke
+ public Object filterDeniedInvocations(InvocationContext invocationContext) throws Exception
+ {
+ return this.securityStrategy.execute(invocationContext);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptorBinding.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptorBinding.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptorBinding.java
new file mode 100644
index 0000000..0cd3dd6
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptorBinding.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package org.apache.deltaspike.security.impl.authorization;
+
+import javax.interceptor.InterceptorBinding;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Interceptor binding type for SecurityInterceptor. Users should not apply
+ * this binding themselves, it is applied by the security portable extension.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@InterceptorBinding
+@Target({ElementType.TYPE, ElementType.METHOD })
+@interface SecurityInterceptorBinding
+{
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptorBindingLiteral.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptorBindingLiteral.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptorBindingLiteral.java
new file mode 100644
index 0000000..5888e0c
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityInterceptorBindingLiteral.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package org.apache.deltaspike.security.impl.authorization;
+
+import javax.enterprise.util.AnnotationLiteral;
+
+/**
+ * Annotation literal for SecurityInterceptorBinding
+ */
+class SecurityInterceptorBindingLiteral extends AnnotationLiteral<SecurityInterceptorBinding>
+ implements SecurityInterceptorBinding
+{
+ private static final long serialVersionUID = 2189092542638784524L;
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityMetaDataStorage.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityMetaDataStorage.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityMetaDataStorage.java
new file mode 100644
index 0000000..298256e
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityMetaDataStorage.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.security.impl.authorization;
+
+import org.apache.deltaspike.security.api.authorization.SecurityDefinitionException;
+
+import javax.enterprise.inject.spi.AnnotatedType;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ */
+class SecurityMetaDataStorage
+{
+ /**
+ * Contains all known authorizers
+ */
+ private Set<Authorizer> authorizers = new HashSet<Authorizer>();
+
+ /**
+ * Contains all known secured types
+ */
+ private Set<AnnotatedType<?>> securedTypes = new HashSet<AnnotatedType<?>>();
+
+ /**
+ * A mapping between a secured method of a class and its authorizers
+ */
+ private Map<Class<?>, Map<Method, Set<Authorizer>>> methodAuthorizers =
+ new HashMap<Class<?>, Map<Method, Set<Authorizer>>>();
+
+
+ void addAuthorizer(Authorizer authorizer)
+ {
+ this.authorizers.add(authorizer);
+ }
+
+ void addSecuredType(AnnotatedType<?> annotatedType)
+ {
+ this.securedTypes.add(annotatedType);
+ }
+
+ Set<AnnotatedType<?>> getSecuredTypes()
+ {
+ return securedTypes;
+ }
+
+ void resetSecuredTypes()
+ {
+ this.securedTypes = null;
+ }
+
+ /**
+ * This method is invoked by the security interceptor to obtain the
+ * authorizer stack for a secured method
+ *
+ * @param targetClass
+ * @param targetMethod
+ * @return
+ */
+ Set<Authorizer> getAuthorizers(Class<?> targetClass, Method targetMethod)
+ {
+ if (!isMethodMetaDataAvailable(targetClass, targetMethod))
+ {
+ registerSecuredMethod(targetClass, targetMethod);
+ }
+
+ return getMethodAuthorizers(targetClass, targetMethod);
+ }
+
+ synchronized void registerSecuredMethod(Class<?> targetClass, Method targetMethod)
+ {
+ ensureInitializedAuthorizersForClass(targetClass);
+
+ if (!containsMethodAuthorizers(targetClass, targetMethod))
+ {
+ // Build a list of all security bindings on both the method and its declaring class
+ Set<Annotation> bindings = new HashSet<Annotation>();
+
+ Class<?> cls = targetClass;
+ while (!cls.equals(Object.class))
+ {
+ for (final Annotation annotation : cls.getAnnotations())
+ {
+ if (SecurityUtils.isMetaAnnotatedWithSecurityBindingType(annotation))
+ {
+ bindings.add(annotation);
+ }
+ }
+ cls = cls.getSuperclass();
+ }
+
+ for (final Annotation annotation : targetMethod.getAnnotations())
+ {
+ if (SecurityUtils.isMetaAnnotatedWithSecurityBindingType(annotation))
+ {
+ bindings.add(annotation);
+ }
+ }
+
+ Set<Authorizer> authorizerStack = new HashSet<Authorizer>();
+
+ for (Annotation binding : bindings)
+ {
+ boolean found = false;
+
+ // For each security binding, find a valid authorizer
+ for (Authorizer authorizer : this.authorizers)
+ {
+ if (authorizer.matchesBinding(binding))
+ {
+ if (found)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Matching authorizer methods found: [");
+ sb.append(authorizer.getImplementationMethod().getDeclaringClass().getName());
+ sb.append(".");
+ sb.append(authorizer.getImplementationMethod().getName());
+ sb.append("]");
+
+ for (Authorizer a : authorizerStack)
+ {
+ if (a.matchesBinding(binding))
+ {
+ sb.append(", [");
+ sb.append(a.getImplementationMethod().getDeclaringClass().getName());
+ sb.append(".");
+ sb.append(a.getImplementationMethod().getName());
+ sb.append("]");
+ }
+ }
+
+ throw new SecurityDefinitionException(
+ "Ambiguous authorizers found for security binding type [@" +
+ binding.annotationType().getName() + "] on method [" +
+ targetMethod.getDeclaringClass().getName() + "." +
+ targetMethod.getName() + "]. " + sb.toString());
+ }
+
+ authorizerStack.add(authorizer);
+ found = true;
+ }
+ }
+
+ if (!found)
+ {
+ throw new SecurityDefinitionException(
+ "No matching authorizer found for security binding type [@" +
+ binding.annotationType().getName() + "] on method [" +
+ targetMethod.getDeclaringClass().getName() + "." +
+ targetMethod.getName() + "].");
+ }
+ }
+ addMethodAuthorizer(targetClass, targetMethod, authorizerStack);
+ }
+ }
+
+ Set<Authorizer> getAuthorizers()
+ {
+ return authorizers;
+ }
+
+ private boolean containsMethodAuthorizers(Class<?> targetClass, Method targetMethod)
+ {
+ Map<Method, Set<Authorizer>> resultForClass = this.methodAuthorizers.get(targetClass);
+ return resultForClass.containsKey(targetMethod);
+ }
+
+ private void ensureInitializedAuthorizersForClass(Class<?> targetClass)
+ {
+ Map<Method, Set<Authorizer>> resultForClass = this.methodAuthorizers.get(targetClass);
+
+ if (resultForClass == null)
+ {
+ this.methodAuthorizers.put(targetClass, new HashMap<Method, Set<Authorizer>>());
+ }
+ }
+
+ private boolean isMethodMetaDataAvailable(Class<?> targetClass, Method targetMethod)
+ {
+ Map<Method, Set<Authorizer>> result = this.methodAuthorizers.get(targetClass);
+ return result != null && result.containsKey(targetMethod);
+ }
+
+ private void addMethodAuthorizer(Class<?> targetClass, Method targetMethod, Set<Authorizer> authorizersToAdd)
+ {
+ Map<Method, Set<Authorizer>> authorizerMapping = this.methodAuthorizers.get(targetClass);
+
+ if (authorizerMapping == null)
+ {
+ authorizerMapping = new HashMap<Method, Set<Authorizer>>();
+ this.methodAuthorizers.put(targetClass, authorizerMapping);
+ }
+
+ Set<Authorizer> authorizersForMethod = authorizerMapping.get(targetMethod);
+
+ if (authorizersForMethod == null)
+ {
+ authorizersForMethod = new HashSet<Authorizer>();
+ authorizerMapping.put(targetMethod, authorizersForMethod);
+ }
+
+ authorizersForMethod.addAll(authorizersToAdd);
+ }
+
+ private Set<Authorizer> getMethodAuthorizers(Class<?> targetClass, Method targetMethod)
+ {
+ Map<Method, Set<Authorizer>> resultForClass = this.methodAuthorizers.get(targetClass);
+
+ if (resultForClass == null)
+ {
+ throw new IllegalStateException(
+ "no meta-data available for: " + targetClass.getName() + targetMethod.getName());
+ }
+
+ return resultForClass.get(targetMethod);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityUtils.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityUtils.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityUtils.java
new file mode 100644
index 0000000..4ff9880
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecurityUtils.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.security.impl.authorization;
+
+import org.apache.deltaspike.security.api.authorization.annotation.SecurityBindingType;
+
+import javax.enterprise.inject.Stereotype;
+import javax.enterprise.inject.Typed;
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
+
+@Typed()
+abstract class SecurityUtils
+{
+ private SecurityUtils()
+ {
+ // prevent instantiation
+ }
+
+ static boolean isMetaAnnotatedWithSecurityBindingType(Annotation annotation)
+ {
+ if (annotation.annotationType().isAnnotationPresent(SecurityBindingType.class))
+ {
+ return true;
+ }
+
+ List<Annotation> result = getAllAnnotations(annotation.annotationType().getAnnotations());
+
+ for (Annotation foundAnnotation : result)
+ {
+ if (SecurityBindingType.class.isAssignableFrom(foundAnnotation.annotationType()))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static Annotation resolveSecurityBindingType(Annotation annotation)
+ {
+ List<Annotation> result = getAllAnnotations(annotation.annotationType().getAnnotations());
+
+ for (Annotation foundAnnotation : result)
+ {
+ if (foundAnnotation.annotationType().isAnnotationPresent(SecurityBindingType.class))
+ {
+ return foundAnnotation;
+ }
+ }
+ throw new IllegalStateException(annotation.annotationType().getName() + " is a " + Stereotype.class.getName() +
+ " but it isn't annotated with " + SecurityBindingType.class.getName());
+ }
+
+ static List<Annotation> getAllAnnotations(Annotation[] annotations)
+ {
+ List<Annotation> result = new ArrayList<Annotation>();
+
+ String annotationName;
+ for (Annotation annotation : annotations)
+ {
+ annotationName = annotation.annotationType().getName();
+ if (annotationName.startsWith("java.") || annotationName.startsWith("javax."))
+ {
+ continue;
+ }
+
+ result.add(annotation);
+ result.addAll(getAllAnnotations(annotation.annotationType().getAnnotations()));
+ }
+
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/credential/DefaultLoginCredential.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/credential/DefaultLoginCredential.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/credential/DefaultLoginCredential.java
new file mode 100644
index 0000000..78aaedc
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/credential/DefaultLoginCredential.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.security.impl.credential;
+
+import org.apache.deltaspike.security.api.authentication.events.LoginFailedEvent;
+import org.apache.deltaspike.security.api.authentication.events.PostAuthenticateEvent;
+import org.apache.deltaspike.security.api.credential.Credential;
+import org.apache.deltaspike.security.api.credential.LoginCredential;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.event.Observes;
+import javax.inject.Named;
+
+/**
+ * The default LoginCredential implementation. This implementation allows for a
+ * username and plain text password to be set, and uses the PasswordCredential
+ * implementation of the Credential interface for authentication.
+ */
+@Named("loginCredential")
+@RequestScoped
+public class DefaultLoginCredential implements LoginCredential
+{
+ private Credential credential;
+
+ private String userId;
+
+ @Override
+ public String getUserId()
+ {
+ return userId;
+ }
+
+ @Override
+ public void setUserId(String userId)
+ {
+ this.userId = userId;
+ }
+
+ public Credential getCredential()
+ {
+ return credential;
+ }
+
+ public void setCredential(Credential credential)
+ {
+ this.credential = credential;
+ //X TODO manager.fireEvent(new CredentialsUpdatedEvent(this.credential));
+ }
+
+ public void invalidate()
+ {
+ this.credential = null;
+ this.userId = null;
+ }
+
+ protected void setValid(@Observes PostAuthenticateEvent event)
+ {
+ invalidate();
+ }
+
+ protected void afterLogin(@Observes PostAuthenticateEvent event)
+ {
+ invalidate();
+ }
+
+ //X TODO discuss
+ protected void loginFailed(@Observes LoginFailedEvent event)
+ {
+ invalidate();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "LoginCredential[" + (this.userId != null ? this.userId : "unknown" ) + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/jaas/JaasAuthenticator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/jaas/JaasAuthenticator.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/jaas/JaasAuthenticator.java
deleted file mode 100644
index 36ea6ca..0000000
--- a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/jaas/JaasAuthenticator.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.deltaspike.security.impl.jaas;
-
-import java.io.IOException;
-
-import javax.enterprise.context.RequestScoped;
-import javax.enterprise.inject.spi.BeanManager;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-import org.apache.deltaspike.security.api.BaseAuthenticator;
-import org.apache.deltaspike.security.api.Credentials;
-import org.apache.deltaspike.security.api.Identity;
-import org.apache.deltaspike.security.impl.PasswordCredential;
-import org.apache.deltaspike.security.spi.Authenticator;
-
-/**
- * An authenticator for authenticating with JAAS. The jaasConfigName property
- * _must_ be configured to point to a valid JAAS configuration name, typically
- * defined in a file called login-config.xml in the application server.
- */
-@Named
-@RequestScoped
-public class JaasAuthenticator extends BaseAuthenticator implements Authenticator
-{
- @Inject
- private Identity identity;
-
- @Inject
- private Credentials credentials;
-
- @Inject
- private BeanManager manager;
-
- private Subject subject;
-
- private String jaasConfigName = null;
-
- public JaasAuthenticator()
- {
- subject = new Subject();
- }
-
- public void authenticate()
- {
- if (getJaasConfigName() == null)
- {
- throw new IllegalStateException(
- "jaasConfigName cannot be null. Please set it to a valid JAAS configuration name.");
- }
-
- try
- {
- getLoginContext().login();
- setStatus(AuthenticationStatus.SUCCESS);
- }
- catch (LoginException e)
- {
- setStatus(AuthenticationStatus.FAILURE);
- //log.error("JAAS authentication failed", e);
- }
- }
-
- protected LoginContext getLoginContext() throws LoginException
- {
- return new LoginContext(getJaasConfigName(), subject,
- createCallbackHandler());
- }
-
- /**
- * Creates a callback handler that can handle a standard username/password
- * callback, using the credentials username and password properties
- */
- public CallbackHandler createCallbackHandler()
- {
- return new CallbackHandler()
- {
- public void handle(Callback[] callbacks)
- throws IOException, UnsupportedCallbackException
- {
- for (int i = 0; i < callbacks.length; i++)
- {
- if (callbacks[i] instanceof NameCallback)
- {
- ((NameCallback) callbacks[i]).setName(credentials.getUsername());
- }
- else if (callbacks[i] instanceof PasswordCallback)
- {
- if (credentials.getCredential() instanceof PasswordCredential)
- {
- PasswordCredential credential = (PasswordCredential) credentials.getCredential();
- ((PasswordCallback) callbacks[i]).setPassword(credential.getValue() != null ?
- credential.getValue().toCharArray() : null);
- }
- }
- else
- {
- //log.warn("Unsupported callback " + callbacks[i]);
- }
- }
- }
- };
- }
-
- public String getJaasConfigName()
- {
- return jaasConfigName;
- }
-
- public void setJaasConfigName(String jaasConfigName)
- {
- this.jaasConfigName = jaasConfigName;
- }
-
- public void postAuthenticate()
- {
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/management/IdmAuthenticator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/management/IdmAuthenticator.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/management/IdmAuthenticator.java
deleted file mode 100644
index ba34374..0000000
--- a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/management/IdmAuthenticator.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.deltaspike.security.impl.management;
-
-import org.apache.deltaspike.security.api.User;
-import org.apache.deltaspike.security.spi.Authenticator;
-
-/**
- * Authenticates using the Identity Management API
- *
- * TODO - discuss the Identity Management API before implementing this class
- */
-public class IdmAuthenticator implements Authenticator
-{
-
- @Override
- public void authenticate()
- {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void postAuthenticate()
- {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public AuthenticationStatus getStatus()
- {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public User getUser()
- {
- // TODO Auto-generated method stub
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/resources/META-INF/beans.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/resources/META-INF/beans.xml b/deltaspike/modules/security/impl/src/main/resources/META-INF/beans.xml
index ec7e07b..65b3b51 100644
--- a/deltaspike/modules/security/impl/src/main/resources/META-INF/beans.xml
+++ b/deltaspike/modules/security/impl/src/main/resources/META-INF/beans.xml
@@ -21,6 +21,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<interceptors>
- <class>org.apache.deltaspike.security.impl.SecurityInterceptor</class>
+ <class>org.apache.deltaspike.security.impl.authorization.SecurityInterceptor</class>
</interceptors>
</beans>
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/deltaspike/modules/security/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
index 7973b93..8d0c21d 100644
--- a/deltaspike/modules/security/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
+++ b/deltaspike/modules/security/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -17,4 +17,4 @@
# under the License.
#####################################################################################
-org.apache.deltaspike.security.impl.SecurityExtension
+org.apache.deltaspike.security.impl.authorization.SecurityExtension
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/FailedLoginFailedObserver.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/FailedLoginFailedObserver.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/FailedLoginFailedObserver.java
new file mode 100644
index 0000000..8ed2da3
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/FailedLoginFailedObserver.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authentication;
+
+import org.apache.deltaspike.security.api.authentication.events.LoginFailedEvent;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.event.Observes;
+
+@RequestScoped
+public class FailedLoginFailedObserver
+{
+ private Exception observedException;
+
+ protected void onFailedLogin(@Observes LoginFailedEvent loginFailedEvent)
+ {
+ this.observedException = loginFailedEvent.getLoginException();
+ }
+
+ Exception getObservedException()
+ {
+ return observedException;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InMemoryUserStorage.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InMemoryUserStorage.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InMemoryUserStorage.java
new file mode 100644
index 0000000..1bc9134
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InMemoryUserStorage.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authentication;
+
+import org.apache.deltaspike.core.api.exclude.Exclude;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Exclude
+class InMemoryUserStorage
+{
+ private static Map<String, String> simpleUserPasswordMapping = new ConcurrentHashMap<String, String>();
+
+ static void setPassword(String userName, String password)
+ {
+ simpleUserPasswordMapping.put(userName, password);
+ }
+
+ static String getPassword(String userName)
+ {
+ return simpleUserPasswordMapping.get(userName);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/Inquiry.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/Inquiry.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/Inquiry.java
new file mode 100644
index 0000000..7f16109
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/Inquiry.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authentication;
+
+interface Inquiry
+{
+ String getInquiryId();
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InquiryEntry.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InquiryEntry.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InquiryEntry.java
new file mode 100644
index 0000000..bae1b86
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InquiryEntry.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authentication;
+
+import javax.enterprise.inject.Typed;
+
+@Typed()
+class InquiryEntry
+{
+ private final String userName;
+ private final Inquiry inquiry;
+
+ InquiryEntry(String userName, Inquiry inquiry)
+ {
+ this.userName = userName;
+ this.inquiry = inquiry;
+ }
+
+ String getUserName()
+ {
+ return userName;
+ }
+
+ Inquiry getInquiry()
+ {
+ return inquiry;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ InquiryEntry that = (InquiryEntry) o;
+
+ if (!inquiry.equals(that.inquiry))
+ {
+ return false;
+ }
+ if (!userName.equals(that.userName))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = userName.hashCode();
+ result = 31 * result + inquiry.hashCode();
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InquiryStorage.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InquiryStorage.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InquiryStorage.java
new file mode 100644
index 0000000..1b19cd0
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/InquiryStorage.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authentication;
+
+public interface InquiryStorage
+{
+ boolean addInquiry(Inquiry inquiry);
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/LoginLogoutTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/LoginLogoutTest.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/LoginLogoutTest.java
new file mode 100644
index 0000000..2dbc420
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/LoginLogoutTest.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authentication;
+
+import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
+import org.apache.deltaspike.core.api.provider.BeanProvider;
+import org.apache.deltaspike.core.impl.exclude.ExcludeExtension;
+import org.apache.deltaspike.security.api.Identity;
+import org.apache.deltaspike.security.api.authentication.UnexpectedCredentialException;
+import org.apache.deltaspike.security.api.credential.LoginCredential;
+import org.apache.deltaspike.test.util.ArchiveUtils;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.enterprise.inject.spi.Extension;
+import javax.inject.Inject;
+
+
+/**
+ * Test for {@link org.apache.deltaspike.security.api.authorization.annotation.Secured}
+ */
+@RunWith(Arquillian.class)
+public class LoginLogoutTest
+{
+ @Inject
+ private TestAuthenticator authenticator;
+
+ @Inject
+ private TestInquiryStorage testInquiryStorage;
+
+ @Inject
+ private ShopClient shopClient;
+
+ @Inject
+ private Identity identity;
+
+ @Inject
+ private FailedLoginFailedObserver failedLoginFailedObserver;
+
+ @Deployment
+ public static WebArchive deploy()
+ {
+ new BeanManagerProvider() {
+ @Override
+ public void setTestMode()
+ {
+ super.setTestMode();
+ }
+ }.setTestMode();
+
+ JavaArchive testJar = ShrinkWrap.create(JavaArchive.class, "loginLogoutTest.jar")
+ .addPackage("org.apache.deltaspike.test.security.impl.authentication")
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+
+ return ShrinkWrap.create(WebArchive.class)
+ .addAsLibraries(ArchiveUtils.getDeltaSpikeCoreAndSecurityArchive())
+ .addAsLibraries(testJar)
+ .addAsServiceProvider(Extension.class, ExcludeExtension.class)
+ .addAsWebInfResource(ArchiveUtils.getBeansXml(), "beans.xml");
+ }
+
+ @Test
+ public void loginAndLogout()
+ {
+ final String userName = "spike";
+ final String password = "apache";
+
+ //init
+ this.authenticator.register(userName, password);
+
+ //start
+ this.shopClient.login(userName, password);
+
+ Assert.assertTrue(this.identity.isLoggedIn());
+ Assert.assertEquals(userName, this.identity.getUser().getId());
+
+ Assert.assertNotNull(this.shopClient.requestNewProduct("Security module for DeltaSpike"));
+
+
+ this.shopClient.logout();
+ Assert.assertFalse(this.identity.isLoggedIn());
+
+
+ Assert.assertNotNull(this.shopClient.requestNewProduct("I18n module for DeltaSpike"));
+
+ Assert.assertEquals(1, this.testInquiryStorage.getUserInquiries().size());
+ Assert.assertEquals(userName, this.testInquiryStorage.getUserInquiries().iterator().next().getUserName());
+
+ Assert.assertEquals(1, this.testInquiryStorage.getAnonymInquiries().size());
+
+ Assert.assertFalse(this.testInquiryStorage.getUserInquiries().iterator().next().getInquiry()
+ .equals(this.testInquiryStorage.getAnonymInquiries().iterator()));
+ }
+
+ @Test
+ public void failedLogin()
+ {
+ final String userName = "spike";
+ final String password = "apache";
+
+ //init
+ this.authenticator.register(userName, password);
+
+ //start
+ this.shopClient.login(userName, "123");
+
+ Assert.assertFalse(this.identity.isLoggedIn());
+ }
+
+ //TODO use context-control
+ @Test
+ public void failedForcedReLogin()
+ {
+ final String userName = "spike";
+ final String password = "apache";
+
+ //init
+ this.authenticator.register(userName, password);
+
+ //start
+ this.shopClient.login(userName, password);
+
+ Assert.assertTrue(this.identity.isLoggedIn());
+ Assert.assertEquals(userName, this.identity.getUser().getId());
+
+ //X TODO stop and start new request via ContextControl - instead of:
+ BeanProvider.getContextualReference(LoginCredential.class).invalidate();
+
+ try
+ {
+ this.shopClient.login("xyz", "123");
+ }
+ catch (UnexpectedCredentialException e)
+ {
+ //noinspection ThrowableResultOfMethodCallIgnored
+ Assert.assertTrue(this.failedLoginFailedObserver.getObservedException()
+ instanceof UnexpectedCredentialException);
+
+ // still logged in
+ Assert.assertTrue(this.identity.isLoggedIn());
+ return;
+ }
+
+ Assert.fail();
+ }
+
+ //X TODO add tests for the events
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/NewProductInquiry.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/NewProductInquiry.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/NewProductInquiry.java
new file mode 100644
index 0000000..c037f53
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/NewProductInquiry.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authentication;
+
+import java.util.UUID;
+
+class NewProductInquiry implements Inquiry
+{
+ private String question;
+
+ private String id;
+
+ NewProductInquiry(String question)
+ {
+ this.question = question;
+ this.id = UUID.randomUUID().toString();
+ }
+
+ @Override
+ public String getInquiryId()
+ {
+ return this.id;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.question;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return this.id.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ return obj instanceof NewProductInquiry && this.id.equals(((NewProductInquiry) obj).id);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/Shop.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/Shop.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/Shop.java
new file mode 100644
index 0000000..2fcbdfe
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/Shop.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authentication;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+/**
+ *
+ */
+@ApplicationScoped
+public class Shop
+{
+ @Inject
+ private InquiryStorage inquiryStorage;
+
+ public String sendInquiry(Inquiry inquiry)
+ {
+ if (this.inquiryStorage.addInquiry(inquiry))
+ {
+ return inquiry.getInquiryId();
+ //TODO e.g. send notification in case of inquiries of premium users,...
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/ShopClient.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/ShopClient.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/ShopClient.java
new file mode 100644
index 0000000..158aa7d
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/ShopClient.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authentication;
+
+import org.apache.deltaspike.security.api.Identity;
+import org.apache.deltaspike.security.api.credential.Credential;
+import org.apache.deltaspike.security.api.credential.LoginCredential;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+@ApplicationScoped
+public class ShopClient
+{
+ @Inject
+ private LoginCredential loginCredential;
+
+ @Inject
+ private Identity identity;
+
+ @Inject
+ private Shop shop;
+
+ public void login(String userName, final String password)
+ {
+ this.loginCredential.setUserId(userName);
+ //TODO discuss #setSecurityToken
+ this.loginCredential.setCredential(new Credential<String>() {
+ @Override
+ public String getValue()
+ {
+ return password;
+ }
+ });
+
+ this.identity.login();
+ }
+
+ public void logout()
+ {
+ this.identity.logout();
+ }
+
+ public String requestNewProduct(String customText)
+ {
+ return this.shop.sendInquiry(new NewProductInquiry(customText));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/TestAuthenticator.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/TestAuthenticator.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/TestAuthenticator.java
new file mode 100644
index 0000000..8d4737b
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/TestAuthenticator.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authentication;
+
+import org.apache.deltaspike.security.api.User;
+import org.apache.deltaspike.security.api.credential.LoginCredential;
+import org.apache.deltaspike.security.spi.authentication.BaseAuthenticator;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+
+@RequestScoped
+public class TestAuthenticator extends BaseAuthenticator
+{
+ @Inject
+ private LoginCredential loginCredential;
+
+ private User user;
+
+ @Override
+ public void authenticate()
+ {
+ String password = InMemoryUserStorage.getPassword(this.loginCredential.getUserId());
+
+ if (password != null && password.equals(this.loginCredential.getCredential().getValue()))
+ {
+ setStatus(AuthenticationStatus.SUCCESS);
+ this.user = new User(this.loginCredential.getUserId());
+ return;
+ }
+
+ setStatus(AuthenticationStatus.FAILURE);
+ }
+
+ @Override
+ public User getUser()
+ {
+ return this.user;
+ }
+
+ void register(String userName, String password)
+ {
+ InMemoryUserStorage.setPassword(userName, password);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/TestInquiryStorage.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/TestInquiryStorage.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/TestInquiryStorage.java
new file mode 100644
index 0000000..6d2a56f
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authentication/TestInquiryStorage.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authentication;
+
+import org.apache.deltaspike.security.api.Identity;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@ApplicationScoped
+public class TestInquiryStorage implements InquiryStorage
+{
+ private Map<String, InquiryEntry> userInquiries = new ConcurrentHashMap<String, InquiryEntry>();
+
+ private Map<String, Inquiry> anonymInquiries = new ConcurrentHashMap<String, Inquiry>();
+
+ @Inject
+ private Identity identity;
+
+ public boolean addInquiry(Inquiry inquiry)
+ {
+ if(identity.isLoggedIn())
+ {
+ userInquiries.put(inquiry.getInquiryId(), new InquiryEntry(identity.getUser().getId(), inquiry));
+ }
+ else
+ {
+ this.anonymInquiries.put(inquiry.getInquiryId(), inquiry);
+ }
+ return true;
+ }
+
+ Collection<InquiryEntry> getUserInquiries()
+ {
+ return this.userInquiries.values();
+ }
+
+ Collection<Inquiry> getAnonymInquiries()
+ {
+ return this.anonymInquiries.values();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/secured/SecuredAnnotationTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/secured/SecuredAnnotationTest.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/secured/SecuredAnnotationTest.java
new file mode 100644
index 0000000..26ed4ee
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/secured/SecuredAnnotationTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authorization.secured;
+
+import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
+import org.apache.deltaspike.core.api.provider.BeanProvider;
+import org.apache.deltaspike.core.impl.exclude.ExcludeExtension;
+import org.apache.deltaspike.security.api.authorization.AccessDeniedException;
+import org.apache.deltaspike.test.util.ArchiveUtils;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.enterprise.inject.spi.Extension;
+
+
+/**
+ * Test for {@link org.apache.deltaspike.security.api.authorization.annotation.Secured}
+ */
+@RunWith(Arquillian.class)
+public class SecuredAnnotationTest
+{
+ @Deployment
+ public static WebArchive deploy()
+ {
+ new BeanManagerProvider() {
+ @Override
+ public void setTestMode()
+ {
+ super.setTestMode();
+ }
+ }.setTestMode();
+
+ JavaArchive testJar = ShrinkWrap.create(JavaArchive.class, "securedAnnotationTest.jar")
+ .addPackage("org.apache.deltaspike.test.security.impl.authorization.secured")
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+
+ return ShrinkWrap.create(WebArchive.class)
+ .addAsLibraries(ArchiveUtils.getDeltaSpikeCoreAndSecurityArchive())
+ .addAsLibraries(testJar)
+ .addAsServiceProvider(Extension.class, ExcludeExtension.class)
+ .addAsWebInfResource(ArchiveUtils.getBeansXml(), "beans.xml");
+ }
+
+ @Test
+ public void simpleInterceptorTest()
+ {
+ SecuredBean1 testBean = BeanProvider.getContextualReference(SecuredBean1.class, false);
+
+ Assert.assertEquals("result", testBean.getResult());
+
+ try
+ {
+ testBean.getBlockedResult();
+ Assert.fail();
+ }
+ catch (AccessDeniedException e)
+ {
+ //expected exception
+ }
+ }
+
+ @Test
+ public void interceptorTestWithStereotype()
+ {
+ SecuredBean2 testBean = BeanProvider.getContextualReference(SecuredBean2.class, false);
+
+ Assert.assertEquals("result", testBean.getResult());
+
+ try
+ {
+ testBean.getBlockedResult();
+ Assert.fail();
+ }
+ catch (AccessDeniedException e)
+ {
+ //expected exception
+ }
+ }
+
+ @Test
+ public void simpleInterceptorTestOnMethods()
+ {
+ SecuredBean3 testBean = BeanProvider.getContextualReference(SecuredBean3.class, false);
+
+ Assert.assertEquals("result", testBean.getResult());
+
+ try
+ {
+ testBean.getBlockedResult();
+ Assert.fail();
+ }
+ catch (AccessDeniedException e)
+ {
+ //expected exception
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1a2c7ffd/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/secured/SecuredBean1.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/secured/SecuredBean1.java b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/secured/SecuredBean1.java
new file mode 100644
index 0000000..41b21b1
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/secured/SecuredBean1.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.test.security.impl.authorization.secured;
+
+import org.apache.deltaspike.security.api.authorization.annotation.Secured;
+
+import javax.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+@Secured(TestAccessDecisionVoter.class)
+public class SecuredBean1
+{
+ public String getBlockedResult()
+ {
+ return "blocked result";
+ }
+
+ public String getResult()
+ {
+ return "result";
+ }
+}