diff --git a/.gitignore b/.gitignore
index 86dc131d1b2..6731271b7d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,7 @@ dependency-reduced-pom.xml
buildNumber.properties
service-account.json
+
+# intellij
+.idea/
+*.iml
diff --git a/appengine/oauth2/.gitignore b/appengine/oauth2/.gitignore
new file mode 100644
index 00000000000..471339729ae
--- /dev/null
+++ b/appengine/oauth2/.gitignore
@@ -0,0 +1,7 @@
+# Eclipse files
+.project
+.classpath
+.settings
+
+# Target folders
+target/
diff --git a/appengine/oauth2/README.md b/appengine/oauth2/README.md
new file mode 100644
index 00000000000..3f38cfba462
--- /dev/null
+++ b/appengine/oauth2/README.md
@@ -0,0 +1,41 @@
+# Google App Engine Standard Environment
+## Oauth2 Sample
+
+This sample demonstrates using the Oauth2 apis to create an authenticaion filter.
+
+See the [Google App Engine standard environment documentation][ae-docs] for more
+detailed instructions.
+
+
+## Setup
+1. In the [Cloud Developers Console](https://cloud.google.com/console) > API Manager > Credentials,
+create a Oauth Client ID for a Web Application. You will need to provide an authroized JavaScript
+origin. Typically, https://projectID.appspot.com.
+1. Edit `src/main/webapp/index.html` and change `YOUR_CLIENT_ID_HERE.apps.googleusercontent.com` to
+Client ID from the prior step.
+
+## Running locally
+NOTE: The app can be run locally, but the Oauth2 APIs do not work with the development server.
+
+ $ mvn appengine:devserver
+
+## Deploying
+ $ mvn appengine:update -Dappengine.appId=YOUR-PROJECT-ID -Dappengine.version=SOME-VERSION
+
+1. Using your browser, visit `https://YOUR-PROJECT-ID.appspot.com`, click Sign In.
+
+1. The Sign In process will then request some text from your app, and then display it, if
+the id matches the list in `src/main/java/com/example/appengine/Oauth2Filter.java`.
+
+## Adding you to the list of valid users
+NOTE: Typically, you would use this for Service Accounts, but user accounts work as well.
+
+1. Enable logging by uncommenting the context.log line in
+`src/main/java/com/example/appengine/Oauth2Filter.java`, redeploy, and visit the page
+1. Look at the logs in [Cloud Developers Console](https://cloud.google.com/console) > Logs.
+
+1. Add the `tokenAudience` to the `allowedClients`.
+
+1. Deploy and visit the page again.
+
+[ae-docs]: https://cloud.google.com/appengine/docs/java/
diff --git a/appengine/oauth2/pom.xml b/appengine/oauth2/pom.xml
new file mode 100644
index 00000000000..b29ab18dad4
--- /dev/null
+++ b/appengine/oauth2/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+ war
+ 1.0-SNAPSHOT
+ com.example.appengine
+ appengine-oauth2
+
+
+ 1.9.34
+ 1.7
+ 1.7
+
+
+ com.google.cloud
+ doc-samples
+ 1.0.0
+ ../..
+
+
+
+
+ com.google.appengine
+ appengine-api-1.0-sdk
+ ${appengine.sdk.version}
+
+
+ javax.servlet
+ servlet-api
+ jar
+ provided
+
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+
+ com.google.appengine
+ appengine-maven-plugin
+ ${appengine.sdk.version}
+
+
+
+
diff --git a/appengine/oauth2/src/main/java/com/example/appengine/HelloServlet.java b/appengine/oauth2/src/main/java/com/example/appengine/HelloServlet.java
new file mode 100644
index 00000000000..9e4ebbe6f1e
--- /dev/null
+++ b/appengine/oauth2/src/main/java/com/example/appengine/HelloServlet.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2015 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 com.example.appengine;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+// [START example]
+@SuppressWarnings("serial")
+public class HelloServlet extends HttpServlet {
+
+ @Override
+ public void doPost(final HttpServletRequest req, final HttpServletResponse resp)
+ throws IOException {
+ PrintWriter out = resp.getWriter();
+ out.print("Hello, world"); // simple hello world response
+ }
+}
+// [END example]
diff --git a/appengine/oauth2/src/main/java/com/example/appengine/Oauth2Filter.java b/appengine/oauth2/src/main/java/com/example/appengine/Oauth2Filter.java
new file mode 100644
index 00000000000..17bca9e35a0
--- /dev/null
+++ b/appengine/oauth2/src/main/java/com/example/appengine/Oauth2Filter.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 com.example.appengine;
+
+import static com.google.appengine.api.utils.SystemProperty.environment;
+
+import com.google.appengine.api.oauth.OAuthRequestException;
+import com.google.appengine.api.oauth.OAuthService;
+import com.google.appengine.api.oauth.OAuthServiceFactory;
+import com.google.appengine.api.oauth.OAuthServiceFailureException;
+import com.google.appengine.api.users.User;
+import com.google.appengine.api.utils.SystemProperty;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Filter to verify that request has a "Authorization: Bearer xxxx" header,
+ * and check if xxxx is authorized to use this app.
+ *
+ * Note - this is to demonstrate the OAuth2 APIs, as it is possible to lockdown some
+ * of your app's URL's using cloud console by adding service accounts to the project.
+ */
+public class Oauth2Filter implements Filter {
+
+ private ServletContext context;
+
+ @Override
+ public void init(final FilterConfig config) throws ServletException {
+ this.context = config.getServletContext();
+ }
+
+ // [START oauth2]
+ @Override
+ public void doFilter(final ServletRequest servletReq, final ServletResponse servletResp,
+ final FilterChain chain) throws IOException, ServletException {
+ final String scope = "https://www.googleapis.com/auth/userinfo.email";
+ Set allowedClients = new HashSet<>();
+
+ HttpServletResponse resp = (HttpServletResponse) servletResp;
+
+ OAuthService oauth = OAuthServiceFactory.getOAuthService();
+
+ allowedClients.add("407408718192.apps.googleusercontent.com"); // list of client ids to allow
+ allowedClients.add("755878275993-j4k7emq6rlupctce1c28enpcrr50vfo1.apps.googleusercontent.com");
+
+ // Only check Oauth2 when in production, skip if run in development.
+ SystemProperty.Environment.Value env = environment.value();
+ if (env == SystemProperty.Environment.Value.Production) { // APIs only work in Production
+ try {
+ User user = oauth.getCurrentUser(scope);
+ String tokenAudience = oauth.getClientId(scope);
+
+ // The line below is commented out for privacy.
+// context.log("tokenAudience: " + tokenAudience); // Account we match
+
+ if (!allowedClients.contains(tokenAudience)) {
+ throw new OAuthRequestException("audience of token '" + tokenAudience
+ + "' is not in allowed list " + allowedClients);
+ }
+ } catch (OAuthRequestException ex) {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND); // Not allowed
+ return;
+ } catch (OAuthServiceFailureException ex) {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND); // some failure - reject
+ context.log("oauth2 failure", ex);
+ return;
+ }
+ }
+ chain.doFilter(servletReq, servletResp); // continue processing
+ }
+ // [END oauth2]
+
+ @Override
+ public void destroy() { }
+
+}
diff --git a/appengine/oauth2/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/oauth2/src/main/webapp/WEB-INF/appengine-web.xml
new file mode 100644
index 00000000000..c322e7d016e
--- /dev/null
+++ b/appengine/oauth2/src/main/webapp/WEB-INF/appengine-web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ YOUR-PROJECT-ID
+ YOUR-VERSION-ID
+ true
+
diff --git a/appengine/oauth2/src/main/webapp/WEB-INF/web.xml b/appengine/oauth2/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 00000000000..1884992f5f7
--- /dev/null
+++ b/appengine/oauth2/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,27 @@
+
+
+
+ Oauth2Filter
+ com.example.appengine.Oauth2Filter
+
+
+ Oauth2Filter
+ /hello
+
+
+
+ hello
+ com.example.appengine.HelloServlet
+
+
+ hello
+ /hello
+
+
+
+ index.html
+
+
diff --git a/appengine/oauth2/src/main/webapp/index.html b/appengine/oauth2/src/main/webapp/index.html
new file mode 100644
index 00000000000..e5ac6b237ba
--- /dev/null
+++ b/appengine/oauth2/src/main/webapp/index.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/appengine/urlfetch/pom.xml b/appengine/urlfetch/pom.xml
index 09f67af79af..ee062bbb8b8 100644
--- a/appengine/urlfetch/pom.xml
+++ b/appengine/urlfetch/pom.xml
@@ -19,12 +19,14 @@ Copyright 2015 Google Inc. All Rights Reserved.
1.0-SNAPSHOT
com.example.appengine
appengine-URLFetch
+
com.google.cloud
doc-samples
1.0.0
../..
+
javax.servlet
@@ -38,6 +40,7 @@ Copyright 2015 Google Inc. All Rights Reserved.
20160212
+
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
diff --git a/pom.xml b/pom.xml
index 3004a45fc99..741e29e6b06 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
appengine/mailgun
appengine/mailjet
appengine/memcache
+ appengine/oauth2
appengine/sendgrid
appengine/static-files
appengine/twilio