This is an automated email from the ASF dual-hosted git repository. avikg pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/fineract-cn-anubis.git
The following commit(s) were added to refs/heads/develop by this push: new 8597db5 inter-feign-client-keycloak-token-filter new 5ec70fb Merge pull request #18 from fynmanoj/keycloak-develop 8597db5 is described below commit 8597db5b787f59cd6346ba9b0aa6eb0c2c95d685 Author: fynmanoj <ma...@fynarfin.io> AuthorDate: Fri Aug 20 17:48:24 2021 +0530 inter-feign-client-keycloak-token-filter --- .../FinKeycloakSecurityConfigurerAdapter.java | 194 ++++++++++++--------- .../AccountLevelAccessDeniedException.java | 14 ++ .../security/AccountLevelAccessVerifierCustom.java | 2 +- 3 files changed, 126 insertions(+), 84 deletions(-) diff --git a/library/src/main/java/org/apache/fineract/cn/anubis/config/FinKeycloakSecurityConfigurerAdapter.java b/library/src/main/java/org/apache/fineract/cn/anubis/config/FinKeycloakSecurityConfigurerAdapter.java index 7860409..20a67e4 100644 --- a/library/src/main/java/org/apache/fineract/cn/anubis/config/FinKeycloakSecurityConfigurerAdapter.java +++ b/library/src/main/java/org/apache/fineract/cn/anubis/config/FinKeycloakSecurityConfigurerAdapter.java @@ -20,6 +20,7 @@ package org.apache.fineract.cn.anubis.config; import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.fineract.cn.anubis.filter.IsisAuthenticatedProcessingFilter; +import org.apache.fineract.cn.anubis.filter.UserContextFilter; import org.apache.fineract.cn.anubis.security.FinKeycloakAuthenticationProvider; import org.apache.fineract.cn.anubis.security.UrlPermissionChecker; import org.apache.fineract.cn.lang.ApplicationName; @@ -54,9 +55,12 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy; import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; +import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; +import javax.annotation.PostConstruct; import javax.servlet.Filter; import java.util.ArrayList; import java.util.List; @@ -70,90 +74,114 @@ import java.util.Set; @ComponentScan(basePackageClasses = KeycloakSecurityComponents.class) @ConditionalOnProperty({"authentication.service.keycloak"}) public class FinKeycloakSecurityConfigurerAdapter extends KeycloakWebSecurityConfigurerAdapter { - final private Logger logger; - final private ApplicationName applicationName; - - public FinKeycloakSecurityConfigurerAdapter(final @Qualifier(AnubisConstants.LOGGER_NAME) Logger logger, - final ApplicationName applicationName) { - this.logger = logger; - this.applicationName = applicationName; - } - - static class CustomKeycloakAccessToken extends AccessToken { - @JsonProperty("roles") - protected Set<String> roles; - - public Set<String> getRoles() { - return roles; - } - - public void setRoles(Set<String> roles) { - this.roles = roles; - } - } - - @Override - protected KeycloakAuthenticationProvider keycloakAuthenticationProvider() { - return new KeycloakAuthenticationProvider() { - - @Override - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) authentication; - List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); - - for (String role : ((CustomKeycloakAccessToken)((KeycloakPrincipal<KeycloakSecurityContext>)token.getPrincipal()).getKeycloakSecurityContext().getToken()).getRoles()) { - grantedAuthorities.add(new KeycloakRole(role)); + final private Logger logger; + final private ApplicationName applicationName; + + public FinKeycloakSecurityConfigurerAdapter(final @Qualifier(AnubisConstants.LOGGER_NAME) Logger logger, + final ApplicationName applicationName) { + this.logger = logger; + this.applicationName = applicationName; + } + + @Override + protected KeycloakAuthenticationProvider keycloakAuthenticationProvider() { + return new KeycloakAuthenticationProvider() { + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) authentication; + List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); + + for (String role : ((CustomKeycloakAccessToken) ((KeycloakPrincipal<KeycloakSecurityContext>) token.getPrincipal()).getKeycloakSecurityContext().getToken()).getRoles()) { + grantedAuthorities.add(new KeycloakRole(role)); + } + + return new KeycloakAuthenticationToken(token.getAccount(), token.isInteractive(), new SimpleAuthorityMapper().mapAuthorities(grantedAuthorities)); + } + + }; + } + + @PostConstruct + public void configureSecurityContext() { + SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); + } + + @Bean + public FilterRegistrationBean securityFilterChain(@Qualifier(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) final Filter securityFilter) { + final FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter); + registration.setOrder(Integer.MIN_VALUE + 1); //Just after the tenant filter. + registration.setName(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME); + return registration; + } + + @Bean + public FilterRegistrationBean userContextFilter() { + final FilterRegistrationBean registration = new FilterRegistrationBean(new UserContextFilter()); + registration.setOrder(Integer.MIN_VALUE + 2); + registration.addUrlPatterns("*"); + + return registration; } - return new KeycloakAuthenticationToken(token.getAccount(), token.isInteractive(), new SimpleAuthorityMapper().mapAuthorities(grantedAuthorities)); - } - - }; - } - - @Autowired - public void configureGlobal( - final AuthenticationManagerBuilder auth, - @SuppressWarnings("SpringJavaAutowiringInspection") final FinKeycloakAuthenticationProvider provider) - throws Exception { - auth.authenticationProvider(provider); - } - - @Bean - @Override - protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { - return new NullAuthenticatedSessionStrategy(); - } - @Bean - public KeycloakSpringBootConfigResolver KeycloakConfigResolver() { - return new KeycloakSpringBootConfigResolver(); - } - - @Bean - public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean( - KeycloakAuthenticationProcessingFilter filter) { - FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter); - registrationBean.setEnabled(false); - return registrationBean; - } - - @Bean - public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(KeycloakPreAuthActionsFilter filter) { - FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter); - registrationBean.setEnabled(false); - return registrationBean; - } - - private AccessDecisionManager defaultAccessDecisionManager() { - final List<AccessDecisionVoter<?>> voters = new ArrayList<>(); - voters.add(new UrlPermissionChecker(logger, applicationName));return new UnanimousBased(voters); - } - - protected void configure(HttpSecurity http) throws Exception { - Filter filter = new IsisAuthenticatedProcessingFilter(super.authenticationManager()); - ((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)((UrlAuthorizationConfigurer.StandardInterceptUrlRegistry)((UrlAuthorizationConfigurer.AuthorizedUrl)((UrlAuthorizationConfigurer)((HttpSecurity)((HttpSecurity)http.httpBasic().disable()).csrf().disable()).apply(new UrlAuthorizationConfigurer(this.getApplicationContext()))).getRegistry().anyRequest()).hasAuthority("maats_feather").accessDecisionManager(this.defaultAccessDecisionManager())).and()).formLogin().disable()).logout( [...] - response.setStatus(404); - }); - } + @Autowired + public void configureGlobal( + final AuthenticationManagerBuilder auth, + @SuppressWarnings("SpringJavaAutowiringInspection") final FinKeycloakAuthenticationProvider provider) + throws Exception { + auth.authenticationProvider(provider); + } + + @Bean + @Override + protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { + return new NullAuthenticatedSessionStrategy(); + } + + @Bean + public KeycloakSpringBootConfigResolver KeycloakConfigResolver() { + return new KeycloakSpringBootConfigResolver(); + } + + @Bean + public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean( + KeycloakAuthenticationProcessingFilter filter) { + FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter); + registrationBean.setEnabled(false); + return registrationBean; + } + + @Bean + public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(KeycloakPreAuthActionsFilter filter) { + FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter); + registrationBean.setEnabled(false); + return registrationBean; + } + + private AccessDecisionManager defaultAccessDecisionManager() { + final List<AccessDecisionVoter<?>> voters = new ArrayList<>(); + voters.add(new UrlPermissionChecker(logger, applicationName)); + return new UnanimousBased(voters); + } + + protected void configure(HttpSecurity http) throws Exception { + Filter filter = new IsisAuthenticatedProcessingFilter(super.authenticationManager()); + ((HttpSecurity) ((HttpSecurity) ((HttpSecurity) ((HttpSecurity) ((UrlAuthorizationConfigurer.StandardInterceptUrlRegistry) ((UrlAuthorizationConfigurer.AuthorizedUrl) ((UrlAuthorizationConfigurer) ((HttpSecurity) ((HttpSecurity) http.httpBasic().disable()).csrf().disable()).apply(new UrlAuthorizationConfigurer(this.getApplicationContext()))).getRegistry().anyRequest()).hasAuthority("maats_feather").accessDecisionManager(this.defaultAccessDecisionManager())).and()).formLogin().dis [...] + response.setStatus(404); + }); + } + + static class CustomKeycloakAccessToken extends AccessToken { + @JsonProperty("roles") + protected Set<String> roles; + + public Set<String> getRoles() { + return roles; + } + + public void setRoles(Set<String> roles) { + this.roles = roles; + } + } } \ No newline at end of file diff --git a/library/src/main/java/org/apache/fineract/cn/anubis/security/AccountLevelAccessDeniedException.java b/library/src/main/java/org/apache/fineract/cn/anubis/security/AccountLevelAccessDeniedException.java new file mode 100644 index 0000000..d645fdd --- /dev/null +++ b/library/src/main/java/org/apache/fineract/cn/anubis/security/AccountLevelAccessDeniedException.java @@ -0,0 +1,14 @@ +package org.apache.fineract.cn.anubis.security; + +import org.springframework.security.core.AuthenticationException; + +/** + * @author manoj + */ +public class AccountLevelAccessDeniedException extends AuthenticationException { + private AccountLevelAccessDeniedException(final String message) { super(message); } + + public static AccountLevelAccessDeniedException internalError(final String message) { + return new AccountLevelAccessDeniedException(message); + } +} diff --git a/library/src/main/java/org/apache/fineract/cn/anubis/security/AccountLevelAccessVerifierCustom.java b/library/src/main/java/org/apache/fineract/cn/anubis/security/AccountLevelAccessVerifierCustom.java index 5e66118..602f00a 100644 --- a/library/src/main/java/org/apache/fineract/cn/anubis/security/AccountLevelAccessVerifierCustom.java +++ b/library/src/main/java/org/apache/fineract/cn/anubis/security/AccountLevelAccessVerifierCustom.java @@ -49,7 +49,7 @@ public class AccountLevelAccessVerifierCustom { .collect(Collectors.toSet()); if(accountOperation.size() == 0 || !(accountOperation.contains(OWNER) || accountOperation.contains(operation))) { - throw AmitAuthenticationException.internalError("Access Denied, " + operation + " on " + accountNo); + throw AccountLevelAccessDeniedException.internalError("Access Denied, " + operation + " on " + accountNo); } } }