Adding new Spring Social connections to the same user - java

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.

Related

Spring security - securing some rest endpoints with OKTA and others with Active Directory in the same API

I have rest API where I need to secure some (UI facing) endpoints with OKTA authentication, and others (backend-facing) with Azure Active Directory. I managed to do it separately (either I can secure the endpoints with OKTA or AAD), but they don't want to work together. As soon as I add okta-spring-boot-starter to POM (or okta-spring-security-oauth2) - AAD security stops working and endpoints are either open or secured with OKTA only. I am trying to do it using WebSecurityConfigurerAdapter implementations for okta and aad:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Configuration
#Order(1)
public static class OktaAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/v1/endpoint1").authenticated()
.antMatchers("/v1/endpoint2/**").authenticated();
}
}
#Configuration
#Order(2)
public static class ActiveDirectoryAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private AADAppRoleStatelessAuthenticationFilter filter;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/v1/endpoint3/**").authenticated()
.antMatchers("/v1/endpoint4/**").authenticated()
.and()
.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
}
}
}
This configuration however works only for endpoint1 and endpoint2 (secured with okta), other rest points are open (as if 2nd implementation of WebSecurityConfigurerAdapter was ignored). If I remove okta package from pom, AAD configuration starts working. If I switch orders of above configurations then nothing is secured. I suspect okta package does some autoconfiguration, but can't find any information about it. What am I missing?
The Okta Spring Boot Starter is mostly just a light wrapper to help configure the existing Spring Security OAuth autoconfig with a few Okta specific bits.
My first suggestion (if possible) is to try to use Spring Security OAuth for both IdPs, as it doesn't look like the AAD starter works Spring Security's built-in OAuth support (I could be wrong, I only took a quick look). Assuming AAD is just OAuth/OIDC it will just work with a little bit of configuration.
You will still need a solution to protect your given routes 1 & 2 -> Okta 3 & 4 AAD. There are a few ways to do this. You could use scopes (assuming they are different) or some other type of "authority":
http.authorizeRequests()
.antMatchers("/your/route").hasAuthority("SCOPE_custom");
The Okta Spring Boot Starter should work with other IdPs configured with Spring Security OAuth properties: https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login-boot-property-mappings
I cannot speak 100% to what the ADD starter adds, but I'm guessing it's similar to Okta. Which is:
A common set of properties (inline with other vendor offerings)
Vendor-specific JWT validation (Spring Security only does basic JWT validation, and each vendor has its own recommendations, assuming you are using JWT access tokens)
A little sugar (for example the Okta starter adds a mapping of Okta groups to Spring Authorities)
As far as JWT validation goes Okta recommends validating JWTs like this:
https://scotch.io/tutorials/jwt-vs-opaque-access-tokens-use-both-with-spring-boot#toc-better-jwt-validation
A similar technique could be used (if needed).
Keep us posted!

Is it possible to use Spring Security 4 remember-me alongside a custom AuthenticatonProvider?

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.

Checking whether a user is logged in using stormpath and spring-boot

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.

Custom JDBC Authorisation using Spring Security 4

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

Spring 4 - Authentication with preAuthorize & PostAuthorize

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.

Categories

Resources