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