I have a security jar that I am implementing in my project. I am extending the BasicSecurityConfig which extends WebSecurityConfigurerAdapter and has all the filters. I was told that all I need is to extend the BasicSecurityConfig and call super().configure which will call the parent's configure method. However, I am getting this error,
Field authenticationManager in com.custom.security.CustomSecurityFilter required a bean of type 'org.springframework.security.authentication.AuthenticationManager' that could not be found.
The parent class already has an AuthenticationManager bean, I shouldn't need to define it in the child class too.
My Security Class
public class SecurityConfiguration extends BasicSecurityConfig {
private static final String PAYMONEYROLE = "(hasRole('EE'))";
#Override
protected void configure(HttpSecurity http) throws Exception {
// must call super first
super.configure(http);
http.authorizeRequests()
.antMatchers(HttpMethod.POST, "/v1/cart/validate").authenticated()
.antMatchers(HttpMethod.POST, "/v1/cart/validate").access(PAYMONEYROLE)
.and().cors().and().csrf().disable();
}
#Bean
public FilterRegistrationBean invalidResourceFilterRegistration(InvalidResourceFilter invalidResourceFilter) {
FilterRegistrationBean registration = new FilterRegistrationBean(invalidResourceFilter);
registration.setEnabled(false);
invalidResourceFilter.setDisabled(true);
return registration;
}
#Bean
public FilterRegistrationBean customSecurityFilterRegistration(CustomSecurityFilter customSecurityFilter) {
FilterRegistrationBean registration = new FilterRegistrationBean(customSecurityFilter);
registration.setEnabled(false);
return registration;
}
}
Custom Security Jar
public class BasicSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private ApplicationContext applicationContext;
#Autowired
private InvalidResourceFilter invalidResourceFilter;
public BasicSecurityConfig() {
}
protected void configure(HttpSecurity http) throws Exception {
((HttpSecurity)((HttpSecurity)http.addFilterBefore(this.customSecurityFilter(), AbstractPreAuthenticatedProcessingFilter.class).addFilterAfter(this.invalidResourceFilter, FilterSecurityInterceptor.class).sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()).exceptionHandling().authenticationEntryPoint(this.authenticationEntryPoint()).accessDeniedHandler(this.customDeniedHandler()).and()).authorizeRequests().accessDecisionManager(this.accessDecisionManager());
}
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(new String[]{"/docs**/**", "/swagger-ui.html**/**", "/webjars**/**", "/swagger-resources**/**", "/api-docs**/**", "/v2/api-docs**", "/version.json**"});
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(this.customAuthenticationProvider());
}
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler() {
return new CustomWebSecurityExpressionHandler();
}
#Bean
public CustomSecurityFilter customSecurityFilter() {
return new CustomSecurityFilter();
}
#Bean
public AuthenticationProvider customAuthenticationProvider() {
return new CustomAuthenticationProvider();
}
#Bean
public AuthenticationSuccessHandler customSuccessHandler() {
return new CustomSuccessHandler();
}
#Bean
public AccessDeniedHandler customDeniedHandler() {
return new CustomAccessDeniedHandler();
}
#Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
return new CustomAuthenticationEntryPoint();
}
#Bean
public CustomSystemUserAuthVoter customSystemUserAuthVoter() {
return new CustomSystemUserAuthVoter();
}
#Bean
public WebExpressionVoter webExpressionVoter() {
WebExpressionVoter wev = new WebExpressionVoter();
wev.setExpressionHandler(this.defaultWebSecurityExpressionHandler());
return wev;
}
#Bean
public AccessDecisionManager accessDecisionManager() {
return new ExplicitDecisionManager(Arrays.asList(this.customSystemUserAuthVoter(), this.webExpressionVoter()));
}
}
As per your error, CustomSecurityFilter is supposed to have authenticationManager injected. But it is created without authenticationManager as below.
#Bean
public CustomSecurityFilter customSecurityFilter() {
return new CustomSecurityFilter();
}
If you can modify BasicSecurityConfig, then update the method as follows:
#Bean
public CustomSecurityFilter customSecurityFilter() {
//If it has a constructor which accept AuthenticationManager
return new CustomSecurityFilter(authenticationManagerBean());
//If it has a setter for AuthenticationManager instead
CustomSecurityFilter filter = new CustomSecurityFilter();
filter.setAuthenticationManager(authenticationManagerBean())
return filter;
}
If you cannot modify BasicSecurityConfig, then create it in SecurityConfiguration with Primary
#Bean
#Primary
public CustomSecurityFilter customSecurityFilter() {
//If it has a constructor which accept AuthenticationManager
return new CustomSecurityFilter(authenticationManagerBean());
//If it has a setter for AuthenticationManager instead
CustomSecurityFilter filter = new CustomSecurityFilter();
filter.setAuthenticationManager(authenticationManagerBean())
return filter;
}
Related
I am trying to have a custom authentication provider where I would like to have a keycloak as an authenticator.
Have created just a simple class for authentication provider but its not being called.
#Component
public class CustomKeycloakAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication auth)
throws AuthenticationException {
String username = auth.getName();
String password = auth.getCredentials()
.toString();
if ("externaluser".equals(username) && "pass".equals(password)) {
return new UsernamePasswordAuthenticationToken
(username, password, Collections.emptyList());
} else {
throw new
BadCredentialsException("External system authentication failed");
}
}
#Override
public boolean supports(Class<?> auth) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(auth));
}
}
Here is my WebConfig class:
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
//#EnableMyHttpSession
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private ClientDetailsService clientDetailsService;
private AccessDecisionManager accessDecisionManager;
#Autowired
private CustomKeycloakAuthenticationProvider keycloakAuthenticationProvider;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().accessDecisionManager(accessDecisionManager)
// .antMatchers("/oauth/token", "/*.html", "/js/**", "/images/**",
// "/styles/**").permitAll().
.antMatchers("/service/*").fullyAuthenticated()
// .antMatchers("/reports/*").fullyAuthenticated()
.anyRequest().permitAll().and().httpBasic().and().csrf().disable();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(keycloakAuthenticationProvider);
}
#Override
#Bean(name = "authenticationManagerBean")
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#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;
}
#Bean
public AffirmativeBased accessDecisionManager() {
List<AccessDecisionVoter<?>> accessDecisionVoters = new ArrayList<>();
accessDecisionVoters.add(new ScopeVoter());
accessDecisionVoters.add(new RoleVoter());
accessDecisionVoters.add(new AuthenticatedVoter());
AffirmativeBased accessDecisionManager = new AffirmativeBased(accessDecisionVoters);
return accessDecisionManager;
}
I also have a Authorization Server:
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private static final Logger log = LoggerFactory.getLogger(AuthorizationServerConfiguration.class);
//private static String REALM="MY_OAUTH_REALM";
#Autowired
private DataSource dateSource;
#Autowired
private UserApprovalHandler userApprovalHandler;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Autowired
private CustomClientBuilder customClientBuilder;
#Autowired
private TokenStore tokenStore;
#Autowired
public UserService userService;
#Autowired
private CustomClientService customClientService;
#Autowired
private AccessRightsService accessRightService;
private MyTokenServices tokenServices = null;
#Bean
#Primary
public MyTokenServices tokenServices() {
if(tokenServices != null) return tokenServices;
tokenServices = new MyTokenServices();
tokenServices.setTokenStore(tokenStore);
tokenServices.setClientDetailsService(customClientService);
tokenServices.setAuthenticationManager(authenticationManager);
tokenServices.userService = userService;
tokenServices.accessRightService = accessRightService;
return tokenServices;
}
#Bean
#Primary
public TokenStore tokenStore( #Value("${oauth2Token.store.type}") String tokenStoreType) {
TokenStore tokenStore = null;
log.info("Token store is type " + tokenStoreType);
if(tokenStoreType.toLowerCase().equals("jdbc")){
tokenStore = new JdbcTokenStore(dateSource);
}else {
tokenStore = new InMemoryTokenStore();
}
log.info("Token store is " + tokenStore);
return tokenStore;
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.setBuilder(customClientBuilder);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore)
.tokenServices(tokenServices())
.userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager).addInterceptor(new HandlerInterceptorAdapter() {
#Override
public boolean preHandle(HttpServletRequest hsr, HttpServletResponse rs, Object o) throws Exception {
rs.setHeader("Access-Control-Allow-Origin", "*");
rs.setHeader("Access-Control-Allow-Methods", "*");
rs.setHeader("Access-Control-Max-Age", "3600");
rs.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
log.info(hsr.getMethod());
if(hsr.getMethod().equals("OPTIONS")){
rs.setStatus(200); // hard fix for options
}
return true;
}
});
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients();
}
When I try to do a login in the providers there are only 2 of them:
I have tried to put #Autowired to protected void configure(AuthenticationManagerBuilder auth) { but it didn't helped
Don't know if there is something in configuration that I am missing so it doesn't add the 3rd authentication provider.
With Spring Security keyclaock can be configured with a class that derive of KeycloakWebSecurityConfigurerAdapter
#Configuration
#EnableWebSecurity
#KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
(https://www.keycloak.org/docs/latest/securing_apps/)
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-security-adapter</artifactId>
<version>20.0.2</version>
</dependency>
I think you don't need to create your own AuthenticationProvider keycloak give you an implementation KeycloakAuthenticationProvider
Update OK (but why ?) :
So I think you don't need to override that method
#Override
protected void configure(AuthenticationManagerBuilder auth)
Create another one like this
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
I'm using Spring 2.3.12.RELEASE with Hoxton.SR11 as cloud version. The dependency I'm using is spring-cloud-starter-oauth2.
I just configure all the oauth server but when I'm trying to do login I get a 401 response. I think that I'm missing something but I cannot fix it.
Here is the code:
AuthoritationServerConfig
#RefreshScope
#Configuration
#EnableAuthorizationServer
public class AuthoritationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private Environment env;
#Autowired
private BCryptPasswordEncoder passwordEncoder;
#Autowired
private AuthenticationManager authenticacionManager;
#Autowired
private InfoAdicionalToken infoAdicionalToken;
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient(env.getProperty("config.security.oauth.client.id"))
.secret(passwordEncoder.encode(env.getProperty("config.security.oauth.client.secret")))
.scopes("read", "write").authorizedGrantTypes("password", "refresh_token")
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(3600);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(infoAdicionalToken, accessTokenConverter()));
endpoints.authenticationManager(this.authenticacionManager)
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter()).tokenEnhancer(tokenEnhancerChain);
}
#Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();
tokenConverter.setSigningKey(env.getProperty("config.security.oauth.jwt.key"));
return tokenConverter;
}
}
SpringSecurityConfig
#Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsService usuarioService;
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
#Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(this.usuarioService).passwordEncoder(passwordEncoder());
}
#Override
#Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
}
ResourceServerConfig
#RefreshScope
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Value("${config.security.oauth.jwt.key}")
private String jwtKey;
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/api/security/oauth/**").permitAll();
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenStore(tokenStore());
}
#Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();
tokenConverter.setSigningKey(jwtKey);
return tokenConverter;
}
Zuul application properties
zuul.routes.security.service-id=servicio-oauth
zuul.routes.security.path=/api/security/**
zuul.routes.security.sensitive-headers=Cookie,Set-Cookie
This is a capture of the request:
Request headers:
Response headers:
Thank you in advance.
I'm having a problem configuring an Oauth2 Auth Server in Spring, I have my custom AuthenticationProvider and I'm defining my own AuthenticationManager, but everytime that I do a request for a token to "/oauth/token", I see that Spring keeps injecting and calling the default DaoAuthenticationProvider in the ProviderManager defined by Spring.
This are my configuration classes:
#Configuration
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private AuthenticationManager authenticationManager;
public AuthorizationServerConfiguration(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Bean
PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
#Bean
JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
return converter;
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private AuthenticationProvider authenticationProvider;
public WebSecurityConfig(AuthenticationProvider authenticationProvider) {
this.authenticationProvider = authenticationProvider;
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return new ProviderManager(authenticationProvider);
}
}
Thanks in advance
EDIT
#Service
public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
private ADCustomerService adCustomerService;
public CustomAuthenticationProvider(ADCustomerService adCustomerService) {
this.adCustomerService = adCustomerService;
}
#Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
}
#Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
return adCustomerService.retrieveUser(username, authentication);
}
}
You need to override configure(AuthenticationManagerBuilder auth) from WebSecurityConfigurerAdapter class
The final class should look something like this
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider authenticationProvider;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
}
Edit your WebSecurityConfig as follows:
FROM
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private AuthenticationProvider authenticationProvider;
public WebSecurityConfig(AuthenticationProvider authenticationProvider) {
this.authenticationProvider = authenticationProvider;
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return new ProviderManager(authenticationProvider);
}
}
TO
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private CustomAuthenticationProvider customAuthenticationProvider;
public WebSecurityConfig(AuthenticationProvider authenticationProvider) {
this.authenticationProvider = authenticationProvider;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return new ProviderManager(authenticationProvider);
}
}
I am trying to implement Oauth2 with spring boot with the configurations as below
Securty configuration:
#Configuration
#EnableWebSecurity(debug = true)
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private PasswordEncoder passwordEncoder;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
auth.userDetailsService(userDetailsService);
}
public AuthenticationProvider authenticationProvider(){
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
return daoAuthenticationProvider;
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(11);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().anonymous().disable().authorizeRequests()
.antMatchers("/oauth2/login","/logout").permitAll()
.anyRequest().authenticated()
.and().formLogin().loginPage("/oauth2/login").loginProcessingUrl("/login").permitAll();
}
}
Authorization configuration
#Configuration
#EnableAuthorizationServer
public class AuthServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private TokenStore tokenStore;
#Autowired
private ClientDetailsService clientDetailsService;
#Bean
public TokenStore tokenStore(DataSource dataSource){
return new JdbcTokenStore(dataSource);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
enhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer()));
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore)
.tokenEnhancer(enhancerChain)
.tokenGranter(new CompositeTokenGranter(getCustomizedTokenGranters()))
.tokenServices(tokenServices())
.approvalStoreDisabled();
}
#Bean
#Primary
public AuthorizationServerTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenEnhancer(tokenEnhancer());
tokenServices.setTokenStore(tokenStore);
tokenServices.setClientDetailsService(clientDetailsService);
return tokenServices;
}
#Bean
public TokenEnhancer tokenEnhancer(){
return (accessToken, authentication) -> {
if(!"client_credentials".equalsIgnoreCase(authentication.getOAuth2Request().getRequestParameters().get(OAuth2Utils.GRANT_TYPE)))
{
ExtendedUser principal = (ExtendedUser) authentication.getPrincipal();
Map<String, Object> additionalInfo = Maps.newHashMap();
additionalInfo.put("user_id", principal.getUserId());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
}
return accessToken;
};
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("permitAll()")
.tokenKeyAccess("permitAll()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
#Bean
public ClientDetailsService clientDetailsService(DataSource dataSource){
return new CachedClientDetailsService(dataSource);
}
private List<TokenGranter> getCustomizedTokenGranters() {
AuthorizationServerTokenServices tokenServices = tokenServices();
ClientDetailsService clientDetails = clientDetailsService;
OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(clientDetails);
RefreshTokenGranter refreshTokenGranter = new RefreshTokenGranter(tokenServices, clientDetails, requestFactory);
ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory);
ClientCredentialsTokenGranter clientCredentialsTokenGranter = new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory);
clientCredentialsTokenGranter.setAllowRefresh(true);//custom config, see AuthorizationServerEndpointsConfigurer.getDefaultTokenGranters
List<TokenGranter> tokenGranters = Lists.newArrayList();
tokenGranters.add(refreshTokenGranter);
tokenGranters.add(implicit);
tokenGranters.add(clientCredentialsTokenGranter);
if (authenticationManager != null) {
tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, clientDetails, requestFactory));
}
return tokenGranters;
}
}
Resource server configuration :
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/**").authenticated();
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("identity-service");
}
#Bean
public ResourceServerTokenServices resourceServerTokenServices(TokenStore tokenStore){
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenStore(tokenStore);
return tokenServices;
}
}
application.properties
security.oauth2.resource.filter-order = 3
the resource server is on the same authorization server (Same Application), and I am trying to implement the Implicit grant (Password grant working just fine)
when I am trying to login in to complete the implicit grant (oauth/authorize endpoint need authentication) I am getting /login 404 ?
spring boot: 1.5.10,
spring security Oauth2: 2.0.14
Finally, i managed to make it work
Security Configuration :
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/**").and().csrf().disable().authorizeRequests()
.antMatchers("/oauth2/login","/logout").permitAll()
.antMatchers("/oauth/authorize").authenticated()
.and().formLogin().loginPage("/oauth2/login").loginProcessingUrl("/login").permitAll();
}
Resources Server Configuration
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/api/**").and().anonymous().disable().authorizeRequests()
.anyRequest().authenticated();
}
I had to enable the anonymous in spring security and specify mapping URI matcher for both spring security and resource server
Resource server on /api/**
,Spring security on /**
and for taking care of the ordering (on version 1.5.10)
application.properties
security.oauth2.resource.filter-order = 3
I am trying to implement Method Security using #PreAuthorize.
Spring Version: 4.2.3.Release
Spring Security: 4.0.3.Release
I have implemented a CustomPermissionEvaluator. I have noticed that it seems to be working fine except for 1 service where the hasPmerission is not called.
I know this because I get the a logging message from hasPermission / or in the erroneous case do not get the log:
public boolean hasPermission(Authentication authentication, Object o, Object o1) {
logger.info("Call to hasPermission with "+o+" and "+o1);
...
}
My Spring configuration is as follows:
#Configuration
#ComponentScan
public class RootConfiguration {
}
MVC Config
#EnableWebMvc
#Configuration
#ComponentScan({"OntoRais.*"})
#PropertySource("classpath:application.properties")
#EnableGlobalMethodSecurity(prePostEnabled=true)
public class MvcConfiguration extends WebMvcConfigurerAdapter{
#Bean
public ViewResolver getViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigIn() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean(name="multipartResolver")
public CommonsMultipartResolver commonsMultipartResolver(){
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
commonsMultipartResolver.setDefaultEncoding("utf-8");
commonsMultipartResolver.setMaxUploadSize(50000000);
return commonsMultipartResolver;
}
}
Method Security Config:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
#ComponentScan
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
#Autowired
private CustomPermissionEvaluator permissionEvaluator;
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler handler
= new DefaultMethodSecurityExpressionHandler();
handler.setPermissionEvaluator(permissionEvaluator);
return handler;
}
public CustomPermissionEvaluator getPermissionEvaluator() {
return permissionEvaluator;
}
public void setPermissionEvaluator(CustomPermissionEvaluator permissionEvaluator) {
this.permissionEvaluator = permissionEvaluator;
}
}
Initializer:
#Configuration
#EnableSpringConfigured
public class MessageWebApplicationInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.addListener(org.springframework.web.context.request.RequestContextListener.class);
super.onStartup(servletContext);
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { MvcConfiguration.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
#Override
protected Filter[] getServletFilters() {
return new Filter[]{new HiddenHttpMethodFilter(),
new OpenEntityManagerInViewFilter(),
new DelegatingFilterProxy("springSecurityFilterChain")
};
}
}
Security Config:
#Configuration
#EnableWebSecurity
#ComponentScan
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
OntoRAISUserDetailsService ontoRAISUserDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.
formLogin().
and().
logout().
and().
authorizeRequests().
antMatchers("/login").permitAll().
anyRequest().authenticated().
and().csrf().disable();
}
#Autowired
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(ontoRAISUserDetailsService);
auth.authenticationProvider(authenticationProvider());
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(ontoRAISUserDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
public OntoRAISUserDetailsService getOntoRAISUserDetailsService() {
return ontoRAISUserDetailsService;
}
public void setOntoRAISUserDetailsService(OntoRAISUserDetailsService ontoRAISUserDetailsService) {
this.ontoRAISUserDetailsService = ontoRAISUserDetailsService;
}
The Service in question:
#Service
public class StakeholderService {
#Autowired
private OntopManager om;
private static final Logger logger = LoggerFactory.getLogger("OntoRais");
public OntopManager getOm() {
return om;
}
public void setOm(OntopManager om) {
this.om = om;
}
#PreAuthorize("hasPermission(#stakeholderType, 'Create_StakeholderType')")
public void createStakeholderType(StakeholderType stakeholderType) {
try {
logger.info("Create stakeholder type in service layer");
List<OBDADataSource> sources = om.getObdaModel().getSources();
OBDAMappingAxiom mapping = om.getObdaModel().getMapping(new URI("genertatedURI"), MappingList.StakheholderType());
HashMap<String, String> values = new HashMap<>();
values.put("stakeholderName", stakeholderType.getLabel());
String query = ClassSQLHelper.generateSQLCreateSatement(mapping.getSourceQuery(), values);
SQLHelper.executeSQL(query, sources.get(0));
} catch (URISyntaxException e) {
logger.error(e.getMessage());
}
}
And the controller from which i call the service layer:
#Api(description = "Operations related to Stakeholders")
#RestController
public class StakeholderController {
#Autowired
private OntopManager om;
#Autowired
StakeholderService stakeholderService;
#Autowired
ProjectService projectService;
private static final Logger logger = LoggerFactory.getLogger("OntoRais");
...
/**
* Add a new Stakeholder Type
*
* #param stakeholdertype The new Stakeholder to be added.
* #return
*/
#ApiOperation(value = "Add new stakeholder type",
notes = "",
response = ResponseResource.class,
responseContainer = "Object")
#JsonView(Views.Details.class)
#RequestMapping(value = "/api/stakeholder/types", method = RequestMethod.POST)
public ResponseEntity<List<StakeholderType>> addStakeholderType(#RequestBody StakeholderType stakeholdertype) {
logger.info("Add Stakeholder type in controller");
getStakeholderService().createStakeholderType(stakeholdertype);
return getStakeholderTypes();
}
When calling api/stakeholder/types" with method = POST
This is my debug output:
Add Stakeholder type in controller
Create stakeholder type in service layer
INSERT INTO prefix_http_www_ontorais_de_stakeholdertype(id,stakeholderName) VALUES(DEFAULT,'TESTEWRTERETE');
As you can see the log from hasPermission is not present -> not called.
I can see that the method is called from my other method sercurity annotations in other service objects.
A similar Service which correctly invokes hasPermission as expected just for comparison:
#Service
public class OrganisationService {
private static final Logger logger = LoggerFactory.getLogger("OntoRais");
#Autowired
private OntopManager om;
#Autowired
private ProjectService projectService;
...
#PreAuthorize("hasAuthority('Add_Organisation')")
public void addOrganisation(Organisation organisation) {
List<OBDADataSource> sources = om.getObdaModel().getSources();
OBDAMappingAxiom mapping = null;
try {
mapping = om.getObdaModel().getMapping(new URI("genertatedURI"), MappingList.OrganisationMapping());
} catch (URISyntaxException e) {
e.printStackTrace();
}
HashMap<String, String> valueMap = new HashMap<>();
valueMap.put("organisationName", organisation.getName());
valueMap.put("organisationDescription", organisation.getDescription());
String query = ClassSQLHelper.generateSQLCreateSatement(mapping.getSourceQuery(), valueMap);
SQLHelper.executeSQL(query, sources.get(0));
}
Any hints on what I am doing wrong/missing/am blind for are very welcome thanks.
Benedict
Ok I found the problem, and a solution.
The Problem was that my CustomPermissionEvaluator depended on a method within the StakeholderService. Even though that method was not secured this resulted in the Spring not being able to proxy the object, therefore preventing any security checks.
Even though it is a bad idea to use a service layer object in the PermissionEvaluator, perhaps someone could elaborate on the exact implications, as i am definately not an expert in spring sercurity