Skip to content

Commit

Permalink
Initial commit for Github
Browse files Browse the repository at this point in the history
  • Loading branch information
engelke committed Mar 14, 2019
0 parents commit a077882
Show file tree
Hide file tree
Showing 19 changed files with 626 additions and 0 deletions.
15 changes: 15 additions & 0 deletions 1-HelloWorld/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2019 Google LLC
#
# 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.

runtime: python37
47 changes: 47 additions & 0 deletions 1-HelloWorld/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright 2019 Google LLC
#
# 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.

from flask import Flask, render_template

app = Flask(__name__)


# Disable browser caching so changes in each step are always shown
@app.after_request
def set_response_headers(response):
response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '0'
return response

@app.route('/', methods=['GET'])
def say_hello():
page = render_template('index.html')
return page

@app.route('/privacy', methods=['GET'])
def show_policy():
page = render_template('privacy.html')
return page


if __name__ == '__main__':
# This is used when running locally, only to verify it does not have
# significant errors. It cannot demonstrate restricting access using
# Identity-Aware Proxy when run locally, only when deployed.
#
# When deploying to Google App Engine, a webserver process such as
# Gunicorn will serve the app. This can be configured by adding an
# `entrypoint` to app.yaml.
app.run(host='127.0.0.1', port=8080, debug=True)
1 change: 1 addition & 0 deletions 1-HelloWorld/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Flask>=1.0.0
15 changes: 15 additions & 0 deletions 1-HelloWorld/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html>
<head>
<title>IAP Hello World</title>
</head>
<body>
<h1>Hello World</h1>

<p>
Hello, world! This is step 1 of the <em>User Authentication with IAP</em>
codelab.
</p>

</body>
</html>
17 changes: 17 additions & 0 deletions 1-HelloWorld/templates/privacy.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!doctype html>
<html>
<head>
<title>Privacy Policy</title>
</head>
<body>
<h1>Privacy Policy</h1>

<p>
This is a demonstration application that has access to your email address
and a unique user identifier code. None of that data is ever stored by
the application, and is used only to display a web page to the logged-in
user showing those values.
</p>

</body>
</html>
15 changes: 15 additions & 0 deletions 2-HelloUser/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2019 Google LLC
#
# 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.

runtime: python37
52 changes: 52 additions & 0 deletions 2-HelloUser/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright 2019 Google LLC
#
# 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.

from flask import Flask, render_template, request

app = Flask(__name__)


# Disable browser caching so changes in each step are always shown
@app.after_request
def set_response_headers(response):
response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '0'
return response

@app.route('/', methods=['GET'])
def say_hello():
user_email = request.headers.get('X-Goog-Authenticated-User-Email')
user_id = request.headers.get('X-Goog-Authenticated-User-ID')

page = render_template('index.html',
email=user_email,
id=user_id)
return page

@app.route('/privacy', methods=['GET'])
def show_policy():
page = render_template('privacy.html')
return page


if __name__ == '__main__':
# This is used when running locally, only to verify it does not have
# significant errors. It cannot demonstrate restricting access using
# Identity-Aware Proxy when run locally, only when deployed.
#
# When deploying to Google App Engine, a webserver process such as
# Gunicorn will serve the app. This can be configured by adding an
# `entrypoint` to app.yaml.
app.run(host='127.0.0.1', port=8080, debug=True)
1 change: 1 addition & 0 deletions 2-HelloUser/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Flask>=1.0.0
19 changes: 19 additions & 0 deletions 2-HelloUser/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!doctype html>
<html>
<head>
<title>IAP Hello User</title>
</head>
<body>
<h1>Hello User</h1>

<p>
Hello, {{ email }}! Your persistent ID is {{ id }}.
</p>

<p>
This is step 2 of the <em>User Authentication with IAP</em>
codelab.
</p>

</body>
</html>
17 changes: 17 additions & 0 deletions 2-HelloUser/templates/privacy.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!doctype html>
<html>
<head>
<title>Privacy Policy</title>
</head>
<body>
<h1>Privacy Policy</h1>

<p>
This is a demonstration application that has access to your email address
and a unique user identifier code. None of that data is ever stored by
the application, and is used only to display a web page to the logged-in
user showing those values.
</p>

</body>
</html>
15 changes: 15 additions & 0 deletions 3-HelloVerifiedUser/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2019 Google LLC
#
# 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.

runtime: python37
74 changes: 74 additions & 0 deletions 3-HelloVerifiedUser/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Copyright 2019 Google LLC
#
# 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.

from flask import request
from jose import jwt
import os
import requests

KEYS = None # Cached public keys for verification
AUDIENCE = None # Cached value requiring information from metadata server


# Google publishes the public keys needed to verify a JWT. Save them in KEYS.
def keys():
global KEYS

if KEYS is None:
resp = requests.get('https://www.gstatic.com/iap/verify/public_key')
KEYS = resp.json()

return KEYS


# Returns the JWT "audience" that should be in the assertion
def audience():
global AUDIENCE

if AUDIENCE is None:
project_id = os.getenv('GOOGLE_CLOUD_PROJECT', None)

endpoint = 'http://metadata.google.internal'
path = '/computeMetadata/v1/project/numeric-project-id'
response = requests.get(
'{}/{}'.format(endpoint, path),
headers = {'Metadata-Flavor': 'Google'}
)
project_number = response.json()

AUDIENCE = '/projects/{}/apps/{}'.format(project_number, project_id)

return AUDIENCE


# Return the authenticated user's email address and persistent user ID if
# available from Cloud Identity Aware Proxy (IAP). If IAP is not active,
# returns None.
#
# Raises an exception if IAP header exists, but JWT token is invalid, which
# would indicates bypass of IAP or inability to fetch KEYS.
def user():
# Requests coming through IAP have special headers
assertion = request.headers.get('X-Goog-IAP-JWT-Assertion')
if assertion is None: # Request did not come through IAP
return None, None

info = jwt.decode(
assertion,
keys(),
algorithms=['ES256'],
audience=audience()
)

return info['email'], info['sub']
57 changes: 57 additions & 0 deletions 3-HelloVerifiedUser/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright 2019 Google LLC
#
# 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.

from auth import user
from flask import Flask, render_template, request

app = Flask(__name__)


# Disable browser caching so changes in each step are always shown
@app.after_request
def set_response_headers(response):
response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '0'
return response

@app.route('/', methods=['GET'])
def say_hello():
user_email = request.headers.get('X-Goog-Authenticated-User-Email')
user_id = request.headers.get('X-Goog-Authenticated-User-ID')

verified_email, verified_id = user()

page = render_template('index.html',
email=user_email,
id=user_id,
verified_email=verified_email,
verified_id=verified_id)
return page

@app.route('/privacy', methods=['GET'])
def show_policy():
page = render_template('privacy.html')
return page


if __name__ == '__main__':
# This is used when running locally, only to verify it does not have
# significant errors. It cannot demonstrate restricting access using
# Identity-Aware Proxy when run locally, only when deployed.
#
# When deploying to Google App Engine, a webserver process such as
# Gunicorn will serve the app. This can be configured by adding an
# `entrypoint` to app.yaml.
app.run(host='127.0.0.1', port=8080, debug=True)
4 changes: 4 additions & 0 deletions 3-HelloVerifiedUser/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Flask>=1.0.0
cryptography
python-jose[cryptography]
requests
24 changes: 24 additions & 0 deletions 3-HelloVerifiedUser/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!doctype html>
<html>
<head>
<title>IAP Hello Verified User</title>
</head>
<body>
<h1>Hello Verified User</h1>

<p>
Hello, {{ email }}! Your persistent ID appears to be {{ id }}.
</p>

<p>
Your verified email is {{ verified_email }},
and your verified persistent ID is {{ verified_id }}.
</p>

<p>
This is step 3 of the <em>User Authentication with IAP</em>
codelab.
</p>

</body>
</html>
Loading

0 comments on commit a077882

Please sign in to comment.