how to share User Principal/ securityContext on Public pages with permitAll() in spring security OAuth2 - spring

We have developed a SSO application in spring boot using OAuth [LDAP/ Social Login]. Application has some public pages and some protected pages. The requirement is we want some contents on public pages based on authenticated users. The issue is once we login in one application and visit the public page of other application, the user principal is not available on public pages, unless we visit one of the protected pages of same application. Any suggestion/ sample to achieve this, would be helpful here. Below is my code for resource server.
public class SocialApplication extends WebSecurityConfigurerAdapter {
#Autowired
CustomLdapAuthoritiesPopulator ldapAuthoritiesPopulator;
#Autowired
CustomLogoutSuccessHandler customLogoutSuccessHandler;
#RequestMapping({ "/user", "/me" })
public Map<String, String> user(Principal principal) {
Map<String, String> map = new LinkedHashMap<>();
map.put("name", principal.getName());
return map;
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/page1Prv");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().antMatchers("/login", "/index**", "/webjars/**").permitAll()
.anyRequest().authenticated().and().authorizeRequests().anyRequest().fullyAuthenticated().and()
.formLogin().loginPage("/login").defaultSuccessUrl("/").and().logout()
.logoutSuccessHandler(customLogoutSuccessHandler).permitAll().and().csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
//.userDetailsService(userDetailsService);
http.httpBasic().and().authorizeRequests().anyRequest().authenticated().and().csrf().disable();
}
#Override
protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.ldapAuthentication()
.contextSource()
.url("ldap://localhost:10389/dc=example,dc=com").managerDn("uid=admin,ou=system")
.managerPassword("secret").and()
.ldapAuthoritiesPopulator(ldapAuthoritiesPopulator)
.userSearchBase("ou=users").userSearchFilter("(cn={0})");
}
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/me").authorizeRequests().anyRequest().authenticated();
}
}
public static void main(String[] args) {
SpringApplication.run(SocialApplication.class, args);
}
}

I returned the Principal object from user(). see below code, and it solved my problem.
#RequestMapping({ "/user", "/me" })
public Principal user(Principal principal) {
return principal;
}

Related

spring security - Home page setup for authorize and unauthorize user

i'm stuck in spring security configuration. can any one help me for better solution. i have 2 jsp page one for login user and other for simple user. in which login user have option for logout and while in other jsp have option for login and signup.
my secuirty configuration class
#Configuration
#EnableWebSecurity
public class SecureConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsService userDetailsService;
#Value("${winni.auth.exit}")
private String authExit;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().requestMatchers()
.antMatchers("/login","/web/**" ,"/exit","/action/**","/cart/**","/cart/xhr/**","/buyer/**")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().permitAll().and()
.logout().logoutSuccessUrl(authExit);
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/assets/**","/account/**","/start/**");
}
}
home controller is
#RequestMapping("/")
public String sayHello(Principal principal) {
if (principal != null) {
return "login_user";
} else {
return "simple_user";
}
}
in every case Principal Object also null. how can solve this issue.

How to configure oAuth2 when Authorization Server is also the Resource server

I'm trying to setup a very basic oAuth2 authentication in spring boot 2.x.x using either authorization code grant or implicit grant but I can't seem to access the Resource server (which resides in the same spring boot app as the Authorization server) after the token is obtained.
Following is the configuration of WebSecurityConfigurerAdapter
#EnableWebSecurity
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final String[] IGNORE_URIS = {
"/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**",
"/resources/**",
"/h2-console/**",
"/common/**",
"/configuration/ui",
"/configuration/security",
"/error"
};
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers(IGNORE_URIS);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/product/**")
.hasAnyRole("ADMIN").and()
.httpBasic().and().formLogin().and().authorizeRequests().anyRequest().authenticated();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("{noop}admin").roles("ADMIN");
}
#Bean
public PasswordEncoder bCrypt() {
return new BCryptPasswordEncoder();
}
And the AuthorizationServerConfigurerAdapter
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
#Autowired
public AuthorizationServerConfiguration(AuthenticationConfiguration authenticationConfiguration) throws Exception {
this.authenticationManager = authenticationConfiguration.getAuthenticationManager();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("my-client-id")
.authorizedGrantTypes("authorization_code", "implicit")
.authorities("ADMIN")
.scopes("all")
.resourceIds("product_api")
.secret("{noop}secret").redirectUris("https://google.com").accessTokenValiditySeconds(0);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
So far so good. I am able to reach the default Spring login page by typing the following Url in the browser.
http://localhost:8080/oauth/authorize?response_type=token&client_id=my-client-id&redirect_uri=https://google.com
Then The login page shows up and I enter my credentials.
After I log in I can then grant access to "my-client-id" app.
Eventually after I approve the app I can see the newly generated access token in the URL bar of the browser which is something like this.
https://www.google.com/#access_token=f2153498-6a26-42c6-93f0-80825ef03b16&token_type=bearer&scope=all
My question is that All of this flow won't work when I also configure a Resource Server.
#EnableResourceServer
#Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId("product_api");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/**")
.and().authorizeRequests()
.antMatchers("/**").permitAll();
}
}
What am I doing wrong? When I try to access the oauth/authorize url as before I get the following:
Why? How can one access the login page and retrieve the token? What Am I missing?
You need to use
#Order
Annotation to specify order for WebMvc and ResourceServer classes
#EnableWebSecurity
#Configuration
#Order(1)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}
and for Resource Server
#EnableResourceServer
#Configuration
#Order(2)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
...
}
If you want to see workable example, you can check it here https://github.com/alex-petrov81/stackoverflow-answers/tree/master/auth-server-also-resource
I've created it from your code example.

Spring boot security get username and password from authentication login to access rest services

I am new to Spring. Client requests to access the rest services, giving username and password in http login provided by Spring, as shown in the image. I don't want to save credentials('username and password') in the application.properties. When I provide the credentials and enter login button, I need to read data (in my case username-'root' and pwd-'root') provided by the user from login and use it in my algorithm, do the process and then authenticate. Is there a way?
Please help me, if anyone has any idea.
authentication login screen
Here is my sample code:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private MyBasicAuthenticationEntryPoint authEntryPoint;
#Autowired
private MyUserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// auth.inMemoryAuthentication().withUser("user1").password("user1Pass").roles("ADMIN")
// .and().withUser("user2").password("user2Pass").roles("ADMIN");
auth.authenticationProvider(authenticationProvider());
}
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
// provider.setPasswordEncoder(new BCryptPasswordEncoder());
return provider;
}
// I am trying like this but not sure is this the right way
public void details(User user) {
String name = user.getName();
String password = user.getPassword();
System.out.println("name " + name + "password" + password);
}
// I am trying like this but not sure is this the right way
public void userDetails(UsernamePasswordAuthenticationFilter filter) {
String usernameParameter = filter.getUsernameParameter();
System.out.println(usernameParameter);
String passwordParameter = filter.getPasswordParameter();
System.out.println(passwordParameter);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().anyRequest().authenticated();
http.httpBasic().authenticationEntryPoint(authEntryPoint);
}
}
#Component
public class MyBasicAuthenticationEntryPoint extends
BasicAuthenticationEntryPoint{
#Override
public void commence(HttpServletRequest request, HttpServletResponse
response,
AuthenticationException authException) throws IOException,
ServletException {
response.addHeader("WWW-Authenticate", "Basic realm=" +
getRealmName());
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter printWriter= response.getWriter();
printWriter.println("Http Status 401-" + authException.getMessage());
}
#Override
public void afterPropertiesSet() throws Exception {
//RealName appears in the login window
setRealmName("Rashmi");
super.afterPropertiesSet();
}
}
#SpringBootApplication
public class SpringRestfulWebServiceApplication extends
SpringBootServletInitializer {
#Autowired
CustomerDetailsController customerDetailsController;
public static void main(String[] args) {
SpringApplication.run(SpringRestfulWebServiceApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder
application) {
return application.sources(SpringRestfulWebServiceApplication.class);
}
}

Oauth2 with Spring Security Basic Authentication

I have a oauth2 service and I have a client. I'm trying to login with my oauth2 service but I keep getting "user must be login to get authentication". I'm trying to send user to oauth service to login then I'm trying to gettin the token but when I try that pop-up security login opens and I can't get authentication from my oauth2 service. When I login that pop-up security login then I can get authentication. Am I missing something? Please I need help.
My auth service class:
#SpringBootApplication
#EnableResourceServer
#Order(6)
public class AuthServiceApplication {
public static void main(String[] args) {
SpringApplication.run(AuthServiceApplication.class, args);
}
}
#RestController
class PrincipalRestController {
#RequestMapping({"/user", "/me"})
Principal principal(Principal principal) {
System.out.println(SecurityContextHolder.getContext().getAuthentication().getPrincipal());
return principal;
}
#RequestMapping("/giris")
Principal giris(Principal principal) {
return principal;
}
}
#Configuration
#EnableAuthorizationServer
class OAuthConfiguration extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
#Autowired
public OAuthConfiguration(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
// security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(this.authenticationManager);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("acme")
.secret("acmesecret")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.scopes("openid", "read", "write").autoApprove(".*");
}
}
//#Component
//class AccountCLR implements CommandLineRunner {
//
// #Override
// public void run(String... strings) throws Exception {
// Stream.of("jlong,spring", "pwebb,boot", "zeynep,Bisoft123").map(x -> x.split(",")).forEach(tuple -> this.accountRepository.save(new Account(tuple[0], tuple[1], true)));
// }
//
// private final AccountRepository accountRepository;
//
// #Autowired
// public AccountCLR(AccountRepository accountRepository) {
// this.accountRepository = accountRepository;
// }
//
//}
#Service
class AccountUserDetailService implements UserDetailsService {
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return accountRepository.findByKullaniciAdi(username);
}
private final KullaniciRepository accountRepository;
#Autowired
public AccountUserDetailService(KullaniciRepository accountRepository) {
this.accountRepository = accountRepository;
}
}
//My web security config
#Configuration
#EnableWebSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
//#EnableOAuth2Client
//#EnableAuthorizationServer
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/css/**", "/metronic/css/**").permitAll()
.and().authorizeRequests().antMatchers("/metronic/image/**", "/image/**", "/metronic/css/fonts/**", "/metronic/fonts/**").permitAll()
.and().authorizeRequests().antMatchers("/js/**", "/metronic/js/**").permitAll()
.and().httpBasic().and().authorizeRequests()
.antMatchers("/login.html", "/language/**","/uaa/*", "/api/kullanici/user", "/logout", "/kilitEkrani.html", "/404.html").permitAll()
.anyRequest().authenticated().and()
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class).csrf().csrfTokenRepository(csrfTokenRepository()).and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login.html")
.permitAll().and().csrf().disable();
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
//my resource server
#Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/me")
.authorizeRequests().anyRequest().authenticated();//.and().csrf().csrfTokenRepository(csrfTokenRepository());
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
// #Autowired
// public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// auth
// .inMemoryAuthentication()
// .withUser("zeynep").password("Bisoft123").roles("USER");
// }
}

Custom Authentication provider with Spring Security and Java Config

How can I define a custom Authentication provider by using Spring Security with Java Configurations?
I would like to perform a login checking credentials on my own database.
The following does what you need (CustomAuthenticationProvider is your implementation which needs to be managed by Spring)
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
#Override
protected void configure(HttpSecurity http) throws Exception {
/**
* Do your stuff here
*/
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
}
As shown on baeldung.com, define your authentication provider as follow:
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String name = authentication.getName();
String password = authentication.getCredentials().toString();
if (shouldAuthenticateAgainstThirdPartySystem(username, password)) {
// use the credentials
// and authenticate against the third-party system
return new UsernamePasswordAuthenticationToken(
name, password, new ArrayList<>());
} else {
return null;
}
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(
UsernamePasswordAuthenticationToken.class);
}
}
and following code is corresponding java config:
#Configuration
#EnableWebSecurity
#ComponentScan("org.project.security")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider authProvider;
#Override
protected void configure(
AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic();
}
}

Resources