Modify UserDetailsService of Pentaho - spring-security

I need receive two string parameters in loadUserByUsername method. I do not want to use spring security authentication, for this a have my own implementation that needs password too (It´s a integration system).
Is it possible create another method with the same name loadUserByUsername(String username, String password) in the same class, and call that method instead another one ?

I don't understand this requirement but UserDetailsService.loadUserByUsername(String) is just fine. At the time this method is invoked the user is already authenticated and hence the password is not needed anymore. So, if you need a password at that point there's a fair chance you're doing something wrong.
If you want to implement your own authentication mechanism based on username & password you need to provide your own AuthenticationProvider.
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="yourProvider" />
</security:authentication-manager>
<bean id="yourProvider" class="package.yourProviderClass">
<!-- I suppose you need this, too -->
<property name="userDetailsService" ref="yourUserDetailsService" />
</bean>
Have a look at the existing implementations and find the one that most closely offers what you need.

Related

spring security login with query string along with form login

We've an application which performs form login with spring security. But now we wanted to authenticate user from the query string as well. I tried with custom filter but it didn't solve the purpose. Can anyone please help me in solving the problem?
Authentication via GET is disabled in spring security for, well, security reasons. GET-requests (and their parameters) make their way into log files what is a very bad thing for login credentials. They can also be cached in upstream proxies where the logging is totally out of your control. You have been warned, but if you really want to:
You can enable auth via GET by setting a property on your loginFilter. Depending on your config style (xml or javaconfig) this will be:
<bean id="loginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"
p:postOnly="false" />
or
#Bean
public UsernamePasswordAuthenticationFilter getLoginFilter() {
UsernamePasswordAuthenticationFilter loginFilter = new UsernamePasswordAuthenticationFilter();
loginFilter.setPostOnly(false);
return loginFilter;
}

Two separate UserDetailsService Implementations

Is it possible to have to have UserDetailsService implementations in a single web application ?
To be more precise, my requirement is I have a Servlet which listens to http POST requests which needs to authenticated against a one type of user(lets say UserType 1), the Http POST request contains some fields that I could used to authentication user(user id, and some Hash String). Upon successful authentication user is again forwarded to another login page where again authentication happens this time user type is UserType 2.
Here,
The UserType 1 and UserType 2 have two separate principal and credentials.
I need to Http POST request parameters to flow to session of the UserType 2( I.e. session 2).
session 2 should survive till session 1 is destroyed.
I also guess I need to have two authentication entry points as well?
My gut feeling is that this is not possible(I wish I were wrong) !
Any clarifications or ideas regarding this?
I am not sure how nested authentication may be implemented with Spring Security. But you can have two separate UserDetailsService implementations. Consider case when you have two types of URLs /** and /admin/**, and they can be used by two separate groups of users. Starting from Spring Security 3.1 you can use multiple http tags (see corresponding documentation):
<http pattern="/admin/**" authentication-manager-ref="adminAuthenticationManager">
<intercept-url pattern="/**" access="ROLE_ADMIN" />
...
</http>
<authentication-manager id="adminAuthenticationManager" >
<authentication-provider user-service-ref="adminUserDetailsService"/>
</authentication-manager>
<bean id="adminUserDetailsService" class="com.mucompany.security.AdminUserDetailsService"/>
<!-- No pattern, so everything will be matched -->
<http authentication-manager-ref="adminAuthenticationManager">
<intercept-url pattern="/**" access="ROLE_USER" />
...
</http>
<authentication-manager id="userAuthenticationManager" >
<authentication-provider user-service-ref="publicUserDetailsService"/>
</authentication-manager>
<bean id="publicUserDetailsService" class="com.mucompany.security.PublicUserDetailsService"/>
You can even declare different entry points for each http tag using entry-point-ref attribute.

spring security intercept-url access

in our app, we have the following:
<intercept-url pattern="/app/**" access="ROLE_ADMIN,ROLE_USER,ROLE_CUST_ADMIN" />
but, in our app, we can create custom roles too, and, when a user of a custom role, for ex, ROLE_LIMITED_USER tries login, the access is denied.
how can I secure the app without listing the roles ? or how can I make it accept a pattern ROLE_* ?
I tried the following :
<intercept-url pattern="/app/**" access="IS_AUTHENTICATED_FULLY" />
but, this is causing the session time out and user is required to login. Before the change, the user login was remembered.
Appreciate any solution
thanks
A couple things:
The roles that you are requiring to access functionality in your app should not change - think of them more as "permissions" instead of "roles". (The Spring Security default here may be a misnomer.) Then you can map sets of permissions to roles (via your own code), allowing custom roles to be created as a different bag of permissions, but the actual permissions that you are coding/checking against are static - they don't change. When a user is authenticated, the set of GrantedAuthoritys you populate in the UserDetails should be a merged collection of permissions based on the user's assigned roles.
That said, I think you can still do what you want without changing the security model by using Expression-Based Access Control. Assuming you're using the security namespace (i.e. xmlns="http://www.springframework.org/schema/security"), then you need to set use-expressions="true" on the <http> element and change your access attribute values to SpEL expressions, such as:
<http use-expressions="true">
<intercept-url pattern="/app/**" access="hasAnyRole('ROLE_ADMIN','ROLE_USER','ROLE_CUST_ADMIN')" />
<intercept-url pattern="/other1/**" access="isAuthenticated()" />
<intercept-url pattern="/other2/**" access="authentication.authorities.?[authority.startsWith('ROLE_')].size() != 0" />
</http>
Note that this code snippet has not been tested, and I'm pretty sure the 3rd intercept-url example won't work as is but should be pretty close. (It's attempting to filter the Collection<GrantedAuthority> to authorities that start with ROLE_ and make sure the filtered list isn't empty.)
My guess is that it will be easier to use the 2nd intercept-url and do any further custom checking in code, where you can get access to the current SecurityContext / Authentication / principal via:
SecurityContextHolder.getContext()
Hope this helps.
Note similar question here as well:
Spring Security Authorize Access Role with a Wildcard
Use Spring's #PreAuthorize annotations in your classes, and reference a custom permission evaluator via SpEL. Don't worry about building an expression parser, as you can simply reference a boolean method from within the annotation:
#PreAuthorize("#myCustomClass.booleanMethod(param1, param2, #passedParam) and isAuthenticated()")
myMethod(passedParam) {
//do something
}
Then, in the custom class, define the boolean method, and it can handle your roles (permissions) however you like -- including accessing a database to discover your newly added roles.
You won't be able to add new roles to the XML configuration on the fly, so if your question pertains to new role creation (which seems to be the case), you'll need something like the above to make it happen. Using SpEL and a custom boolean method gives you access to a potentially limitless set of restrictions and requirements you can add to your application.

Most painless multi-tenancy implementation using ASP.NET, NHibernate / Fluent NHibernate

I'm trying to implement multi-tenancy in an ASP.NET MVC application I have, that uses NHibernate. Though I have control over the database for multi-tenancy. I'm trying to figure out the best way to filter our database queries using NHibernate.
I would like to know if there is a painless way where I can append a condition (something like WHERE InstanceID = 1) to every CRUD query to the DB using NHibernate.
I looked at global filters. But I wasn't sure if I'm using it the right way. I tried something like this.
NHibernateSession.GetDefaultSessionFactory().GetCurrentSession()
.EnableFilter("instance-filter").SetParameter("InstanceId", "2");
But it didn't seem to work. Any good example of NHibernate global filters / any good approach of filtering all DB queries with a condition would be highly appreciated.
I've been looking for the same thing for a small project of mine that's still in planning phase. The most complete implementation of using a single database that I came upon is written by Michael Valenty in his blog post: Bolt-on Multi-Tenancy in ASP.NET MVC with Unity and NHibernate: Part II – Commingled Data. He's also using global filters.
Just for the sake of completeness, here are the mappings he used:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<filter-def name="tenant">
<filter-param name="id" type="System.Int32" />
</filter-def>
</hibernate-mapping>
And for each entity:
<class name="User" table="[user]">
<id name="Id" column="user_id">
<generator class="identity" />
</id>
<property name="Username" />
<property name="Email" />
<filter name="tenant" condition="tenant_id = :id" />
</class>
After that, he uses his IoC container of choice to inject the parameter value to instance of ISession.
session.EnableFilter("tenant").SetParameter("id", c.Resolve<Tenant>().Id);
There's also an interceptor to implement - to write the value of current tenant id when saving the entity (OnSave method), and also to check whether the given entity belongs to current tenant when loading the entity by id (OnLoad method). OnLoad override is necessary because tenant filter won't be applied when loading entity by id.

Spring Security being called from different sources

I want to run authentication/authorization only for the calls that come from HTTP requests.
The method on the controller I want to have authentication/authorization enabled is called from more than one source. In this case, it can be either called by another controller or by a direct HTTP request.
Can I turn off authentication/authorization for the calls that come from other Controllers?
Just read further if you haven't got this clear enough yet.
Let's say I have a method doIt() on a Controller A. I also have a Controller B, in which I inject controller A. At some point on Controller B, I call 'a.doIt()', but I can also call doIt() from an HTTP call to doIt.do.
I want to test the call for authentication/authorization if the call comes from an HTTP call, but not if it comes from Controller B.
You are injecting in B the security proxied bean of A. Can't you inject A without the proxy?. Bean A proxied:
<bean id="beanASecured" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetName" value="beanA"/>
<property name="interceptorNames">
<value>securityInterceptor</value>
</property>
</bean>
The secutiryInterceptor:
<bean id="securityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
...
</bean>
Bean A not proxied:
<bean id="beanA" class="com.A"/>
Bean B injected with bean 'A not proxied':
<bean id="beanB" class="com.B">
<constructor-arg ref="beanA"/>
</bean>
You need to only configure the spring authentication on URL and not on the method invocation. This will work for you.
I don't see any way to do this, my guess is you'll just have to have a second method like doitDirectCall(..) that the actual other controller calls and doit(..) that get's called on an HTTP request.

Resources