Skip to content

Commit bd070d9

Browse files
committed
appengine/oauth2 sample (#168)
* appengine/oauth2 sample * Also add minor formatting change to url fetch. * check style helping too much.
1 parent c6749dd commit bd070d9

File tree

11 files changed

+334
-0
lines changed

11 files changed

+334
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,7 @@ dependency-reduced-pom.xml
2626
buildNumber.properties
2727

2828
service-account.json
29+
30+
# intellij
31+
.idea/
32+
*.iml

appengine/oauth2/.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Eclipse files
2+
.project
3+
.classpath
4+
.settings
5+
6+
# Target folders
7+
target/

appengine/oauth2/README.md

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Google App Engine Standard Environment
2+
## Oauth2 Sample
3+
4+
This sample demonstrates using the Oauth2 apis to create an authenticaion filter.
5+
6+
See the [Google App Engine standard environment documentation][ae-docs] for more
7+
detailed instructions.
8+
9+
10+
## Setup
11+
1. In the [Cloud Developers Console](https://cloud.google.com/console) > API Manager > Credentials,
12+
create a Oauth Client ID for a Web Application. You will need to provide an authroized JavaScript
13+
origin. Typically, https://projectID.appspot.com.
14+
1. Edit `src/main/webapp/index.html` and change `YOUR_CLIENT_ID_HERE.apps.googleusercontent.com` to
15+
Client ID from the prior step.
16+
17+
## Running locally
18+
NOTE: The app can be run locally, but the Oauth2 APIs do not work with the development server.
19+
20+
$ mvn appengine:devserver
21+
22+
## Deploying
23+
$ mvn appengine:update -Dappengine.appId=YOUR-PROJECT-ID -Dappengine.version=SOME-VERSION
24+
25+
1. Using your browser, visit `https://YOUR-PROJECT-ID.appspot.com`, click Sign In.
26+
27+
1. The Sign In process will then request some text from your app, and then display it, if
28+
the id matches the list in `src/main/java/com/example/appengine/Oauth2Filter.java`.
29+
30+
## Adding you to the list of valid users
31+
NOTE: Typically, you would use this for Service Accounts, but user accounts work as well.
32+
33+
1. Enable logging by uncommenting the context.log line in
34+
`src/main/java/com/example/appengine/Oauth2Filter.java`, redeploy, and visit the page
35+
1. Look at the logs in [Cloud Developers Console](https://cloud.google.com/console) > Logs.
36+
37+
1. Add the `tokenAudience` to the `allowedClients`.
38+
39+
1. Deploy and visit the page again.
40+
41+
[ae-docs]: https://cloud.google.com/appengine/docs/java/

appengine/oauth2/pom.xml

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<!--
2+
Copyright 2015 Google Inc. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<project>
17+
<modelVersion>4.0.0</modelVersion>
18+
<packaging>war</packaging>
19+
<version>1.0-SNAPSHOT</version>
20+
<groupId>com.example.appengine</groupId>
21+
<artifactId>appengine-oauth2</artifactId>
22+
23+
<properties>
24+
<appengine.sdk.version>1.9.34</appengine.sdk.version>
25+
<maven.compiler.target>1.7</maven.compiler.target>
26+
<maven.compiler.source>1.7</maven.compiler.source>
27+
</properties>
28+
<parent>
29+
<groupId>com.google.cloud</groupId>
30+
<artifactId>doc-samples</artifactId>
31+
<version>1.0.0</version>
32+
<relativePath>../..</relativePath>
33+
</parent>
34+
35+
<dependencies>
36+
<dependency>
37+
<groupId>com.google.appengine</groupId>
38+
<artifactId>appengine-api-1.0-sdk</artifactId>
39+
<version>${appengine.sdk.version}</version>
40+
</dependency>
41+
<dependency>
42+
<groupId>javax.servlet</groupId>
43+
<artifactId>servlet-api</artifactId>
44+
<type>jar</type>
45+
<scope>provided</scope>
46+
</dependency>
47+
</dependencies>
48+
49+
<build>
50+
<!-- for hot reload of the web application -->
51+
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
52+
<plugins>
53+
<plugin>
54+
<groupId>com.google.appengine</groupId>
55+
<artifactId>appengine-maven-plugin</artifactId>
56+
<version>${appengine.sdk.version}</version>
57+
</plugin>
58+
</plugins>
59+
</build>
60+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright 2015 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.appengine;
18+
19+
import java.io.IOException;
20+
import java.io.PrintWriter;
21+
22+
import javax.servlet.http.HttpServlet;
23+
import javax.servlet.http.HttpServletRequest;
24+
import javax.servlet.http.HttpServletResponse;
25+
26+
// [START example]
27+
@SuppressWarnings("serial")
28+
public class HelloServlet extends HttpServlet {
29+
30+
@Override
31+
public void doPost(final HttpServletRequest req, final HttpServletResponse resp)
32+
throws IOException {
33+
PrintWriter out = resp.getWriter();
34+
out.print("Hello, world"); // simple hello world response
35+
}
36+
}
37+
// [END example]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package com.example.appengine;
15+
16+
import static com.google.appengine.api.utils.SystemProperty.environment;
17+
18+
import com.google.appengine.api.oauth.OAuthRequestException;
19+
import com.google.appengine.api.oauth.OAuthService;
20+
import com.google.appengine.api.oauth.OAuthServiceFactory;
21+
import com.google.appengine.api.oauth.OAuthServiceFailureException;
22+
import com.google.appengine.api.users.User;
23+
import com.google.appengine.api.utils.SystemProperty;
24+
25+
import java.io.IOException;
26+
import java.util.HashSet;
27+
import java.util.Set;
28+
29+
import javax.servlet.Filter;
30+
import javax.servlet.FilterChain;
31+
import javax.servlet.FilterConfig;
32+
import javax.servlet.ServletContext;
33+
import javax.servlet.ServletException;
34+
import javax.servlet.ServletRequest;
35+
import javax.servlet.ServletResponse;
36+
import javax.servlet.http.HttpServletResponse;
37+
38+
/**
39+
* Filter to verify that request has a "Authorization: Bearer xxxx" header,
40+
* and check if xxxx is authorized to use this app.
41+
*
42+
* Note - this is to demonstrate the OAuth2 APIs, as it is possible to lockdown some
43+
* of your app's URL's using cloud console by adding service accounts to the project.
44+
*/
45+
public class Oauth2Filter implements Filter {
46+
47+
private ServletContext context;
48+
49+
@Override
50+
public void init(final FilterConfig config) throws ServletException {
51+
this.context = config.getServletContext();
52+
}
53+
54+
// [START oauth2]
55+
@Override
56+
public void doFilter(final ServletRequest servletReq, final ServletResponse servletResp,
57+
final FilterChain chain) throws IOException, ServletException {
58+
final String scope = "https://www.googleapis.com/auth/userinfo.email";
59+
Set<String> allowedClients = new HashSet<>();
60+
61+
HttpServletResponse resp = (HttpServletResponse) servletResp;
62+
63+
OAuthService oauth = OAuthServiceFactory.getOAuthService();
64+
65+
allowedClients.add("407408718192.apps.googleusercontent.com"); // list of client ids to allow
66+
allowedClients.add("755878275993-j4k7emq6rlupctce1c28enpcrr50vfo1.apps.googleusercontent.com");
67+
68+
// Only check Oauth2 when in production, skip if run in development.
69+
SystemProperty.Environment.Value env = environment.value();
70+
if (env == SystemProperty.Environment.Value.Production) { // APIs only work in Production
71+
try {
72+
User user = oauth.getCurrentUser(scope);
73+
String tokenAudience = oauth.getClientId(scope);
74+
75+
// The line below is commented out for privacy.
76+
// context.log("tokenAudience: " + tokenAudience); // Account we match
77+
78+
if (!allowedClients.contains(tokenAudience)) {
79+
throw new OAuthRequestException("audience of token '" + tokenAudience
80+
+ "' is not in allowed list " + allowedClients);
81+
}
82+
} catch (OAuthRequestException ex) {
83+
resp.sendError(HttpServletResponse.SC_NOT_FOUND); // Not allowed
84+
return;
85+
} catch (OAuthServiceFailureException ex) {
86+
resp.sendError(HttpServletResponse.SC_NOT_FOUND); // some failure - reject
87+
context.log("oauth2 failure", ex);
88+
return;
89+
}
90+
}
91+
chain.doFilter(servletReq, servletResp); // continue processing
92+
}
93+
// [END oauth2]
94+
95+
@Override
96+
public void destroy() { }
97+
98+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- [START_EXCLUDE] -->
3+
<!--
4+
Copyright 2016 Google Inc. All Rights Reserved.
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
-->
15+
<!-- [END_EXCLUDE] -->
16+
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
17+
<application>YOUR-PROJECT-ID</application>
18+
<version>YOUR-VERSION-ID</version>
19+
<threadsafe>true</threadsafe>
20+
</appengine-web-app>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
3+
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
4+
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
5+
version="2.5">
6+
<filter>
7+
<filter-name>Oauth2Filter</filter-name>
8+
<filter-class>com.example.appengine.Oauth2Filter</filter-class>
9+
</filter>
10+
<filter-mapping>
11+
<filter-name>Oauth2Filter</filter-name>
12+
<url-pattern>/hello</url-pattern>
13+
</filter-mapping>
14+
15+
<servlet>
16+
<servlet-name>hello</servlet-name>
17+
<servlet-class>com.example.appengine.HelloServlet</servlet-class>
18+
</servlet>
19+
<servlet-mapping>
20+
<servlet-name>hello</servlet-name>
21+
<url-pattern>/hello</url-pattern>
22+
</servlet-mapping>
23+
24+
<welcome-file-list>
25+
<welcome-file>index.html</welcome-file>
26+
</welcome-file-list>
27+
</web-app>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta name="google-signin-scope" content="profile">
5+
<meta name="google-signin-client_id" content="YOUR_CLIENT_ID_HERE.apps.googleusercontent.com" />
6+
7+
<script src="https://apis.google.com/js/platform.js" async defer></script>
8+
<script>
9+
function onSignIn(googleUser) {
10+
// Useful data for your client-side scripts:
11+
var access_token = googleUser.getAuthResponse().access_token;
12+
13+
14+
var xhr = new XMLHttpRequest();
15+
xhr.open('POST', '/hello');
16+
xhr.setRequestHeader("Authorization", "Bearer "+access_token);
17+
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
18+
xhr.onload = function() {
19+
document.getElementById('response').innerHTML = xhr.responseText;
20+
document.getElementById('me').style = "display:inline;";
21+
};
22+
xhr.onError = function() {
23+
document.getElementById('response').innerHTML = "Error";
24+
document.getElementById('me').style = "display:inline;";
25+
};
26+
xhr.send();
27+
}
28+
</script>
29+
</head>
30+
<body>
31+
<div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div>
32+
<div id="me" style="display: none;">
33+
<h1><span id="response"></span></h1>
34+
</div>
35+
</body>
36+
</html>

appengine/urlfetch/pom.xml

+3
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ Copyright 2015 Google Inc. All Rights Reserved.
1919
<version>1.0-SNAPSHOT</version>
2020
<groupId>com.example.appengine</groupId>
2121
<artifactId>appengine-URLFetch</artifactId>
22+
2223
<parent>
2324
<groupId>com.google.cloud</groupId>
2425
<artifactId>doc-samples</artifactId>
2526
<version>1.0.0</version>
2627
<relativePath>../..</relativePath>
2728
</parent>
29+
2830
<dependencies>
2931
<dependency>
3032
<groupId>javax.servlet</groupId>
@@ -38,6 +40,7 @@ Copyright 2015 Google Inc. All Rights Reserved.
3840
<version>20160212</version>
3941
</dependency>
4042
</dependencies>
43+
4144
<build>
4245
<!-- for hot reload of the web application -->
4346
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>

pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
<module>appengine/mailgun</module>
5050
<module>appengine/mailjet</module>
5151
<module>appengine/memcache</module>
52+
<module>appengine/oauth2</module>
5253
<module>appengine/sendgrid</module>
5354
<module>appengine/static-files</module>
5455
<module>appengine/twilio</module>

0 commit comments

Comments
 (0)