Spring Security Custom Authfilter doesnt work - spring

i am working in a personal project and i using spring web mvc and spring security 4, all annotation based configs, and my custom UsernamePasswordAuthenticationFilter is never reached, i am losing it, i already search but i can get it solved, so if anyone could help, i 'd be very grateful, So here is my code
Spring Initialization
#Order(1)
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{AppConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
Security Initialization
#Order(2)
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
Spring beans declarations and context stuff
#EnableWebMvc
#Configuration
#ComponentScan({"app","server"})
#Import({ SecurityContext.class })
public class AppConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/META-INF/resources/");
}
#Bean
public InternalResourceViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setSuffix(".jsp");
resolver.setPrefix("/WEB-INF/views/");
resolver.setContentType("text/html; charset=UTF-8");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Bean
public DriverManagerDataSource dataSource(){
DriverManagerDataSource driver = new DriverManagerDataSource();
driver.setDriverClassName("com.mysql.jdbc.Driver");
driver.setUrl("jdbc:mysql://localhost:3306/dberp-1");
driver.setUsername("root");
driver.setPassword("123456");
return driver;
}
#Bean
public LocalSessionFactoryBean sessionFactory(){
LocalSessionFactoryBean session = new LocalSessionFactoryBean();
session.setDataSource(dataSource());
String[] pakages = {"model"};
session.setPackagesToScan(pakages);
Properties prop = new Properties();
prop.put("dialect", MySQLDialect.class);
session.setHibernateProperties(prop);
return session;
}
}
I am almost sure i am doing something wrong in this SecurityContext class....
#Configuration
#EnableWebSecurity
public class SecurityContext extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception{
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint())
.and()
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/login","/resources/**").anonymous()
.antMatchers("/users").hasAuthority("admin")
.antMatchers("/**").hasAnyAuthority("employee","admin")
.and()
.logout()
.logoutSuccessUrl("/login")
.invalidateHttpSession(true)
.logoutUrl("/logout")
.and()
.csrf().disable();
}
#Bean
public AuthenticationEntryPoint authenticationEntryPoint(){
AuthenticationEntryPoint entryAuth = new LoginUrlAuthenticationEntryPoint("/login");
return entryAuth;
}
#Bean(name="customAuthenticationManager")
#Override
protected AuthenticationManager authenticationManager() throws Exception {
AuthenticationManager authManager = new CustomAuthenticationManager();
return authManager;
};
#Bean
public UsernamePasswordAuthenticationFilter authenticationFilter() throws Exception{
/*UsernamePasswordAuthenticationFilter authFilter = new UsernamePasswordAuthenticationFilter();
authFilter.setAuthenticationManager(authenticationManager());
authFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/home"));
authFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/login?error"));*/
UsernamePasswordAuthenticationFilter authFilter = new AuthFilter();
authFilter.setAuthenticationManager(authenticationManager());
authFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/home"));
authFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/login?error"));
authFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST"));
return authFilter;
}
}

Related

Getting Spring Security KeyCloak Adapter and Spring Security ACL to play together

I have a grails 4 application that uses Spring Security ACL to protect access to resources. I am trying to incorporate KeyCloak SSO into the mix and unable to figure out how to bridge the two worlds. I've configured KeyCloak Authentication and after login can see keyCloakPrincipal on SpringSecurity Context. How do I go from here to set up the roles for ACL?
here is my keycloak adapter:
#Configuration
#EnableWebSecurity
#ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(
AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider
= keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(
new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
#Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(
new SessionRegistryImpl());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/customers*")
.hasRole("user")
.anyRequest()
.permitAll();
}
}
and here is my ACL:
#Autowired
DataSource dataSource;
#Bean
public AclAuthorizationStrategy aclAuthorizationStrategy() {
return new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_ADMIN"));
}
#Bean
public PermissionGrantingStrategy permissionGrantingStrategy() {
return new DefaultPermissionGrantingStrategy(
new ConsoleAuditLogger());
}
#Bean
public EhCacheBasedAclCache aclCache() {
return new EhCacheBasedAclCache(
aclEhCacheFactoryBean().getObject(),
permissionGrantingStrategy(),
aclAuthorizationStrategy()
);
}
#Bean
public EhCacheFactoryBean aclEhCacheFactoryBean() {
EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject());
ehCacheFactoryBean.setCacheName("aclCache");
return ehCacheFactoryBean;
}
#Bean
public EhCacheManagerFactoryBean aclCacheManager() {
return new EhCacheManagerFactoryBean();
}
#Bean
public LookupStrategy lookupStrategy() {
return new BasicLookupStrategy(
dataSource,
aclCache(),
aclAuthorizationStrategy(),
new ConsoleAuditLogger()
);
}
How do I

Spring OAuth security - Implicit flow

Is it possible to implement OAuth implicit flow with spring security? I want to create both auth and resource server in the same application. I need standard auth endpoints for authentication and authorization and some custom endpoints for handling with users (create/update/list...).
Requirements:
implicit flow
custom login page (/my_login_page)
silent mode for obtaining token (/oauth/authorize?...&prompt=none)
secured custom endpoints with OAuth (/users)
I'm stuck with configuration. Whatever I do, the requirements above never work together.
Spring WebSecurityConfig
#Configuration
#Order(-10)
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private MyAuthenticationProvider authenticationProvider;
private MyAuthenticationDetailsSource authenticationDetailsSource;
#Autowired
public SecurityConfig(MyAuthenticationProvider authenticationProvider, MyAuthenticationDetailsSource authenticationDetailsSource) {
this.authenticationProvider = authenticationProvider;
this.authenticationDetailsSource = authenticationDetailsSource;
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(authenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
.sessionFixation().newSession()
.and()
.authorizeRequests()
.antMatchers("/assets/**", "/swagger-ui.html", "/webjars/**", "/swagger-resources/**", "/v2/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/my_login_page")
.loginProcessingUrl("/my_process_login")
.usernameParameter("my_username")
.passwordParameter("pmy_assword")
.authenticationDetailsSource(authenticationDetailsSource)
.permitAll();
}
}
Spring AuthorizationServerConfig
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private ResourceLoader resourceLoader;
private AuthProps authProps;
#Autowired
public OAuth2AuthorizationServerConfig(ResourceLoader resourceLoader, AuthProps authProps) {
this.resourceLoader = resourceLoader;
this.authProps = authProps;
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
#Qualifier("jwtAccessTokenConverter")
public JwtAccessTokenConverter accessTokenConverter() {
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resourceLoader.getResource(authProps.getAuthServerPrivateCertPath()), authProps.getAuthServerPrivateCertKey().toCharArray());
JwtAccessTokenConverter converter = new MYJwtAccessTokenConverter();
converter.setKeyPair(keyStoreKeyFactory
.getKeyPair(authProps.getAuthServerPrivateCertAlias()));
final Resource resource = resourceLoader.getResource(authProps.getAuthServerPublicCertPath());
String publicKey;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter());
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("my-secured-client")
.secret("foo")
.authorizedGrantTypes("implicit")
.scopes("read", "write")
.resourceIds("my-resource")
.authorities("CLIENT")
.redirectUris(
"http://localhost:4200"
)
.accessTokenValiditySeconds(300)
.autoApprove(true);
}
}
Spring ResourceServerConfig
#Configuration
#EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
private AuthProps authProps;
private TokenStore tokenStore;
private DefaultTokenServices tokenServices;
#Autowired
public OAuth2ResourceServerConfig(AuthProps authProps, TokenStore tokenStore, DefaultTokenServices tokenServices) {
this.authProps = authProps;
this.tokenStore = tokenStore;
this.tokenServices = tokenServices;
}
#Override
public void configure(final ResourceServerSecurityConfigurer config) {
config
.resourceId("my-resource")
.tokenStore(tokenStore)
.tokenServices(tokenServices);
}
#Override
public void configure(final HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/**").authenticated()
.and()
.csrf().disable();
}
}
I placed WebSecurityConfig before ResourceServerConfig otherwise login page doesn't work. But now I can't access my custom endpoint for users (I'm redirected to the login page). If I place ResourceServerConfig before WebSecurityConfig login page stop working. I get 404 not found response when I submit login page form.
I also have an issue with silent mode to obtain a new access token. When calling /oauth/authorize with still valid access_token I'm redirected to the login page.
Finally I found a solution:
ResourceServerConfig have to be before WebSecurityConfig
loginProcessingUrl should be /oauth/authorize
Silent refresh works by default until session is valid (login form)
Custom endpoint for logout where invalidate current session
EDITED:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private MyAuthenticationProvider authenticationProvider;
private MyAuthenticationDetailsSource authenticationDetailsSource;
#Autowired
public SecurityConfig(MyAuthenticationProvider authenticationProvider, MyAuthenticationDetailsSource authenticationDetailsSource) {
this.authenticationProvider = authenticationProvider;
this.authenticationDetailsSource = authenticationDetailsSource;
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) {
auth
.authenticationProvider(authenticationProvider);
}
#Override
public void configure(WebSecurity web) {
web
.debug(true)
.ignoring()
.antMatchers(HttpMethod.OPTIONS)
.antMatchers("/my-custom-login-page", "/my-custom-logout-page")
.antMatchers("/assets/**", "/swagger-ui.html", "/webjars/**", "/swagger-resources/**", "/v2/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/my-custom-login-page")
.loginProcessingUrl("/oauth/authorize")
.usernameParameter("myUsernameParam")
.passwordParameter("myPasswordParam")
.authenticationDetailsSource(authenticationDetailsSource)
.permitAll()
.and()
.csrf().disable();
}
}
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private ResourceLoader resourceLoader;
private AuthProps authProps;
#Autowired
public OAuth2AuthorizationServerConfig(ResourceLoader resourceLoader, AuthProps authProps) {
this.resourceLoader = resourceLoader;
this.authProps = authProps;
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
#Qualifier("jwtAccessTokenConverter")
public JwtAccessTokenConverter accessTokenConverter() {
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(resourceLoader.getResource(authProps.getAuthServerPrivateCertPath()), authProps.getAuthServerPrivateCertKey().toCharArray());
JwtAccessTokenConverter converter = new MyJwtAccessTokenConverter();
converter.setKeyPair(keyStoreKeyFactory.getKeyPair(authProps.getAuthServerPrivateCertAlias()));
final Resource resource = resourceLoader.getResource(authProps.getAuthServerPublicCertPath());
String publicKey;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter());
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient(authProps.getAuthServerClientId())
.secret(authProps.getAuthServerClientSecret())
.authorizedGrantTypes("implicit")
.scopes("read", "write")
.resourceIds(authProps.getAuthServerResourceId())
.authorities("CLIENT")
.redirectUris(
"http://localhost:4200/#/login",
"http://localhost:4200/assets/silent-refresh.html",
"http://localhost:8080/my-api/webjars/springfox-swagger-ui/oauth2-redirect.html"
)
.accessTokenValiditySeconds(authProps.getAuthServerAccessTokenValiditySeconds())
.autoApprove(true);
}
}
#Configuration
#EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
private AuthProps authProps;
private TokenStore tokenStore;
private DefaultTokenServices tokenServices;
#Autowired
public OAuth2ResourceServerConfig(AuthProps authProps, TokenStore tokenStore, DefaultTokenServices tokenServices) {
this.authProps = authProps;
this.tokenStore = tokenStore;
this.tokenServices = tokenServices;
}
#Override
public void configure(final ResourceServerSecurityConfigurer config) {
config.resourceId(authProps.getAuthServerResourceId()).tokenStore(tokenStore);
config.resourceId(authProps.getAuthServerResourceId()).tokenServices(tokenServices);
}
#Override
public void configure(final HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.anyRequest().hasRole(AppRole.ROLE_APP_USER.split("ROLE_")[1])
.and()
.csrf().disable();
}
}
#Controller
public class MainController {
#Autowired
public MainController() {
...
}
#GetMapping("/my-custom-login-page")
public ModelAndView loginPage(HttpServletRequest request, HttpServletResponse response) {
ModelAndView mv = new ModelAndView("login-page");
return mv;
}
#GetMapping("/my-custom-logout-page")
public ModelAndView logoutPage(HttpServletRequest request) {
ModelAndView mv = new ModelAndView("logout-page");
HttpSession session = request.getSession(false);
if (Objects.isNull(session)) {
mv.addObject("msg", "NO SESSION");
return mv;
}
session.invalidate();
mv.addObject("msg", "SUCCEEDED");
return mv;
}
}
In addition to #user3714967 answer, I add some tips maybe It helps someone. The problem is that we are defining multiple HttpSecurity (The resourceServer is a WebSecurityConfigurerAdapter with order 3). The solution is to use HttpSecurity.requestMatchers() with the specific value.
Example
First Class:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("url1", "url2", ...).and()
.authorizeRequests()
.antMatchers(...).and()...
}
}
Second Class:
#Configuration
#EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers("url3", "url4", ...)
.and()
.authorizeRequests()
.antMatchers(...).and()...
}
}
}
This will be useful when we have more than flow (password && implicit flows for my case).

Spring stops serving static resources after messageSource is created

After creatig messageSource bean in spring webMvcConfigurer my application stops serving static resources(images/css/js) with http status 404, but all files have a right path(I'm completely sure that error somewhere within messageSource because without this bean serving works correctly). Maybe you have idea how to resolve this problem?
My WebMvcConfigurerImpl:
#Configuration
#Import({dbConfig.class})
#EnableWebMvc
#EnableSpringDataWebSupport
#ComponentScan("my.shop.common.fliPusto")
#PropertySource("classpath:properties/resources.properties")
public class mvcConfig implements WebMvcConfigurer {
#Value("${uploadBook.path}")
private String bookPath;
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**")
.addResourceLocations("file:/" + bookPath + "/images/");
registry.addResourceHandler("/scripts/**")
.addResourceLocations("file:/" + bookPath + "/scripts/");
registry.addResourceHandler("/styles/**")
.addResourceLocations("file:/" + bookPath + "/styles/");
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
#Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("classpath:freemarkerTemplates/");
configurer.setDefaultEncoding("UTF-8");
return configurer;
}
#Bean
public FreeMarkerViewResolver freeMarkerViewResolver() {
FreeMarkerViewResolver freeMarkerViewResolver = new FreeMarkerViewResolver();
freeMarkerViewResolver.setCache(false);
freeMarkerViewResolver.setPrefix("");
freeMarkerViewResolver.setSuffix(".ftl");
freeMarkerViewResolver.setContentType("text/html; charset=UTF-8");
return freeMarkerViewResolver;
}
#Bean
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
#Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
#Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("/messages/locales");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
My securityConfig:
#Configuration
#EnableWebSecurity(debug = true)
#EnableGlobalMethodSecurity(prePostEnabled = true)
#ComponentScan(value = "my.shop.common.fliPusto.services")
public class securityConfig extends WebSecurityConfigurerAdapter {
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(4);
}
#Bean
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceEncoding(true);
encodingFilter.setForceRequestEncoding(true);
encodingFilter.setForceResponseEncoding(true);
return encodingFilter;
}
#Autowired
void setAuthManagerBuilder(AuthenticationManagerBuilder authenticationManagerBuilder, PasswordEncoder passwordEncoder, UserDetailsService userDetailsService) {
try {
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/registration", "/test/*", "/book", "/tag/**", "/user/profile/{profile}", "/images/**", "/scripts/**", "/styles/**").permitAll()
.antMatchers("/admin/**").hasAuthority("MODERATOR")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/")
.permitAll()
.and()
.requiresChannel()
.anyRequest()
.requiresSecure();
http.addFilterBefore(characterEncodingFilter(), CsrfFilter.
}
}
I'm solved this by adding messagesource to another Configuration class and adding this class to the dispatherServlet as the ServletConfigClass
Another config:
#Configuration
public class OtherConfig {
#Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new
ResourceBundleMessageSource();
messageSource.setBasename("/messages/locales");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
Servlet class:
public class servlet extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[] {mvcConfig.class, securityConfig.class};
}
protected Class<?>[] getServletConfigClasses() {
return new Class[] {OtherConfig.class}; <-------------There
}
protected String[] getServletMappings() {
return new String[] {"/"};
}
#Override
protected Filter[] getServletFilters() {
return new Filter[]{new charsetFilter()};
}
#Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
registration.setMultipartConfig(new MultipartConfigElement(""));
}
}

spring oauth2, unable to retrieve user info

couldn't find a doc which illustrates how to use access_token to get user info.
How can I make a such endpoint?
I see when I access the /user endpoint OAuth2AuthenticationProcessingFilter is not included.
I think I messed up something below
#Configuration
#EnableWebSecurity
#Order(2)
// after ResourceServerConfigurerAdapter
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
// https://stackoverflow.com/questions/26387003/how-to-make-spring-boot-never-issue-session-cookie
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/", "index", "/login**", "/webjars/**")
.permitAll()
.and().exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(oAuth2FailedHandler)
.and().csrf().disable().authorizeRequests()
.and().addFilterBefore(new CORSFilter(), BasicAuthenticationFilter.class); }
}
I also have..
#Order(3)
#Configuration
#EnableResourceServer
#Slf4j
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(final ResourceServerSecurityConfigurer config) {
config.tokenServices(tokenServices());
}
#Override
public void configure(HttpSecurity http) throws Exception {
// super.configure(http);
log.info("hello OAuth2ResourceServerConfig:configure");
http
.authorizeRequests().anyRequest().authenticated();
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
// JDBC token store configuration
#Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("spring.datasource.url"));
dataSource.setUsername(env.getProperty("spring.datasource.username"));
dataSource.setPassword(env.getProperty("spring.datasource.password"));
return dataSource;
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource());
}
}
#Configuration
//#PropertySource({ "classpath:persistence.properties" }) #EnableAuthorizationServer
#Slf4j
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
// ....
}
Add a REST controller with something like this:
#RequestMapping("/user")
public #ResponseBody Principal user(Principal user) {
return user;
}
Then you can call it, using your access token in the Authorization header.

Spring Boot with different security contexts

I have two DispatcherServlets and I want to have different contexts for them. First servlet should be secured with spring security and second servlet should not use security at all.
I register servlets as follows:
#SpringBootApplication(exclude = {DispatcherServletAutoConfiguration.class})
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public ServletRegistrationBean FirstServletRegistration() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(FirstWebConfig.class, SecurityConfig.class);
dispatcherServlet.setApplicationContext(applicationContext);
ServletRegistrationBean registrationBean = new ServletRegistrationBean(
dispatcherServlet, "/api/*"
);
registrationBean.setName("firstServlet");
return registrationBean;
}
#Bean
public ServletRegistrationBean SecondServletRegistration() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(SecondWebConfig.class);
dispatcherServlet.setApplicationContext(applicationContext);
ServletRegistrationBean registrationBean = new ServletRegistrationBean(
dispatcherServlet, "/*"
);
registrationBean.setName("secondServlet");
return registrationBean;
}
}
For each of the servlets, I set the context:
#Configuration
#EnableWebMvc
#ComponentScan("com.example.app.controllers.first")
public class FirstWebConfig extends WebMvcConfigurerAdapter {
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
#Configuration
#EnableWebMvc
#ComponentScan("com.example.app.controllers.second")
public class SecondWebConfig extends WebMvcConfigurerAdapter {
}
And I want to use SecurityConfig only for "firstServlet":
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final BCryptPasswordEncoder passwordEncoder;
private final DataSource dataSource;
#Autowired
public SecurityConfig(BCryptPasswordEncoder passwordEncoder, DataSource dataSource) {
this.passwordEncoder = passwordEncoder;
this.dataSource = dataSource;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.usersByUsernameQuery(USERS_BY_USERNAME_QUERY)
.authoritiesByUsernameQuery(AUTHORITIES_BY_USERNAME_QUERY)
.dataSource(dataSource)
.passwordEncoder(passwordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated().and()
.formLogin()
.loginPage("/api/login")
.usernameParameter("username")
.passwordParameter("password")
.and()
.httpBasic().and()
.csrf().disable();
}
}
So how can I exclude use of security for "secondServlet"?

Resources