We are implementing a custom authentication component for JasperReports Server 5.1. We are relying on an external source to provide the username, tenant, roles and profile attributes of a user directed to JasperReports Server from another internal site.
All is going well with the exception of creating the profile attributes. We receive a security related error when calling the putProfileAttribute() method. We can retrieve and even delete existing ProfileAttributes fine. Creating new ones is the only issue.
public class TestExternalUserSetupProcessor extends AbstractExternalUserProcessor { @Override public void afterPropertiesSet() throws Exception { getProfileAttributeService().setUserAuthorityService(getUserAuthorityService()); super.afterPropertiesSet(); } public void process() { ........ ((ExternalUserService)getUserAuthorityService()).makeUserLoggedIn(user); ProfileAttribute attribute = getProfileAttributeService().newProfileAttribute(new ExecutionContextImpl()); attribute.setAttrName("TestName"); attribute.setAttrValue("TestAttrVal"); attribute.setPrincipal(user); logger.info("Trying to set attribute"); getProfileAttributeService().putProfileAttribute(new ExecutionContextImpl(), attribute); // Error, never hit this logger.info("Tried to set attribute"); } }
What do we have wrong or need to do otherwise?
org.springframework.security.AccessDeniedException: Access is denied
at org.springframework.security.vote.AffirmativeBased.decide(AffirmativeBased.java:68)
at org.springframework.security.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:265)
at org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:63)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy32.putProfileAttribute(Unknown Source)
at com.apption.jasper.server.security.TestExternalUserSetupProcessor.process(TestExternalUserSetupProcessor.java:124)
at com.jaspersoft.jasperserver.api.security.externalAuth.ExternalDataSynchronizerImpl.synchronize(ExternalDataSynchronizerImpl.java:78)
2 Answers:
The solution which worked for us to add ROLE_USER to the following bean def in the application-context.xml file:
<bean id="profileAttributeServiceMethodSecurityInterceptor" class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor">
....
<property name="objectDefinitionSource">
<value>com.jaspersoft.jasperserver.api.metadata.user.service.ProfileAttributeService.putProfileAttribute=ROLE_ADMINISTRATOR,ROLE_SUPERUSER,ROLE_USER</value>
</property>
As well we MAY have been required to mark the user logged in as well.
// Mark user logged in
((ExternalUserService)getUserAuthorityService()).makeUserLoggedIn(user);
I have extactly the same problem on JasperReports Server 5.5; and followed with sucess the indicated procedures to allow it.
In order to not mess up with Jasper configurations i have overrided property value on referenced beans adding configuration to a custom configuration file named "applicationContext-security-custom.xml"
- Option 1
For Community Edition
Add ROLE_ADMINISTRATOR for property "defaultInternalRoles" on bean "userAuthorityService"
<bean class="com.jaspersoft.jasperserver.api.common.util.spring.GenericBeanUpdater"> <property name="definition"> <bean class="com.jaspersoft.jasperserver.api.common.util.spring.GenericBeanUpdaterDefinition"> <property name="order" value="10"/> <property name="beanName" value="userAuthorityService"/> <property name="propertyName" value="defaultInternalRoles"/> <property name="operation" value="set"/> </bean> </property> <property name="value"> <list> <value>ROLE_USER</value> <value>ROLE_ADMINISTRATOR</value> <list> </property> <property name="valueType" value="stringList"/> </bean>
On Pro Edition
Add ROLE_ADMINISTRATOR for property "defaultInternalRoles" on bean "mtUserAuthorityServiceTarget"
<bean class="com.jaspersoft.jasperserver.api.common.util.spring.GenericBeanUpdater"> <property name="definition"> <bean class="com.jaspersoft.jasperserver.api.common.util.spring.GenericBeanUpdaterDefinition"> <property name="order" value="10"/> <property name="beanName" value="mtUserAuthorityServiceTarget"/> <property name="propertyName" value="defaultInternalRoles"/> <property name="operation" value="set"/> </bean> </property> <property name="value"> <list> <value>ROLE_USER</value> <value>ROLE_ADMINISTRATOR</value> <list> </property> <property name="valueType" value="stringList"/> </bean>
- Option 2
Adding ROLE_USER on bean "profileAttributeServiceMethodSecurityInterceptor" for property "objectDefinitionSource". Or derefining
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd"> <!-- allow creating new profile attributes from users --> <bean class="com.jaspersoft.jasperserver.api.common.util.spring.GenericBeanUpdater"> <property name="definition"> <bean class="com.jaspersoft.jasperserver.api.common.util.spring.GenericBeanUpdaterDefinition"> <property name="order" value="10"/> <property name="beanName" value="profileAttributeServiceMethodSecurityInterceptor"/> <property name="propertyName" value="objectDefinitionSource"/> <property name="operation" value="set"/> </bean> </property> <property name="value" value="com.jaspersoft.jasperserver.api.metadata.user.service.ProfileAttributeService.putProfileAttribute=ROLE_ADMINISTRATOR,ROLE_SUPERUSER,ROLE_USER"/> <property name="valueType" value="string"/> </bean> </beans>
regards,
--
Bruno Antunes
Ah, I got it working when I put the ROLE_ADMINISTRATOR as a default internal role by now, so I was googling about for method security config.
Thanks a bunch!