SSO/Oauth login on same application, Login based on UrL - spring-boot

I have spring MVC application and I am trying to register different SSO login on same application. For example if url is (admin.abc.com), It should login from microsoft SSO and if the url is abc.com it should redirect to google login.
Here is my code but when I run the code both sso open with giving me the option to choose.
Is there any way I can set sso login based on domain instead of select option.
#Autowired
ClientRegistrationRepository regRepository;
#Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(Arrays.asList(msClientRegistration(), googleSSOClientRegistration()));
}
and the configuration for antmatcher is like this
#Override
protected void configure(final HttpSecurity http)
throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.antMatchers("/login.htm").authenticated()
.antMatchers("/**")
.permitAll().anyRequest()
.authenticated().and().logout()
.logoutSuccessHandler(oauthLogoutSuccessHandler())
.invalidateHttpSession(true)
.logoutUrl("/logout")
.and().oauth2Login()
.failureHandler(new CustomAuthenticationFailureHandler())
.authorizationEndpoint()
.authorizationRequestResolver(
new CustomAuthorizationRequestResolver(regRepository, "/oauth2/authorization"))
.and().tokenEndpoint()
.accessTokenResponseClient(authorizationCodeTokenResponseClient())
.and().and().headers()
.frameOptions()
.sameOrigin().and().csrf()
.disable();
}
How to add antMatcher configuration based on domain url? google sso for abc.com and admin.abc.com for microsoft login with OAuth2.
Instead of having this I want to redirect base on url's.. either Google login or Microsoft.

Related

SecurityContextHolder.getContext().getAuthentication() returns null

I'm developing Spring boot and security web application with authorization and resource servers enabled. I have defined a set of users with roles assigned to them and have implemented roles based access to rest endpoints. Besides that my application has straightforward UI with web pages. Those pages display the same data that is on rest. I'm trying to implement the same roles based access to pages with ResourceServerConfig#configure and my current code:
public void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/rest/products/add").hasAnyRole("ADMIN")
.anyRequest().authenticated()
.and().formLogin()
.loginPage("/login.jsf").permitAll()
.loginProcessingUrl("/login")
.defaultSuccessUrl("/login-successful", true)
.and().logout().permitAll();
}
This configuration works perfectly for REST controllers access with bearer token, but authorization with the login form leads to the redirect to the /login-successful and the message
Full authentication is required to access this resourceunauthorized is displayed.
The reason is that SecurityContextHolder.getContext().getAuthentication() for /login-successful request in spite it was correctly initialized in AbstractAuthenticationProcessingFilter#successfulAuthentication at the point of login form post. The same issue with other web pages in my app as well.
What should be added to the above configuration so that make it work for the REST and form login bought ?
Here is indicted that HttpSecurity configuration provided above is enough for authorization with form login to work correctly as far as .anyRequest().authenticated() should pass security context for all the resources in the application.
A similar case is described here but the reason over there is that an url was explicitly ignored in WebSecurity configurer.
The problem was in the fact that I was using deprecated #EnableResourceServer annotation that adds OAuth2AuthenticationProcessingFilter. For the form login authorization flow this is incorrect and that filter was removing authentication object from the SecurityContext. Here is indicated that OAuth2AuthenticationProcessingFilter shouldn't present in the filter chain for the form login authorization flow.
The reason why I was needed #EnableResourceServer annotation is that there are there is the bearer authentication flow in my application alongside with form login.
I replaced #EnableResourceServer annotation and ResourceServerConfigurerAdapter for the bearer authentication flow with Spring Security 5 resource server as http.oauth2ResourceServer() that is in WebSecurityConfigurerAdapter ( see here ). Finally the solution is with the following two WebSecurityConfigurerAdapter-s:
For bearer authorization flow:
#Configuration
#Order(2)
public class SecurityConfigRest extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
NimbusJwtDecoder jwtDecoder = Build custom JWT decoder;
http.csrf().disable()
.requestMatcher(new AntPathRequestMatcher("/rest/**"))
.authorizeRequests()
.mvcMatchers("/products/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.oauth2ResourceServer().jwt().decoder(jwtDecoder);
}`
and for the form login authorization flow:
#Configuration
#Order(1)
#EnableWebSecurity
public class SecurityConfigFormLogin extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http .requestMatcher(new AntPathRequestMatcher("/view/**"))
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/view/login").permitAll()
.defaultSuccessUrl("/view/login-successful", true)
.and().logout()
.logoutUrl("/view/perform_logout")
.logoutSuccessUrl("/view/login");
}
These two WebSecurityConfigurerAdapter-s make it possible to separate those two authorization flows.
As far as Spring Security 5 resource server supports only JWT or Opaque tokens ( see here ) it requires additional configuration. Here is a detailed description of such a configuration for Spring Security 5 resource server.

Spring security : configure JWT with formLogin

I am trying to configure JWT filter with formLogin authentication .
(My server serve UI clients (thats why i need formLogin ) and i am exposing also Rest End Point (to be authenticated by JWT ) .
currently my JWT is working , but it seems that my Roles (anyRole) -- isnt working .
here is my configure method :
post login -> if I am trying to reach /kuku path - I get 302 and login page again .
if i am removing the addFilterBefore -> my roles is working fine .
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/").hasRole("ADMIN")
.antMatchers("/kuku/**").hasRole("ADMIN")
.anyRequest()
.authenticated()
.and()
.formLogin().defaultSuccessUrl("/inital.html", true)
;
http.addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class);
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
String userName = "Admin"; // currently due to Vault IMPL - this input is hardcoded .
String password ="Admin"
auth.inMemoryAuthentication()
.withUser(userName).password(passwordEncoder().encode(password))
.roles("ADMIN");
}
Try adding csrf().disable() to your configure(http) method. This worked in my case where I have similar configuration as yours. Although, I suggest searching for whether or not this is secure, because this disables built-in csrf protection.

How Can I Customize Login Page for Oauth2 in Spring Webflux?

I just want to override default oauth2 login url (/login). How can I do that? The config I have tried without success:
#Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange().pathMatchers(permittedUrls).permitAll()
.anyExchange().authenticated()
.and()
.oauth2Login(Customizer.withDefaults()).formLogin().loginPage("/oauth2_login")
.authenticationSuccessHandler(this::onAuthenticationSuccess)
.and()
.csrf().disable();
return http.build();
I was hoping it will redirect to /oauth2_login url but it didn't work. It still redirect to /login. But this time it returns 404 instead of showing default login page.
The code above is customizing the login page for formLogin which is typically username/password based log in from a form. It's much easier to see what configuration you are impacting using the new lambda style approach, so I have updated the entire configuration to use it. If you want to customize the login page for oauth2Login, then you should change the login page on it. For example:
#Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange(exchanges -> exchanges
.pathMatchers(permittedUrls).permitAll()
.anyExchange().authenticated()
)
.oauth2Login(oauth2 -> oauth2
// you now must render a log in page for the URL /login
.loginPage("/login")
);
// remove formLogin that was for a username/password based log in
// if you are doing oauth2 login I'm guessing you allow users to work within a browser, so you should not disable csrf
return http.build();
}

Spring security antMatcher not working as expected

I have my custom controller "/my-endpoint" and spring app with the following configuration:
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/my-endpoint", "/health")
.permitAll()
.antMatchers(DENY_RESOURCE_PATTERNS)
.denyAll()
.anyRequest()
.authenticated()
}
It seems that for a unanimous user it working fine. But if I already authorized (using oauth2) and my session(or token) is expired -> spring trying to redirect me to the login page.
I don't want this, I want to allow any user to connect to "/my-endpoint" endpoint.
What I forgot to configure?
The interesting thing, that built-in endpoint "/health" working as expected, even if session is expired.
you can use configure(WebSecurity web). It will bypass the Spring Security Filters and will allow any user to access the endpoint. see HttpSecurity vs WebSecurity
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(HttpMethod.yourMethod, "/health")
.antMatchers(HttpMethod.yourMethod, "/my-endpoint");
}

How can I get roles or groups from Azure SAML 2.0 Application in Spring Boot

I have a spring boot application where I need to limit access for specific endpoints. So far I can authenticate against Azure using SAML 2.0.
This is the main configuration of the authentication in Spring
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(samlEntryPoint());
http
.csrf()
.disable();
http
.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class)
.addFilterAfter(samlFilter(), BasicAuthenticationFilter.class);
http
.authorizeRequests()
.antMatchers("/error").permitAll()
.antMatchers("/saml/**").permitAll()
.anyRequest().authenticated();
http
.logout()
.logoutSuccessUrl("/");
}
in Azure I have added the roles to the claim values as shown in the image below
Azure Claims
My target is to be able evantaully to do something like the following:
#GetMapping("/")
#PreAuthorize("hasRole('User')")
public String getSample(Principal principal) {
log.info("Get Request");
return "Hello";
}
Next step would be to implement your own SAMLUserDetailsService that would return the corresponding UserDetail instance with the rights Authorities granted to the user.
You would have to retrieve the list of Azure role from the SAMLCredential (something like credential.getAtttributeAsString(<your_attribute_name>) then you would have to map theses values with the list of authorities defined in your application.

Resources