Skip to content

Instantly share code, notes, and snippets.

@hortega
Created November 29, 2016 19:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hortega/59c88d15b732ae9311b6de6fe358c76c to your computer and use it in GitHub Desktop.
Save hortega/59c88d15b732ae9311b6de6fe358c76c to your computer and use it in GitHub Desktop.
Files for Twilio guide about validating Twilio requests in Servlet project
package guide;
import com.twilio.security.RequestValidator;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TwilioRequestValidatorFilter implements Filter {
private static final String AUTH_TOKEN_ENV_NAME = "TWILIO_AUTH_TOKEN";
private RequestValidator requestValidator;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
requestValidator = new RequestValidator(System.getenv(AUTH_TOKEN_ENV_NAME));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
boolean requestIsValid = false;
if (request instanceof HttpServletRequest) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
// Concatenates the request URL with the query string
String pathAndQueryUrl = getPathAndQueryUrl(httpRequest);
// Extracts only the form parameters and converts the parameters Map type
Map<String, String> formParams = extractFormParams(httpRequest);
requestIsValid = requestValidator.validate(
pathAndQueryUrl,
formParams,
httpRequest.getHeader("X-Twilio-Signature"));
}
if(requestIsValid) {
chain.doFilter(request, response);
} else {
((HttpServletResponse)response).sendError(HttpServletResponse.SC_FORBIDDEN);
}
}
@Override
public void destroy() {
// Nothing to do
}
private Map<String, String> extractFormParams(HttpServletRequest request) {
String queryString = request.getQueryString();
Map<String, String[]> requestParams = request.getParameterMap();
List<String> queryStringKeys = getQueryStringKeys(queryString);
return requestParams.entrySet().stream()
.filter(e -> !queryStringKeys.contains(e.getKey()))
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()[0]));
}
private List<String> getQueryStringKeys(String queryString) {
if(queryString == null || queryString.length() == 0) {
return Collections.emptyList();
} else {
return Arrays.stream(queryString.split("&"))
.map(pair -> pair.split("=")[0])
.collect(Collectors.toList());
}
}
private String getPathAndQueryUrl(HttpServletRequest request) {
String queryString = request.getQueryString();
String requestUrl = request.getRequestURL().toString();
if(queryString != null && queryString != "") {
return requestUrl + "?" + queryString;
}
return requestUrl;
}
}
package guide;
import com.twilio.security.RequestValidator;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TwilioRequestValidatorFilter implements Filter {
private static final String AUTH_TOKEN_ENV_NAME = "TWILIO_AUTH_TOKEN";
private final String currentEnvironment = System.getenv("ENVIRONMENT");
private RequestValidator requestValidator;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
requestValidator = new RequestValidator(System.getenv(AUTH_TOKEN_ENV_NAME));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
boolean requestIsValid = false;
if (request instanceof HttpServletRequest) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
// Concatenates the request URL with the query string
String pathAndQueryUrl = getPathAndQueryUrl(httpRequest);
// Extracts only the form parameters and converts the parameters Map type
Map<String, String> formParams = extractFormParams(httpRequest);
requestIsValid = requestValidator.validate(
pathAndQueryUrl,
formParams,
httpRequest.getHeader("X-Twilio-Signature"));
}
if(requestIsValid && environmentIsTest()) {
chain.doFilter(request, response);
} else {
((HttpServletResponse)response).sendError(HttpServletResponse.SC_FORBIDDEN);
}
}
@Override
public void destroy() {
// Nothing to do
}
private boolean environmentIsTest() {
return "test".equals(currentEnvironment);
}
private Map<String, String> extractFormParams(HttpServletRequest request) {
String queryString = request.getQueryString();
Map<String, String[]> requestParams = request.getParameterMap();
List<String> queryStringKeys = getQueryStringKeys(queryString);
return requestParams.entrySet().stream()
.filter(e -> !queryStringKeys.contains(e.getKey()))
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()[0]));
}
private List<String> getQueryStringKeys(String queryString) {
if(queryString == null || queryString.length() == 0) {
return Collections.emptyList();
} else {
return Arrays.stream(queryString.split("&"))
.map(pair -> pair.split("=")[0])
.collect(Collectors.toList());
}
}
private String getPathAndQueryUrl(HttpServletRequest request) {
String queryString = request.getQueryString();
String requestUrl = request.getRequestURL().toString();
if(queryString != null && queryString != "") {
return requestUrl + "?" + queryString;
}
return requestUrl;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
metadata-complete="true"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<servlet>
<servlet-name>helloWorld</servlet-name>
<servlet-class>guide.HelloWorldServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloWorld</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>helloWorldFilter</filter-name>
<filter-class>guide.TwilioRequestValidatorFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>helloWorldFilter</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
</web-app>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment