Skip to content

Commit 87f67e6

Browse files
jeffmendozaJon Wayne Parrott
authored and
Jon Wayne Parrott
committed
IAP Refresh Session Example. (GoogleCloudPlatform#1230)
* IAP Refresh Session Example. * Review comments. * Use flask.render_template.
1 parent 53e782a commit 87f67e6

File tree

9 files changed

+221
-0
lines changed

9 files changed

+221
-0
lines changed

iap/refresh/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
lib

iap/refresh/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Identity-Aware Proxy Refresh Session Sample
2+
3+
This sample is used on the following documentation page:
4+
5+
* https://cloud.google.com/iap/docs/sessions-howto
6+
7+
8+
## Deploy to Google App Engine standard environment
9+
10+
```shell
11+
$ gcloud app deploy
12+
13+
```
14+
15+
Enable Cloud IAP using the instructions here:
16+
https://cloud.google.com/iap/docs/app-engine-quickstart#enabling_iap
17+
18+
## Usage
19+
20+
The app will continually refresh a fake status (always "Success"). After 1 hour,
21+
the AJAX request will fail. The [js/poll.js](js/poll.js) code will detect this
22+
and allow the user to refresh the session.

iap/refresh/app.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
runtime: python27
2+
threadsafe: yes
3+
api_version: 1
4+
5+
handlers:
6+
- url: /js
7+
static_dir: js
8+
- url: .*
9+
script: main.app

iap/refresh/appengine_config.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2016 Google Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
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+
from google.appengine.ext import vendor
16+
17+
# Add any libraries installed in the "lib" folder.
18+
vendor.add('lib')

iap/refresh/js/poll.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright Google Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
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+
"use strict";
16+
17+
function getStatus() {
18+
var statusElm = document.getElementById('status');
19+
statusElm.innerHTML = 'Polling';
20+
fetch('/status').then(function(response) {
21+
if (response.ok) {
22+
return response.text();
23+
}
24+
// [START handle_error]
25+
if (response.status === 401) {
26+
statusElm.innerHTML = 'Login stale. <input type="button" value="Refresh" onclick="sessionRefreshClicked();"/>';
27+
}
28+
// [END handle_error]
29+
else {
30+
statusElm.innerHTML = response.statusText;
31+
}
32+
throw new Error (response.statusText);
33+
})
34+
.then(function(text) {
35+
statusElm.innerHTML = text;
36+
})
37+
.catch(function(statusText) {
38+
});
39+
}
40+
41+
getStatus();
42+
setInterval(getStatus, 10000); // 10 seconds
43+
44+
// [START refresh_session]
45+
var iapSessionRefreshWindow = null;
46+
47+
function sessionRefreshClicked() {
48+
if (iapSessionRefreshWindow == null) {
49+
iapSessionRefreshWindow = window.open("/_gcp_iap/do_session_refresh");
50+
window.setTimeout(checkSessionRefresh, 500);
51+
}
52+
return false;
53+
}
54+
55+
function checkSessionRefresh() {
56+
if (iapSessionRefreshWindow != null && !iapSessionRefreshWindow.closed) {
57+
fetch('/favicon.ico').then(function(response) {
58+
if (response.status === 401) {
59+
window.setTimeout(checkSessionRefresh, 500);
60+
} else {
61+
iapSessionRefreshWindow.close();
62+
iapSessionRefreshWindow = null;
63+
}
64+
});
65+
} else {
66+
iapSessionRefreshWindow = null;
67+
}
68+
}
69+
// [END refresh_session]

iap/refresh/main.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copyright Google Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
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+
"""
16+
Sample application that demonstrates refreshing a session when using
17+
Identity Aware Proxy. This application is for App Engine Standard.
18+
"""
19+
20+
import flask
21+
from google.appengine.api import users
22+
23+
app = flask.Flask(__name__)
24+
25+
26+
@app.route('/')
27+
def index():
28+
user = users.get_current_user()
29+
if user:
30+
logged_in = True
31+
nickname = user.nickname()
32+
logout_url = users.create_logout_url('/')
33+
login_url = None
34+
else:
35+
logged_in = False
36+
nickname = None
37+
logout_url = None
38+
login_url = users.create_login_url('/')
39+
40+
template_values = {
41+
'logged_in': logged_in,
42+
'nickname': nickname,
43+
'logout_url': logout_url,
44+
'login_url': login_url,
45+
}
46+
47+
return flask.render_template('index.html', **template_values)
48+
49+
50+
# Fake status
51+
@app.route('/status')
52+
def status():
53+
return 'Success'

iap/refresh/main_test.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
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+
import main
16+
import webtest
17+
18+
19+
def test_index(testbed, login):
20+
app = webtest.TestApp(main.app)
21+
22+
response = app.get('/')
23+
assert 'Login' in response.body
24+
25+
login()
26+
response = app.get('/')
27+
assert 'Logout' in response.body
28+
assert 'user@example.com' in response.body
29+
30+
31+
def test_status(testbed):
32+
app = webtest.TestApp(main.app)
33+
34+
response = app.get('/status')
35+
assert 'Success' in response.body

iap/refresh/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Flask==0.12.2

iap/refresh/templates/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<meta charset="utf-8">
3+
<title> Fake Status Page </title>
4+
<div id="welcome">
5+
{% if logged_in %}
6+
Welcome, {{ nickname }} ! (<a href="{{ logout_url }}">sign out</a>)
7+
{% else %}
8+
<a href="{{ login_url }}">Sign in</a>
9+
{% endif %}
10+
</div>
11+
<div id="message">Live status below:</div>
12+
<div id="status">No status yet.</div>
13+
<script src="/js/poll.js"></script>

0 commit comments

Comments
 (0)