This is continuing after this question: Custom LDAP authentication using Spring Security 4. After the user has been authenticated, I need to authorize it. My roles has and the user mapping is stored in a database. I need to fetch the roles and save them in the GrantedAuthority object. How do I do this using Spring Security 4? I am using Java based config.
You need to implement your own AuthenticationProvider (i.e. a class implementing org.springframework.security.authentication.AuthenticationProvider) and configure Spring Security to use it. Give a look to this: Implement custom AuthenticationProvider in Spring Security 2.06
Related
I am using Spring Social along with Spring Boot and Spring Security. I use Spring Social to provide authentication into our web service. This is done using the SocialAuthenticationFilter approach.
I am trying to support the ability to have a single user (ie. org.springframework.security.core.userdetails.UserDetails) have multiple Spring Social connections. This way a user could sign in with either his Google credentials or Facebook credentials.
If I go directly into my database I can make this configuration. Then I can sign into the same Spring Security account for different Spring Social connections. The problem is the point at which a user adds the new connection. I'll give a sample of what I'm doing with the assumption that I'm signed in via a Google account and want to add Facebook.
I log in via Google. Then if I load either my Spring Security formLogin().loginPage() or go straight to auth/facebook (the standard Spring Social Facebook login URL), I can perform Facebook authentication. But, the result is that my current Authentication object (from SecurityContextHolder.getContext().getAuthentication()) is an anonymous authentication user. This does make sense because I just logged in using Facebook. But at the same time I'd like to know that I'm logged in so that I could ask the user about connecting the accounts and setup the database.
How can I provide the ability to let an authenticated user add a new social account to his user account? Also, I'm not tied to a particular workflow for adding new connections; the above was just my first set of experiments.
Spring Social 1.1.4
Spring Boot 1.3.8
Spring Security & MVC - as
specified by Spring Boot 1.3.8
Update
From Jerome's suggestion I extracted the security filter chain from Spring Security debugging:
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
SocialAuthenticationFilter
UsernamePasswordAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
This is probably not an issue with Spring Social, but rather with Spring Security. If you get an anonymous user logged in, then it means that AnonymousAuthenticationFilter is kicking in before yours, or SocialAuthenticationFilter.
Switch spring security to debug:
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.debug(true);
}
}
And check which filters are involved. I'm pretty sure you have the anonymous filter which kicks in for undesired paths.
I'm using spring 4 with annotation based configuration and I'm trying to get the spring security 4 remember-me (PersistentTokenRepository) feature working alongside my custom AuthenticationProvider.
At the official spring security documentation (http://docs.spring.io/spring-security/site/docs/current/reference/html/remember-me.html) there is a hint that you must have a UserDetailsService.
Is there a way to bypass this restriction? Because I need this custom AuthenticationProvider to check an authentication chain (LDAP, Database(s) etc) for different conditions until a user is allowed to log in. I don't think I can mimic this behaviour with a UserDetailsService. Or am I wrong? Any ideas are appreciated.
I have a simple web application which I am writing using spring-boot and storm path for user authentication. (I'm actually using spring-boot-starter-stormpath-thymeleaf)
I have a have the following request mapping in my controller
#RequestMapping(value = "/secure", method = RequestMethod.GET)
public String secure(Model mode, HttpServletRequest request) {
Account account = AccountResolver.INSTANCE.getAccount(request);
if (account != null)
return "secure";
else
return "redirect:/login?next=secure";
}
which forces a user to login to view the secure page. It works, but it doesn't feel like it is the most elegant of solutions. Is there a better way? I think a solution with filters should be possible but I cannot figure it out.
The current Stormpath Spring Boot starter does not (yet) have an authentication filter, but it will on future releases for those that want an out-of-the-box experience without having to use Spring Security or Apache Shiro.
That said, we're currently working on natively supporting Spring Security and Apache Shiro as Spring Boot starters that 'just work' with the Stormpath Spring Boot starter. Until we can release those, creating a custom servlet filter as you indicate is the best approach.
Are you also using the Stormpath Servlet as well?
If so, you could do what you need following this piece of documentation. This way you will only need to declare which are the resources of your application that you want to secure and Stormpath's authc filter will prompt for authentication when required.
If you're using Spring MVC, you should use Spring Security and have Stormpath acting as an authentication provider. Then use the standard Spring Security tools to declare access rules and inject the current user where needed.
I have a scenario where I have roles and permissions in a different system (where i need to make a REST call) and that system will specify whether I can access a particular resource or not.
I need to intercept my controller methods and that Interceptor should talk to external service and figure out the authorization. I am using just spring boot (no spring security).
It should be similar to this with JAX-RS but I'm looking in spring context. Can I achieve this using #RolesAllowed?
I would recommend using an interceptor:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-handlermapping
You need to have a configuration that you will annotate with (check spring documentation)
#EnableGlobalMethodSecurity(jsr250Enabled = true)
Then you will have to create your own access decision manager and register your own roles. With this you should be able to annotate your controllers to a specific user like #RolesAllowed("admin")
NOTE: My application uses the latest version of the Spring framework, 4.0.6, 3.2.4 for security, and, it uses no xml but only Java-Config to configure the application.
I have a set of services which I would like to secure with roles and other business specific authorization conditions. This services are grouped into a module (a jar) which is used by a REST application and a web application. I already have an AuthenticationProvider in the web application (REST application is in initial phase). I use #EnableGlobalMethodSecurityin the web application. Having said that, I now need to secure the methods in the services too. In that case, do I need to provide another authentication provider? Or, is right to move the authentication provider to the services module so that the web/rest apps uses the authentication provider in the services jar? If I configure #EnableGlobalMethodSecurity in the ApplicationServiceConfig.java of the services module, I get the blow exception.
com.name.mvoice.project.service.ApplicationServiceConfig: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: An AuthenticationManager is required
How do I configure the security if the application requires double authentication, one from the RDBMS and the other from the LDAP. The condition should be that the user information should be present and be enabled in both the systems. Do I need to write this in the existing authentication manager itself or shall I provide separate auth provider for the LDAP? If so how?
WebSecurityConfig.java
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
AuthenticationProvider dbAuthenticationProvider = new DatabaseAuthenticationProvider();
auth.authenticationProvider(dbAuthenticationProvider );
// is it right to do like this
AuthenticationProvider ldapAuthenticationProvider = new LDAPAuthenticationProvider();
auth.authenticationProvider(ldapAuthenticationProvider );
}
Though, I seeAuthenticationManagerBuilder.authenticationProvider adds the supplied authenticationprovider to a list!
No, this won't give you the desired result. The default Spring Security implementation uses only one AuthenticationProvider at a time. Your second call to auth.authenticationProvider() would force Spring Security to use just the LDAP provider.
To achieve what you want
Step 1: Create a class of your own, say
public class CompositeAuthenticationProvider implements AuthenticationProvider {}
Step 2: Then, inject the Database and LDAP providers into it.
Step 3: In the authenticate method of the class CompositeAuthenticationProvider, orchestrate the request between the Database and LDAP providers as you see fit. Return a response based on the results you obtain from both the providers.