How to use WebSecurity adapter with Spring-Security-OAuth2 - spring

I am trying to achieve authentication system using OAuth2 as well as simple Spring Security(Web Security adapter). But as I am trying to configure, I am not able to use both the services together. As per configuration file code shared below, But It will work either OAuth2 or simple auth using spring security(Web Security adapter). I want both the authentication system should work based on URL identification.
Thanks in advance!
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = true)
public class ConfigurationClass {
// Its working as simple auth spring security
#EnableWebSecurity
#Configuration
#Order(1)
protected static class StatelessAuthenticationSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private TokenAuthenticationService tokenAuthenticationService;
#Autowired
private OtpManage OtpManage;
#Autowired
private RoleRepository RoleRepository;
public StatelessAuthenticationSecurityConfig() {
super(true);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// allow anonymous resource requests
.antMatchers("/").permitAll()
// allow anonymous POSTs to login
.antMatchers(HttpMethod.POST, "/user/registration").permitAll()
.antMatchers(HttpMethod.POST, "/user/changepassword").permitAll()
.antMatchers(HttpMethod.POST, "/user/resetpassword").permitAll()
// .antMatchers(HttpMethod.POST,
// "/api/otpResetPassword").permitAll()
.antMatchers(HttpMethod.POST, "/user/saveusergroup").permitAll()
.antMatchers(HttpMethod.POST, "/user/bugreport").permitAll()
.antMatchers(HttpMethod.POST, "/user/createtoken").permitAll()
// .anyRequest().authenticated().and()
.anyRequest().hasAnyRole("USER","SYSTEM_ADMIN","ADMIN").and()
// custom JSON based authentication by POST of
// {"username":"<name>","password":"<password>"} which sets the
// token header upon authentication
.addFilterBefore(new StatelessLoginFilter("/api/login", tokenAuthenticationService, userDetailsService,
authenticationManager(), OtpManage), UsernamePasswordAuthenticationFilter.class)
// custom Token based authentication based on the header
// previously given to the client
.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService),
UsernamePasswordAuthenticationFilter.class);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
#Override
protected UserDetailsService userDetailsService() {
return userDetailsService;
}
}
// Its not working, But if I removed #Order(1) annotation from StatelessAuthenticationSecurityConfig class then this one will work as default
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Autowired
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
#Autowired
private CustomLogoutSuccessHandler customLogoutSuccessHandler;
#Override
public void configure(HttpSecurity http) throws Exception {
System.out.println("#EnableResourceServer");
http
.exceptionHandling()
.authenticationEntryPoint(customAuthenticationEntryPoint)
.and()
.logout()
.logoutUrl("/oauth/logout")
.logoutSuccessHandler(customLogoutSuccessHandler)
.and()
.csrf()
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))
.disable()
.headers()
.frameOptions().disable().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/hello/").permitAll()
.antMatchers("/secure/**").authenticated();
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter implements EnvironmentAware {
private static final String ENV_OAUTH = "authentication.oauth.";
private static final String PROP_CLIENTID = "clientid";
private static final String PROP_SECRET = "secret";
private static final String PROP_TOKEN_VALIDITY_SECONDS = "tokenValidityInSeconds";
private RelaxedPropertyResolver propertyResolver;
#Autowired
private DataSource dataSource;
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(tokenStore())
.authenticationManager(authenticationManager);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
System.out.println("#AuthorizationServerConfigurerAdapter");
clients
.inMemory()
.withClient(propertyResolver.getProperty(PROP_CLIENTID))
.scopes("read", "write")
.authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name())
.authorizedGrantTypes("password", "refresh_token")
.secret(propertyResolver.getProperty(PROP_SECRET))
.accessTokenValiditySeconds(propertyResolver.getProperty(PROP_TOKEN_VALIDITY_SECONDS, Integer.class, 1800));
}
#Override
public void setEnvironment(Environment environment) {
this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_OAUTH);
}
}
}
Update:
I have made few changes to my code with #EnableOAuth2Client, #Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) and I have achieved what exactly I want to do. But now the issue is I am not able call to post url: "/api/login" with user credentials. I am getting error as url not found. as per my code in WebSecurityConfig class, I have added filter in configure(HttpSecurity http) method for loginFilter class which extends AbstractAuthenticationProcessingFilter. But this filter which is mapped with "/api/login" url not working at all. Why this one filter is not working I don`t understand. Someone could you help me regarding the same.
#WebSecurityConfigClass
/**
* Implementation of HttpSecurity configure method
* Implementation custom JSON based authentication by POST of {"username":"<name>","password":"<password>"} which sets the token header upon authentication
* #author Santosh
*
*/
#EnableOAuth2Client
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true, securedEnabled = true, proxyTargetClass = true)
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private TokenAuthenticationService tokenAuthenticationService;
#Autowired
private MessageSource messages;
#Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
#Autowired
private RESTAuthenticationSuccessHandler restAuthenticationSuccessHandler;
#Autowired
private RESTAuthenticationFailureHandler restAuthenticationFailureHandler;
#Autowired
private CustomAccessDeniedHandler accessDeniedHandler;
public WebSecurityConfig() {
super(true);
}
/*#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
auth.inMemoryAuthentication().withUser("testUser").password("testUser").roles("USER");
}
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
// setup security
http
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.authorizeRequests()
.anyRequest()
.fullyAuthenticated()
.and().httpBasic();
http
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.anonymous().and()
.servletApi().and()
.headers().and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/login").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.and()
.authorizeRequests()
.anyRequest().hasAnyRole("USER").and()
//all other request need to be authenticated
// custom JSON based authentication by POST of {"username":"<name>","password":"<password>"} which sets the token header upon authentication
.addFilterBefore(new LoginFilter("/api/login", tokenAuthenticationService, userDetailsService, authenticationManager(), restAuthenticationSuccessHandler, restAuthenticationFailureHandler), UsernamePasswordAuthenticationFilter.class)
// custom Token based authentication based on the header previously given to the client
.addFilterBefore(new ApplicationFilter (tokenAuthenticationService, messages), UsernamePasswordAuthenticationFilter.class);
}
// To allow Pre-flight [OPTIONS] request from browser
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
web.ignoring()//allow anonymous GETs to API
.antMatchers(HttpMethod.GET, "/api/status/**");
}
#Bean
public RequestContextListener requestContextListener(){
return new RequestContextListener();
}
#Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
#Bean
public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint(){
return new CustomBasicAuthenticationEntryPoint();
}
#Bean(name="authenticationManagerBean")
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
#OAuth2ServerConfiguration
#Configuration
public class OAuth2ServerConfiguration {
private static final String RESOURCE_ID = "restservice";
private static final String ROLE_ADMIN = "ADMIN";
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Autowired
private CustomOAuth2AccessDeniedHandler accessDeniedHandler;
#Autowired
private RESTOAuth2AuthenticationEntryPoint restAuthenticationEntryPoint;
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/hello").permitAll()
.antMatchers("/users/current/**","/oauth/token","/oauth/authorize","/oauth/refresh_token").permitAll()
.antMatchers("/api/greeting").authenticated().and().exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(restAuthenticationEntryPoint);
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private DataSource dataSource;
#Autowired
private TokenStore tokenStore;
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
// #Autowired
// private UserApprovalHandler userApprovalHandler;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(this.tokenStore).authenticationManager(this.authenticationManager)
.userDetailsService(userDetailsService);
// .userApprovalHandler(userApprovalHandler)
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// jdbc(dataSource)
clients.inMemory().withClient("clientapp").authorizedGrantTypes("password", "refresh_token")
.authorities("USER").scopes("read", "write").resourceIds(RESOURCE_ID).secret("123456")
.accessTokenValiditySeconds(20)// Access token is only valid
// for 2 minutes.
.refreshTokenValiditySeconds(1200);// Refresh token is only
// valid for 10
// minutes.;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenStore(this.tokenStore);
return tokenServices;
}
}
}

On your WebSecurityAdapter you want to build requestMatchers to determine on which requests that instance of HttpSecurity will invoke.
For example :
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/secure/path", "/more/secure/path");
// Rest of your configuration.
}

Related

Error with multiple spring boot security config

I have a spring boot application already secured with JWT and I want to secure the spring actuator endpoint with basic auth in-memory user so I modified the Security config class to include 2 methods
Spring version 2.6.4
The problem
when I set the "ActuatorSecurityConfigurerAdapter" order to -1 and test with user1:user1 I get this error and my API becomes unsecured
JwtAuthenticationEntryPoint: Responding with unauthorized error. Message - Full authentication is required to access this resource
when I set the "ActuatorSecurityConfigurerAdapter" order to 2 i can access both endpoints with JWT
Security Config Class
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true)
public class SecurityConfig {
#Order(1)
#Configuration
public class ApiSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
private final CustomUserDetailsServiceImpl customUserDetailsService;
private final JwtAuthenticationEntryPoint unauthorizedHandler;
private final JwtAuthenticationFilter jwtAuthenticationFilter;
public ApiSecurityConfigurationAdapter(CustomUserDetailsServiceImpl customUserDetailsService, JwtAuthenticationEntryPoint unauthorizedHandler, JwtAuthenticationFilter jwtAuthenticationFilter) {
this.customUserDetailsService = customUserDetailsService;
this.unauthorizedHandler = unauthorizedHandler;
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
}
#Bean(BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(Endpoints.AUTH_ENDPOINT+"/**").permitAll()
.anyRequest()
.authenticated();
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
}
#Order(2)
#Configuration
public class ActuatorSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Autowired
AuthenticationEntryPoint authenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/actuator/**").hasRole("MODERATOR")
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1")
.password(passwordEncoder().encode("user1"))
.authorities("MODERATOR");
}
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Problem Solved
I put Order(1) for the actuator security and Order(2) for the rest of my API
To use the in-memory user I had to add "ROLE_" prefix for the authorities like ROLE_MODERATOR and in the HTTP security method I just added .hasRole("MODERATOR")
and this is the final SecurityConfig.class
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true)
public class SecurityConfig {
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Order(2)
#Configuration
public class ApiSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
private final CustomUserDetailsServiceImpl customUserDetailsService;
private final JwtAuthenticationEntryPoint unauthorizedHandler;
private final JwtAuthenticationFilter jwtAuthenticationFilter;
public ApiSecurityConfigurationAdapter(CustomUserDetailsServiceImpl customUserDetailsService, JwtAuthenticationEntryPoint unauthorizedHandler, JwtAuthenticationFilter jwtAuthenticationFilter) {
this.customUserDetailsService = customUserDetailsService;
this.unauthorizedHandler = unauthorizedHandler;
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
}
#Bean(BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(Endpoints.AUTH_ENDPOINT + "/**").permitAll()
.anyRequest()
.authenticated();
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
}
#Order(1)
#Configuration
public class ActuatorSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Autowired
JwtAuthenticationEntryPoint actuatorAuthenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable().
exceptionHandling().authenticationEntryPoint(actuatorAuthenticationEntryPoint).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.antMatcher(Endpoints.ACTUATOR_ENDPOINT+"/**")
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1")
.password(passwordEncoder().encode("user1"))
.authorities("ROLE_ADMIN");
}
}
}

Spring Boot OAuth2 authentication with login form

i am new to Spring Boot and OAuth2 , i found ressources on github and trying to practice to understand more the architecture and flows, so i have the configuration as follow :
OAuth2Configuration.java
#Configuration
public class OAuth2Configuration {
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Autowired
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
#Autowired
private CustomLogoutSuccessHandler customLogoutSuccessHandler;
#Override
public void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(customAuthenticationEntryPoint)
.and()
.logout()
.logoutUrl("/oauth/logout")
.logoutSuccessHandler(customLogoutSuccessHandler)
.and()
.csrf()
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))
.disable()
.headers()
.frameOptions().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/secure/**", "/person/**", "/product/**").authenticated()
.antMatchers(HttpMethod.GET, "/user/**").authenticated()
.antMatchers(HttpMethod.PUT, "/user/**").authenticated()
.antMatchers(HttpMethod.DELETE, "/user/**").authenticated()
.antMatchers(HttpMethod.POST, "/user").permitAll();
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter implements EnvironmentAware {
private static final String ENV_OAUTH = "authentication.oauth.";
private static final String PROP_CLIENTID = "clientid";
private static final String PROP_SECRET = "secret";
private static final String PROP_TOKEN_VALIDITY_SECONDS = "tokenValidityInSeconds";
private RelaxedPropertyResolver propertyResolver;
#Autowired
private DataSource dataSource;
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(tokenStore())
.authenticationManager(authenticationManager);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient(propertyResolver.getProperty(PROP_CLIENTID))
.scopes("read", "write")
.authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name())
.authorizedGrantTypes("password", "refresh_token")
.secret(propertyResolver.getProperty(PROP_SECRET))
.redirectUris("http://localhost:8080/login")
.accessTokenValiditySeconds(propertyResolver.getProperty(PROP_TOKEN_VALIDITY_SECONDS, Integer.class, 1800));
}
#Override
public void setEnvironment(Environment environment) {
this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_OAUTH);
}
}
}
SecurityConfiguration.java
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Bean
public PasswordEncoder passwordEncoder() {
// Define the type of encode
return new BCryptPasswordEncoder();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
//.antMatchers("/h2console/**")
.antMatchers("/register")
.antMatchers("/activate")
.antMatchers("/lostpassword")
.antMatchers("/resetpassword")
//.antMatchers("/hello")
.antMatchers("/person")
.antMatchers("/product");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
private static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration {
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
}
CustomAuthenticationEntryPoint.java
#Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
private final Logger log = LoggerFactory.getLogger(CustomAuthenticationEntryPoint.class);
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException ae) throws IOException, ServletException {
log.info("Pre-authenticated entry point called. Rejecting access");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access Denied");
}
}
what i want to achieve is authenticate users using loging form on browser in order to access protected ressources , but i don't know how in this configuration.
example :
when i access to /product , it shows all products cos it's not secured , but /product/3 for example is protected so it shows a blank webpage with error access denied , i want to show loging form.
when

Spring Security using Oauth | Overriding HttpSecurity

I am Implementing Spring Security using Oauth following these websystique , baeldung,What I found WebSecurityConfigurerAdapter and ResourceServerConfigurerAdapter both provides control over HttpSecurity,and filterchain adds them in order 0 and 3 respectively.
So I am overriding configure of any of the above ConfigurerAdapter but only one at a time.
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.requestMatchers().antMatchers("/api/**").and()
.authorizeRequests()
.antMatchers("/api/ads").permitAll()
.antMatchers("/api/admin").hasAuthority(RoleConstant.ADMIN.getRole())
.antMatchers("/api/user").hasAuthority(RoleConstant.USER.getRole())
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
What I observe in case of WebSecurityConfigurerAdapter I am able to access unauthorized resources ie I am able to access /api/user after being authenticated even with token having authority ADMIN.Why so?
Note : I am not overriding HttpSecurity of ResourceServerConfigurerAdapter.
References : There are similar resources available here. Resource1 , Resource2.
Also I want to know,I must have to override both configure(HttpSecurity http) or any of the class is sufficient?If yes,which one is recommended?
ResourceServer :
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "my_rest_api";
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.requestMatchers().antMatchers("/api/**").and()
.authorizeRequests()
.antMatchers("/api/ads").permitAll()
.antMatchers("/api/admin").hasAuthority(RoleConstant.ADMIN.getRole())
.antMatchers("/api/user").hasAuthority(RoleConstant.USER.getRole())
.antMatchers("/api/readProperty").access("hasRole('ADMIN')")
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
SpringSecurityConfig :
#Configuration
#EnableWebSecurity
#ComponentScan(basePackages = {"com.ttnd.mvc_mod.services","com.ttnd.mvc_mod.repository","com.ttnd.mvc_mod.config","com.ttnd.mvc_mod.custom"})
#Import({SpringORMHibernateSupportConfig.class})
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
private CustomAuthenticationProvider authProvider;
/* #Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.requestMatchers().antMatchers("/**").and()
.authorizeRequests()
.antMatchers("/oauth/token","/api/ads").permitAll()
.antMatchers("/api/admin").hasAuthority(RoleConstant.ADMIN.getRole())
.antMatchers("/api/user").hasAuthority(RoleConstant.USER.getRole())
.antMatchers("/api/readProperty").access("hasRole('ADMIN')")
.and()
.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());//.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint);
}
*/
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//auth.userDetailsService(customUserDetailsService);
auth.authenticationProvider(authProvider);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Bean
#Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
return handler;
}
#Bean
#Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
}

Spring security oauth2.0 restful and Form login config

I have a app that could login with from or by oauth2 alos.
But I met some troubles.
What I met:
When I visit http://127.0.0.1/, it truns to /login page what is right.
When I visit http://127.0.0.1/api/hellos, it also truns to /login page what is exactly wrong. What I want is I can access /api/hellos by using oauth2.
Here is my Security Configuration:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private SpringDataMyBatisUserDetailsService userDetailsService;
#Override
#Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(this.userDetailsService)
.passwordEncoder(Manager.PASSWORD_ENCODER);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
}
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
#Autowired
private TokenStore tokenStore;
#Autowired
private SpringDataMyBatisClientDetailsService clientDetailsService;
#Autowired
public AuthorizationServerConfig(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
/**
* Defines the security constraints on the token endpoints /oauth/token_key and /oauth/check_token
* Client credentials are required to access the endpoints
*
* #param oauthServer
* #throws Exception
*/
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
/**
* Defines the authorization and token endpoints and the token services
*
* #param endpoints
* #throws Exception
*/
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(this.authenticationManager)
.tokenEnhancer(tokenEnhancer())
.tokenStore(tokenStore);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.withClientDetails(clientDetailsService);
}
#Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
}
#Order(1)
#Configuration
public class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/index.html", "/index.css", "/common.js", "/index.js", "/api/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout()
.logoutSuccessUrl("/")
.and().exceptionHandling().accessDeniedPage("/error/403");
}
}
#Configuration
#EnableResourceServer
#Order(2)
public class AuthorizationResourceConfig extends ResourceServerConfigurerAdapter {
#Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
#Autowired
private AuthenticationSuccessHandler successHandler;
#Autowired
private AuthenticationFailureHandler failureHandler;
#Autowired
private TokenStore tokenStore;
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources
.stateless(true)
.tokenStore(tokenStore);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.and()
.anonymous().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().httpBasic()
.and()
.exceptionHandling()
.accessDeniedHandler(new OAuth2AccessDeniedHandler())
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated();
}
}
}
I have tried some ways where I searched from google.But none can help me.
So, I really want someone can help me, I will be appreciated for you.
In addition, the most helpful info I have searched is this.
u use this ".antMatchers("/api/**").fullyAuthenticated(); " ,, in this case will require a "LOG IN " for all actions /api/.... ,, if u dont Want"log in" form for "127.0.0.1/api/hellos "u must to use only /api/ without stars

Spring OAuth2 additional permision

I need to add additional restriction to authenticate users. My User model has a field 'active'. It is false, when User registers, but not activate his account with hash from mail. Now, even if User is not active he gets access_token from Oauth.
How should I configure this?
I was thinking about SpringSecurityInterceptor, but I'm not sure about confusing Spring Security with OAuth2.
This is my SpringOAuth2.0 configuration:
#Configuration
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {
private static final String RESOURCE_ID = "restservice";
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends
ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
.resourceId(RESOURCE_ID);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(new OrRequestMatcher(
new AntPathRequestMatcher("/rest/**")
))
.authorizeRequests()
.anyRequest().access("#oauth2.hasScope('read')");
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends
AuthorizationServerConfigurerAdapter {
private TokenStore tokenStore = new InMemoryTokenStore();
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Autowired
UserDetailsService userDetailsService;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(this.tokenStore)
.authenticationManager(this.authenticationManager)
.userDetailsService(userDetailsService)
.pathMapping("/oauth/token", "/rest/oauth/token");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("clientapp")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("USER")
.scopes("read", "write", "trust")
.resourceIds(RESOURCE_ID)
.secret("123456");
}
}
}
And also Spring security
#Configuration
#Order(2147483640)
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
DataSource dataSource;
#Autowired
UserDetailsService userDetailsService;
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/user/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("email")
.passwordParameter("password")
.defaultSuccessUrl("/user/")
.successHandler(successHandler())
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.rememberMe()
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(86400)
.and()
.csrf().disable();
}
#Bean
public AuthenticationSuccessHandler successHandler() {
return new UserLoginSuccessHandler();
}
#Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepositoryImpl = new JdbcTokenRepositoryImpl();
tokenRepositoryImpl.setDataSource(dataSource);
return tokenRepositoryImpl;
}
#Bean
public SpringSecurityDialect securityDialect() {
return new SpringSecurityDialect();
}
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Any advice would be helpful.
If I understand you correctly, you don't want your authorization server to grant an access token for a user that is not activated?
You could let your UserDetailsService.loadUserByUsername throw a UsernameNotFoundException if the user exists, but is not activated.

Resources