For Oauth2.0, the access token should be passed either in header or in request parameter. But My requirement is to somehow extract this token from request body to support existing public apis which are passing access token as a JSON field in request body.
Using ContentCachingRequestWrapper, I am able to extract the access token field from request JSON in a custom filter. This custom filter is configured to be invoked before OAuth2AuthenticationProcessingFilter. But I am not able to set it either in the request header or add it to request parameter for the OAuth2AuthenticationProcessingFilter to be able to extract this token and authenticate.
I referred to this link Spring Security: deserialize request body twice (oauth2 processing) which had a similar requirement. This talks about overriding HttpServletRequestWrapper.
With latest versions of Spring and Spring Boot, is there any other cleaner way of doing this rather than creating a HttpServletRequestWrapper?
Or is there any way of injecting my own implementation for BearerTokenExtractor (used by OAuth2AuthenticationProcessingFilter) which can also try to get the token from request attributes?
@Component
public class CustomOAuthTokenFilter extends GenericFilterBean {
@Autowired
private ObjectMapper objectMapper;
@Override
public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
ContentCachingRequestWrapper reqWrapper = new ContentCachingRequestWrapper(httpRequest);
String requestBody = IOUtils.toString(reqWrapper.getInputStream(), java.nio.charset.StandardCharsets.UTF_8);
JsonNode requestJson = objectMapper.readTree(requestBody);
Iterator<JsonNode> jsonIter = requestJson.elements();
while (jsonIter.hasNext()){
JsonNode parent = jsonIter != null ? jsonIter.next() : null;
JsonNode hdr = parent != null ? parent.get("hdr") : null;
JsonNode accessTokenNode = hdr != null ? hdr.get("accessToken") : null;
String accessToken = accessTokenNode != null ? accessTokenNode.asText() : null;
}
chain.doFilter(reqWrapper, response);
}
}
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private CustomOAuthTokenFilter customOAuthTokenFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/auth/token","/oauth/token", "/oauth/authorize**").permitAll().anyRequest()
.authenticated()
.and().addFilterBefore(customOAuthTokenFilter, AbstractPreAuthenticatedProcessingFilter.class);
}
}
OAuth2AuthenticationProcessingFilter
in a bean and thenOAuth2AuthenticationProcessingFilter#setTokenExtractor
and implement your ownTokenExtractor