Created
November 29, 2016 19:47
-
-
Save hortega/59c88d15b732ae9311b6de6fe358c76c to your computer and use it in GitHub Desktop.
Files for Twilio guide about validating Twilio requests in Servlet project
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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