/* * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.picketlink.authorization; import org.apache.deltaspike.security.api.authorization.Secures; import org.picketlink.Identity; import org.picketlink.authentication.levels.InsufficientSecurityLevelException; import org.picketlink.authentication.levels.Level; import org.picketlink.authorization.annotations.GroupsAllowed; import org.picketlink.authorization.annotations.LoggedIn; import org.picketlink.authorization.annotations.PartitionsAllowed; import org.picketlink.authorization.annotations.RequiresLevel; import org.picketlink.authorization.annotations.RequiresPermission; import org.picketlink.authorization.annotations.Restrict; import org.picketlink.authorization.annotations.RolesAllowed; import org.picketlink.authorization.util.AuthorizationUtil; import org.picketlink.idm.IdentityManager; import org.picketlink.idm.PartitionManager; import org.picketlink.idm.RelationshipManager; import org.picketlink.idm.model.Account; import org.picketlink.idm.model.Partition; import org.picketlink.internal.el.ELProcessor; import org.picketlink.producer.LevelFactoryResolver; import javax.enterprise.inject.Any; import javax.enterprise.inject.spi.BeanManager; import javax.inject.Inject; import javax.interceptor.InvocationContext; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import static org.apache.deltaspike.core.util.ProxyUtils.getUnproxiedClass; /** * <p>Default implementation of the authorization checks provided by the built-in security annotations provided by PicketLink.</p> * * @author Pedro Igor */ public class DefaultAuthorizationManager { @Inject private BeanManager beanManager; @Inject @Any private Identity identity; @Inject private ELProcessor elProcessor; @Inject private PartitionManager partitionManager; @Inject private IdentityManager identityManager; @Inject private RelationshipManager relationshipManager; @Inject private LevelFactoryResolver abstractFactory; @Secures @LoggedIn public boolean isLoggedIn(InvocationContext invocationContext) { LoggedIn loggedIn = getAnnotation(invocationContext, LoggedIn.class); Class<? extends Account> accountType = Account.class; if (loggedIn != null) { accountType = loggedIn.requiresAccount(); } Account account = getIdentity().getAccount(); return account != null && accountType.isInstance(account); } @Secures @Restrict public boolean checkExpression(InvocationContext invocationContext) { Restrict restrict = getAnnotation(invocationContext, Restrict.class); String expression = restrict.value(); Object result = this.elProcessor.eval(expression); if (Boolean.class.isInstance(result)) { return Boolean.valueOf(result.toString()); } return false; } @Secures @RequiresPermission public boolean hasPermission(InvocationContext invocationContext) { RequiresPermission requiresPermission = getAnnotation(invocationContext, RequiresPermission.class); String resource = requiresPermission.resource(); Class<?> resourceClass = requiresPermission.resourceClass(); String resourceIdentifier = requiresPermission.resourceIdentifier(); String operation = requiresPermission.operation(); return AuthorizationUtil.hasPermission(getIdentity(), resource, resourceClass, resourceIdentifier, operation); } @Secures @RolesAllowed public boolean hasRole(InvocationContext invocationContext) { RolesAllowed rolesAllowed = getAnnotation(invocationContext, RolesAllowed.class); for (String roleName : rolesAllowed.value()) { if (AuthorizationUtil.hasRole(getIdentity(), this.partitionManager, roleName)) { return true; } } return false; } @Secures @GroupsAllowed public boolean isMember(InvocationContext invocationContext) { GroupsAllowed groupsAllowed = getAnnotation(invocationContext, GroupsAllowed.class); String[] groupNames = groupsAllowed.value(); for (String groupName : groupNames) { if (AuthorizationUtil.isMember(getIdentity(), this.partitionManager, groupName)) { return true; } } return false; } @Secures @PartitionsAllowed public boolean hasPartition(InvocationContext invocationContext) { PartitionsAllowed partitionsAllowed = getAnnotation(invocationContext, PartitionsAllowed.class); String[] partitionNames = partitionsAllowed.name(); Class<? extends Partition> partitionType = partitionsAllowed.type(); return AuthorizationUtil.hasPartition(getIdentity(), partitionType, partitionNames); } @Secures @RequiresLevel public boolean hasLevel(InvocationContext invocationContext){ RequiresLevel requireslevel = getAnnotation(invocationContext,RequiresLevel.class); String level = requireslevel.value(); Level requiredLevel = abstractFactory.resolve().createLevel(level); if (!AuthorizationUtil.hasLevel(identity, requiredLevel)){ throw new InsufficientSecurityLevelException(requiredLevel, "Expected security level is: " + requiredLevel + " but the current level is: " +identity.getLevel()); } return true; } private <T extends Annotation> T getAnnotation(InvocationContext invocationContext, Class<T> annotationType) { Class unproxiedClass = getUnproxiedClass(invocationContext.getTarget().getClass()); T annotation = (T) unproxiedClass.getAnnotation(annotationType); Method invocationContextMethod = invocationContext.getMethod(); if (annotation == null) { annotation = invocationContextMethod.getAnnotation(annotationType); } if (annotation == null) { throw new IllegalArgumentException("No annotation [" + annotationType + "] found in type [" + unproxiedClass + "] or method [" + invocationContextMethod + "."); } return annotation; } private Identity getIdentity() { return this.identity; } }