The actual Spring Security configuration is like this:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/uri1/**").hasAuthority(Permission.AUTHORITY1.toString())
.antMatchers("/uri2/**").hasAuthority(Permission.AUTHORITY2.toString())
.anyRequest().hasAuthority(Permission.AUTHORITY3.toString())
.and().httpBasic()
.realmName("App").and().csrf().disable();
http.authorizeRequests();
http.headers().frameOptions().sameOrigin().cacheControl().disable();
}
@Bean
public Filter shallowEtagHeaderFilter() {
return new ShallowEtagHeaderFilter();
}
}
And the web MVC configuration is like this:
@Configuration
public class DefaultView extends WebMvcConfigurerAdapter{
@Override
public void addViewControllers( ViewControllerRegistry registry ) {
registry.addViewController( "/" ).setViewName( "forward:myPage.html" );
registry.setOrder( Ordered.HIGHEST_PRECEDENCE);
super.addViewControllers( registry );
}
}
I have to replace the httpBasic authentification done in Spring Security by an authentification using onelogin (so with SAML if I understood what I found on the Internet).
By doing research, I found that a possibility was to use Shibboleth on the Apache server and an other was to use a plugin in Spring Security to manage SAML.
For the first solution (shibboleth), the aim is to manage onelogin authentification directly on Apache server (if not connected, the user is redirected on onelogin authentification page, if connected, the ressource is accessible) and to have needed informations returned in SAML response (like username and other need data) in the header of the request (to be abble to have them in Spring app).
With this solution, is it possible to keep httpBasic authentification in Spring security and to have "Basic XXXX" in the header of each request set by Shibboleth? Or, have I to remove the httpBasic authentification from Spring Security?
For the second solution (plugin to manage SAML in Spring Security), is it the same result as the first solution and how it must be implemented?
Thank you in advance for your reply.
2
Answers
This is the entire solution I used to connect to my application using Onelogin, shibboleth (Apache) and Spring Security. I used http but you have to adapt if you want to use https.
Onelogin
Configure a "SAML Test Connector (SP Shibboleth)" with the following configuration:
An parameter "username" has been added and a value is defined for this parameter for each user.
Apache and shibboleth
See: https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPJavaInstall
I installed shibboleth.
I activated AJP (module mod_proxy_ajp). It is recommended to use AJP instead of HTTP request headers.
I updated my apache conf file:
In shibboleth2.xml:
In attribute-map.xml:
Spring-boot
Tomcat configuration to add an AJP connector (attributes loaded from yml with a "server" property):
Spring security configuration (the shibboleth filter can be activated through yml with a "shibboleth-filter" property defined in an "authentication" property):
ShibbolethFilterRegistrar:
ShibbolethAuthFilter:
ShibbolethAuthenticationManager:
ShibbolethAuthToken implements Principal.
Thank you for your help.
welcome to stackoverflow.
If I understood correctly, you are already using spring security. This means your application is already using spring security populated context for authentication and authorization in your controller/service layers. If you use said approach, where apache is populating the authenticate user information in headers, than this is NOT going to populate the spring security context all by itself UNLESS you add a preAuthFilter in your chain to extract this information and populate your spring context appropriately.
If you are able to do it then what I said above would be a bit relaxed. Having said that, to best of my knowledge, there is no option where you can deduce a Basic authentication header using shibboleth apache module. In addition, I’ll also advice to be careful with this approach since, with this approach, you’ll still have to authenticate the user in your app with a dummy password (since you are NOT going to get user’s correct password via SAML in this header) and this opens up your application for security exploits. I’ll strongly advise against this approach. Shibboleth already has some Spoof Checking covered in their documentation.
[EDIT]
Based on the additional information, following is what you can do to achieve all handling by apache and still use spring security effectively
First provide implementation of PreAuthenticatedAuthenticationToken in your application, you can use AbstractPreAuthenticatedProcessingFilter for this purpose. A skeleton for the implementation is provided below, this is excerpt from one of my past work and very much stripped down keeping only the essential elements which are relevant for your scenario. Also take a close look at AuthenticationManager and Authentication docs and make sure you fully understand what to use and for what purpose. Please read javadocs for all these 4 classes carefully to understand the contract as it can be confusing to get it right in spring security otherwise. I have added necessary details as TODO and comments in skeleton blow that you’ll have to fill in yourself in your implementation.
Register this as servlet filter in your app using following registrar
Followed by this, change your WebSecurityConfig to following
Hope these pointers helps you to integrate external auth successfully.
IMHO, following is still valid – as much as I have understood your scenario, if I had to do it, I’ll personally prefer to use spring security inbuilt SAML auth for this purpose since that provides very smooth integration with spring security in every possible context within the framework. In addition, it also simplifies my deployment scenario where I’ll also have to take care of provisioning apache which’ll typically fall under additional workload for DevOps team. For simplicity and scalability, spring security inbuilt SAML SSO support would be my first choice unless there’s a constraint which is forcing me to do otherwise (which I am not able to see in current discussion context based on the explanation provided). There are ample tutorials and examples available on net to get it done. I know this is not what you asked for but I thought to share with you what I have done myself in past for similar SSO solutions in spring distributed apps and learning that I had. Hope it helps!!