FINERACT-1012: Upgrading OAuth support to Spring Security 5.6

This commit is contained in:
Petri Tuomola
2021-12-28 03:08:27 +01:00
committed by Aleksandar Vidakovic
parent b6a9a2791d
commit c74bfed1fe
24 changed files with 719 additions and 530 deletions
@@ -1,44 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.core.boot;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.web.servlet.DispatcherServlet;
/**
* This Configuration replaces what formerly was in web.xml. Beans are loaded only when "oauth" Profile is enabled.
*
* @see <a href=
* "http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-convert-an-existing-application-to-spring-boot">#howto-convert-an-existing-application-to-spring-boot</a>
*/
@Configuration
@Profile("oauth")
public class WebXmlOauthConfiguration {
@Bean
public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
ServletRegistrationBean<DispatcherServlet> registrationBean = new ServletRegistrationBean<DispatcherServlet>(dispatcherServlet);
registrationBean.addUrlMappings("/api/oauth/token");
return registrationBean;
}
}
@@ -0,0 +1,145 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.core.config;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.fineract.infrastructure.core.exceptionmapper.OAuth2ExceptionEntryPoint;
import org.apache.fineract.infrastructure.security.data.FineractJwtAuthenticationToken;
import org.apache.fineract.infrastructure.security.filter.TenantAwareTenantIdentifierFilter;
import org.apache.fineract.infrastructure.security.filter.TwoFactorAuthenticationFilter;
import org.apache.fineract.infrastructure.security.service.TenantAwareJpaPlatformUserDetailsService;
import org.apache.fineract.infrastructure.security.vote.SelfServiceUserAccessVote;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.HttpMethod;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.access.vote.UnanimousBased;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.web.access.expression.WebExpressionVoter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
@Configuration
@Profile("oauth")
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private TwoFactorAuthenticationFilter twoFactorAuthenticationFilter;
@Autowired
private TenantAwareTenantIdentifierFilter tenantAwareTenantIdentifierFilter;
@Autowired
private TenantAwareJpaPlatformUserDetailsService userDetailsService;
private static final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
@Override
protected void configure(HttpSecurity http) throws Exception {
http //
.csrf().disable() // NOSONAR only creating a service that is used by non-browser clients
.antMatcher("/api/**").authorizeRequests() //
.antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll() //
.antMatchers(HttpMethod.POST, "/api/*/echo").permitAll() //
.antMatchers(HttpMethod.POST, "/api/*/authentication").permitAll() //
.antMatchers(HttpMethod.POST, "/api/*/self/authentication").permitAll() //
.antMatchers(HttpMethod.POST, "/api/*/self/registration").permitAll() //
.antMatchers(HttpMethod.POST, "/api/*/self/registration/user").permitAll() //
.antMatchers(HttpMethod.POST, "/api/*/twofactor/validate").fullyAuthenticated() //
.antMatchers("/api/*/twofactor").fullyAuthenticated() //
.antMatchers("/api/**").access("isFullyAuthenticated() and hasAuthority('TWOFACTOR_AUTHENTICATED')") //
.accessDecisionManager(accessDecisionManager()).and() //
.exceptionHandling().authenticationEntryPoint(new OAuth2ExceptionEntryPoint()).and()
.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(authenticationConverter()))
.authenticationEntryPoint(new OAuth2ExceptionEntryPoint())) //
.sessionManagement() //
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) //
.and() //
.addFilterAfter(tenantAwareTenantIdentifierFilter, SecurityContextPersistenceFilter.class) //
.addFilterAfter(twoFactorAuthenticationFilter, BasicAuthenticationFilter.class) //
.requiresChannel(channel -> channel.antMatchers("/api/**").requiresSecure());
}
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
private Converter<Jwt, FineractJwtAuthenticationToken> authenticationConverter() {
return jwt -> {
try {
UserDetails user = userDetailsService.loadUserByUsername(jwt.getSubject());
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("");
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
return new FineractJwtAuthenticationToken(jwt, authorities, user);
} catch (UsernameNotFoundException ex) {
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN), ex);
}
};
}
@Bean
public AccessDecisionManager accessDecisionManager() {
List<AccessDecisionVoter<? extends Object>> decisionVoters = Arrays.asList(new RoleVoter(), new AuthenticatedVoter(),
new WebExpressionVoter(), new SelfServiceUserAccessVote());
return new UnanimousBased(decisionVoters);
}
@Bean
public FilterRegistrationBean<TenantAwareTenantIdentifierFilter> tenantAwareTenantIdentifierFilterRegistration() throws Exception {
FilterRegistrationBean<TenantAwareTenantIdentifierFilter> registration = new FilterRegistrationBean<TenantAwareTenantIdentifierFilter>(
tenantAwareTenantIdentifierFilter);
registration.setEnabled(false);
return registration;
}
@Bean
public FilterRegistrationBean<TwoFactorAuthenticationFilter> twoFactorAuthenticationFilterRegistration() {
FilterRegistrationBean<TwoFactorAuthenticationFilter> registration = new FilterRegistrationBean<TwoFactorAuthenticationFilter>(
twoFactorAuthenticationFilter);
registration.setEnabled(false);
return registration;
}
}
@@ -0,0 +1,46 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.core.exceptionmapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
public class OAuth2ExceptionEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
ApiGlobalErrorResponse errorResponse = ApiGlobalErrorResponse.unAuthenticated();
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
try {
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getOutputStream(), errorResponse);
} catch (Exception e) {
throw new ServletException(e);
}
}
}
@@ -19,7 +19,6 @@
package org.apache.fineract.infrastructure.security.api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
@@ -31,24 +30,23 @@ import java.util.Set;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.constants.TwoFactorConstants;
import org.apache.fineract.infrastructure.security.data.AuthenticatedOauthUserData;
import org.apache.fineract.infrastructure.security.data.FineractJwtAuthenticationToken;
import org.apache.fineract.infrastructure.security.service.SpringSecurityPlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.TwoFactorUtils;
import org.apache.fineract.useradministration.data.RoleData;
import org.apache.fineract.useradministration.domain.AppUser;
import org.apache.fineract.useradministration.domain.Role;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.Scope;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
/*
@@ -60,19 +58,15 @@ import org.springframework.stereotype.Component;
@Scope("singleton")
@Tag(name = "Fetch authenticated user details", description = "")
@SuppressWarnings("deprecation") // TODO FINERACT-1012
public class UserDetailsApiResource {
private final ResourceServerTokenServices tokenServices;
private final ToApiJsonSerializer<AuthenticatedOauthUserData> apiJsonSerializerService;
private final SpringSecurityPlatformSecurityContext springSecurityPlatformSecurityContext;
private final TwoFactorUtils twoFactorUtils;
@Autowired
public UserDetailsApiResource(@Qualifier("tokenServices") final ResourceServerTokenServices tokenServices,
final ToApiJsonSerializer<AuthenticatedOauthUserData> apiJsonSerializerService,
public UserDetailsApiResource(final ToApiJsonSerializer<AuthenticatedOauthUserData> apiJsonSerializerService,
final SpringSecurityPlatformSecurityContext springSecurityPlatformSecurityContext, final TwoFactorUtils twoFactorUtils) {
this.tokenServices = tokenServices;
this.apiJsonSerializerService = apiJsonSerializerService;
this.springSecurityPlatformSecurityContext = springSecurityPlatformSecurityContext;
this.twoFactorUtils = twoFactorUtils;
@@ -83,48 +77,57 @@ public class UserDetailsApiResource {
@Operation(summary = "Fetch authenticated user details\n", description = "checks the Authentication and returns the set roles and permissions allowed.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = UserDetailsApiResourceSwagger.GetUserDetailsResponse.class))) })
public String fetchAuthenticatedUserData(
@QueryParam("access_token") @Parameter(description = "access_token") final String accessToken) {
public String fetchAuthenticatedUserData() {
final Authentication authentication = this.tokenServices.loadAuthentication(accessToken);
if (authentication.isAuthenticated()) {
final AppUser principal = (AppUser) authentication.getPrincipal();
final Collection<String> permissions = new ArrayList<>();
AuthenticatedOauthUserData authenticatedUserData = new AuthenticatedOauthUserData(principal.getUsername(), permissions);
final Collection<GrantedAuthority> authorities = new ArrayList<>(authentication.getAuthorities());
for (final GrantedAuthority grantedAuthority : authorities) {
permissions.add(grantedAuthority.getAuthority());
}
final Collection<RoleData> roles = new ArrayList<>();
final Set<Role> userRoles = principal.getRoles();
for (final Role role : userRoles) {
roles.add(role.toData());
}
final Long officeId = principal.getOffice().getId();
final String officeName = principal.getOffice().getName();
final Long staffId = principal.getStaffId();
final String staffDisplayName = principal.getStaffDisplayName();
final EnumOptionData organisationalRole = principal.organisationalRoleData();
final boolean requireTwoFactorAuth = twoFactorUtils.isTwoFactorAuthEnabled()
&& !principal.hasSpecificPermissionTo(TwoFactorConstants.BYPASS_TWO_FACTOR_PERMISSION);
if (this.springSecurityPlatformSecurityContext.doesPasswordHasToBeRenewed(principal)) {
authenticatedUserData = new AuthenticatedOauthUserData(principal.getUsername(), principal.getId(), accessToken,
requireTwoFactorAuth);
} else {
authenticatedUserData = new AuthenticatedOauthUserData(principal.getUsername(), officeId, officeName, staffId,
staffDisplayName, organisationalRole, roles, permissions, principal.getId(), accessToken, requireTwoFactorAuth);
}
return this.apiJsonSerializerService.serialize(authenticatedUserData);
final SecurityContext context = SecurityContextHolder.getContext();
if (context == null) {
return null;
}
return null;
final FineractJwtAuthenticationToken authentication = (FineractJwtAuthenticationToken) context.getAuthentication();
if (authentication == null) {
return null;
}
final AppUser principal = (AppUser) authentication.getPrincipal();
if (principal == null) {
return null;
}
final Collection<String> permissions = new ArrayList<>();
AuthenticatedOauthUserData authenticatedUserData = new AuthenticatedOauthUserData(principal.getUsername(), permissions);
final Collection<GrantedAuthority> authorities = new ArrayList<>(authentication.getAuthorities());
for (final GrantedAuthority grantedAuthority : authorities) {
permissions.add(grantedAuthority.getAuthority());
}
final Collection<RoleData> roles = new ArrayList<>();
final Set<Role> userRoles = principal.getRoles();
for (final Role role : userRoles) {
roles.add(role.toData());
}
final Long officeId = principal.getOffice().getId();
final String officeName = principal.getOffice().getName();
final Long staffId = principal.getStaffId();
final String staffDisplayName = principal.getStaffDisplayName();
final EnumOptionData organisationalRole = principal.organisationalRoleData();
final boolean requireTwoFactorAuth = twoFactorUtils.isTwoFactorAuthEnabled()
&& !principal.hasSpecificPermissionTo(TwoFactorConstants.BYPASS_TWO_FACTOR_PERMISSION);
if (this.springSecurityPlatformSecurityContext.doesPasswordHasToBeRenewed(principal)) {
authenticatedUserData = new AuthenticatedOauthUserData(principal.getUsername(), principal.getId(),
authentication.getToken().getTokenValue(), requireTwoFactorAuth);
} else {
authenticatedUserData = new AuthenticatedOauthUserData(principal.getUsername(), officeId, officeName, staffId, staffDisplayName,
organisationalRole, roles, permissions, principal.getId(), authentication.getToken().getTokenValue(),
requireTwoFactorAuth);
}
return this.apiJsonSerializerService.serialize(authenticatedUserData);
}
}
@@ -0,0 +1,42 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.security.data;
import java.util.Collection;
import java.util.Objects;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
public class FineractJwtAuthenticationToken extends JwtAuthenticationToken {
private final UserDetails user;
public FineractJwtAuthenticationToken(Jwt jwt, Collection<GrantedAuthority> authorities, UserDetails user) {
super(jwt, authorities, user.getUsername());
this.user = Objects.requireNonNull(user, "user");
}
@Override
public UserDetails getPrincipal() {
return user;
}
}
@@ -20,12 +20,13 @@ package org.apache.fineract.infrastructure.security.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.fineract.useradministration.domain.AppUser;
import org.apache.fineract.infrastructure.security.data.FineractJwtAuthenticationToken;
import org.springframework.context.annotation.Profile;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
@@ -33,6 +34,7 @@ import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
/**
@@ -58,18 +60,21 @@ public class InsecureTwoFactorAuthenticationFilter extends TwoFactorAuthenticati
}
// Add two-factor authenticated authority if user is authenticated
if (authentication != null && authentication.isAuthenticated() && authentication.getPrincipal() instanceof AppUser) {
AppUser user = (AppUser) authentication.getPrincipal();
if (user == null) {
return;
}
if (authentication != null && authentication.isAuthenticated()) {
List<GrantedAuthority> updatedAuthorities = new ArrayList<>(authentication.getAuthorities());
updatedAuthorities.add(new SimpleGrantedAuthority("TWOFACTOR_AUTHENTICATED"));
UsernamePasswordAuthenticationToken updatedAuthentication = new UsernamePasswordAuthenticationToken(
authentication.getPrincipal(), authentication.getCredentials(), updatedAuthorities);
context.setAuthentication(updatedAuthentication);
if (authentication instanceof UsernamePasswordAuthenticationToken) {
UsernamePasswordAuthenticationToken updatedAuthentication = new UsernamePasswordAuthenticationToken(
authentication.getPrincipal(), authentication.getCredentials(), updatedAuthorities);
context.setAuthentication(updatedAuthentication);
} else if (authentication instanceof FineractJwtAuthenticationToken) {
FineractJwtAuthenticationToken fineractJwtAuthenticationToken = (FineractJwtAuthenticationToken) authentication;
FineractJwtAuthenticationToken updatedAuthentication = new FineractJwtAuthenticationToken(
fineractJwtAuthenticationToken.getToken(), (Collection<GrantedAuthority>) updatedAuthorities,
(UserDetails) authentication.getPrincipal());
context.setAuthentication(updatedAuthentication);
}
}
chain.doFilter(req, res);
@@ -54,7 +54,7 @@ import org.springframework.web.filter.GenericFilterBean;
*
* Used to support Oauth2 authentication and the service is loaded only when "oauth" profile is active.
*/
@Service(value = "tenantIdentifierProcessingFilter")
@Service
@Profile("oauth")
public class TenantAwareTenantIdentifierFilter extends GenericFilterBean {
@@ -20,6 +20,7 @@ package org.apache.fineract.infrastructure.security.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
@@ -28,6 +29,7 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.fineract.infrastructure.security.constants.TwoFactorConstants;
import org.apache.fineract.infrastructure.security.data.FineractJwtAuthenticationToken;
import org.apache.fineract.infrastructure.security.domain.TFAccessToken;
import org.apache.fineract.infrastructure.security.service.TwoFactorService;
import org.apache.fineract.useradministration.domain.AppUser;
@@ -39,7 +41,7 @@ import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.web.filter.GenericFilterBean;
@@ -106,25 +108,28 @@ public class TwoFactorAuthenticationFilter extends GenericFilterBean {
List<GrantedAuthority> updatedAuthorities = new ArrayList<>(authentication.getAuthorities());
updatedAuthorities.add(new SimpleGrantedAuthority("TWOFACTOR_AUTHENTICATED"));
final Authentication updatedAuthentication = createUpdatedAuthentication(authentication, updatedAuthorities);
context.setAuthentication(updatedAuthentication);
context.setAuthentication(createUpdatedAuthentication(authentication, updatedAuthorities));
}
chain.doFilter(req, res);
}
@SuppressWarnings("deprecation") // TODO FINERACT-1012
private Authentication createUpdatedAuthentication(final Authentication currentAuthentication,
final List<GrantedAuthority> updatedAuthorities) {
final List<GrantedAuthority> updatedAuthorities) throws ServletException {
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
currentAuthentication.getPrincipal(), currentAuthentication.getCredentials(), updatedAuthorities);
if (currentAuthentication instanceof OAuth2Authentication) {
final OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) currentAuthentication;
return new OAuth2Authentication(oAuth2Authentication.getOAuth2Request(), authentication);
if (currentAuthentication instanceof UsernamePasswordAuthenticationToken) {
UsernamePasswordAuthenticationToken updatedAuthentication = new UsernamePasswordAuthenticationToken(
currentAuthentication.getPrincipal(), currentAuthentication.getCredentials(), updatedAuthorities);
return updatedAuthentication;
} else if (currentAuthentication instanceof FineractJwtAuthenticationToken) {
FineractJwtAuthenticationToken fineractJwtAuthenticationToken = (FineractJwtAuthenticationToken) currentAuthentication;
FineractJwtAuthenticationToken updatedAuthentication = new FineractJwtAuthenticationToken(
fineractJwtAuthenticationToken.getToken(), (Collection<GrantedAuthority>) updatedAuthorities,
(UserDetails) currentAuthentication.getPrincipal());
return updatedAuthentication;
} else {
throw new ServletException("Unknown authentication type: " + currentAuthentication.getClass().getName());
}
return authentication;
}
}
@@ -19,7 +19,6 @@
package org.apache.fineract.portfolio.self.security.api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
@@ -28,7 +27,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.apache.fineract.infrastructure.security.api.UserDetailsApiResource;
import org.springframework.beans.factory.annotation.Autowired;
@@ -57,8 +55,7 @@ public class SelfUserDetailsApiResource {
+ "For more info visit this link - https://demo.fineract.dev/fineract-provider/api-docs/apiLive.htm#selfoauth")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = SelfUserDetailsApiResourceSwagger.GetSelfUserDetailsResponse.class))) })
public String fetchAuthenticatedUserData(
@QueryParam("access_token") @Parameter(description = "äccess_token") final String accessToken) {
return this.userDetailsApiResource.fetchAuthenticatedUserData(accessToken);
public String fetchAuthenticatedUserData() {
return this.userDetailsApiResource.fetchAuthenticatedUserData();
}
}