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.
Related
In a Spring Secuity / Boot application I have multiple #Configuration annotated Configurations that extend WebSecurityConfigurerAdapter.
In one of these specific configurations, I want to protect a specific URL with basic auth. I do that by overriding configure(final HttpSecurity) and using antMatcher("myURL") onto the HttpSecurity object, followed by the usual authorization-chain and httpBasic().
But configuring basic auth in spring also requires your configuration to override configure(final AuthenticationManagerBuilder auth), where you configure an authentication-mechanism, as I understand. In my case, that is a simple inMemoryAuthentication(), with user and password of my choice.
Now, I know that some of the other configurations in the project configure the rest of the urls with a way more complex authentication-mechanism, which implement's SSO. I am not entirely sure if my configuration, which messes with the AuthenticationManagerBuilder, interferes with these other mechanisms in any way?
My expectation is that, because in configure(final HttpSecurity) I use antMatcher("myURL"), this configuration will create a SecurityFilterChain that has my specific inMemoryAuthentication() logic (somewhere deep in a spring filter that handles basic auth) and that this chain will only be used for the requests matching "myURL" pattern. I expect other filters-chains that are created by other other existing configurations and their more complex authentication mechanisms to be unaffected by my new configuration. My new inMemoryAuthentication should never play a role there. Is that correct?
I have created an oauth module for my project.
It has the mechanism for authorization server, spring security and the resource server.
I need some of the end-points to be accessible only on authorization, so I configured the security in the resource-server:
#Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new OrRequestMatcher(new AntPathRequestMatcher("/secured/**")))
.authorizeRequests().anyRequest().authenticated();
}
So far access-token/refresh-token calls are working fine.
Now, I want to create a separate module for all the webservices API - where I would put all the controllers and the logic for processing the requests.
Is it advisable to do it in a different module than oauth?
If yes, how can I secure the calls and verify the tokens? How can I use the resource server in another module.
If the oauth module is where your spring boot app is you could add #ComponentScan("webservices API") to let it know where your api controllers are. Take a look at this question which may have your answer:
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 am building a web application using an AngularJS front-end and a Spring Boot REST back-end (they are running on separate servers i.e. port 3000 and port 8443). The back-end is supposed to connect to multiple external services (with separate authentications) and provide endpoints for the front-end to use.
For security, I decided to use Apache Shiro. For simplicity, I will pretend there are just 2 external services (ES1 and ES2).
I have created 2 x AuthorizingRealm which connect to the respective external services and attempt authentication using the provided tokens.
In the doGetAuthenticationInfo method, if the login is successful, I return a SimpleAuthenticationInfo with the principal, credentials and the name of the realm.
In the doGetAuthorizationInfo method, I check the realm name of the principal and, if it checks out, I return a SimpleAuthorizationInfo with the role "USER" and a permission (e.g. ES1_permitted).
I also extended the UsernamePasswordToken class for each realm to separate usage even more (through the supports method).
In a configuration class, I create a bean for a DefaultWebSecurityManager that uses my two realms and a bean for the Shiro filter.
I added 4 filters:
anon AnonymousFilter
perm PermissionsAuthorizationFilter
es1 ES1Filter
es2 ES2Filter
My filter chain looks something like:
/api/es1/login -> anon
/api/es1/** -> es1, perms[ES1_permitted]
/api/es2/login -> anon
/api/es2/** -> es2, perms[ES2_permitted]
/** -> anon
Somehow, when I served front-end and back-end from the same server (no CORS), it seemed to work. However, now that CORS is an issue, I can't seem to get this to work as expected.
Is there a simpler way to achieve this complete separation of authentication/authorization? I am willing to switch to Spring Security if it can be done there as well.
PS: I am using the Java API, not configuration files (spring xml or shiro.ini).
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")