Skip to content

Commit

Permalink
IAP Refresh Session Example. (GoogleCloudPlatform#1230)
Browse files Browse the repository at this point in the history
* IAP Refresh Session Example.

* Review comments.

* Use flask.render_template.
  • Loading branch information
jeffmendoza authored and Jon Wayne Parrott committed Nov 28, 2017
1 parent 53e782a commit 87f67e6
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 0 deletions.
1 change: 1 addition & 0 deletions iap/refresh/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lib
22 changes: 22 additions & 0 deletions iap/refresh/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Identity-Aware Proxy Refresh Session Sample

This sample is used on the following documentation page:

* https://cloud.google.com/iap/docs/sessions-howto


## Deploy to Google App Engine standard environment

```shell
$ gcloud app deploy

```

Enable Cloud IAP using the instructions here:
https://cloud.google.com/iap/docs/app-engine-quickstart#enabling_iap

## Usage

The app will continually refresh a fake status (always "Success"). After 1 hour,
the AJAX request will fail. The [js/poll.js](js/poll.js) code will detect this
and allow the user to refresh the session.
9 changes: 9 additions & 0 deletions iap/refresh/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /js
static_dir: js
- url: .*
script: main.app
18 changes: 18 additions & 0 deletions iap/refresh/appengine_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2016 Google Inc.
#
# 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 google.appengine.ext import vendor

# Add any libraries installed in the "lib" folder.
vendor.add('lib')
69 changes: 69 additions & 0 deletions iap/refresh/js/poll.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright Google Inc.
//
// 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.

"use strict";

function getStatus() {
var statusElm = document.getElementById('status');
statusElm.innerHTML = 'Polling';
fetch('/status').then(function(response) {
if (response.ok) {
return response.text();
}
// [START handle_error]
if (response.status === 401) {
statusElm.innerHTML = 'Login stale. <input type="button" value="Refresh" onclick="sessionRefreshClicked();"/>';
}
// [END handle_error]
else {
statusElm.innerHTML = response.statusText;
}
throw new Error (response.statusText);
})
.then(function(text) {
statusElm.innerHTML = text;
})
.catch(function(statusText) {
});
}

getStatus();
setInterval(getStatus, 10000); // 10 seconds

// [START refresh_session]
var iapSessionRefreshWindow = null;

function sessionRefreshClicked() {
if (iapSessionRefreshWindow == null) {
iapSessionRefreshWindow = window.open("/_gcp_iap/do_session_refresh");
window.setTimeout(checkSessionRefresh, 500);
}
return false;
}

function checkSessionRefresh() {
if (iapSessionRefreshWindow != null && !iapSessionRefreshWindow.closed) {
fetch('/favicon.ico').then(function(response) {
if (response.status === 401) {
window.setTimeout(checkSessionRefresh, 500);
} else {
iapSessionRefreshWindow.close();
iapSessionRefreshWindow = null;
}
});
} else {
iapSessionRefreshWindow = null;
}
}
// [END refresh_session]
53 changes: 53 additions & 0 deletions iap/refresh/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright Google Inc.
#
# 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.

"""
Sample application that demonstrates refreshing a session when using
Identity Aware Proxy. This application is for App Engine Standard.
"""

import flask
from google.appengine.api import users

app = flask.Flask(__name__)


@app.route('/')
def index():
user = users.get_current_user()
if user:
logged_in = True
nickname = user.nickname()
logout_url = users.create_logout_url('/')
login_url = None
else:
logged_in = False
nickname = None
logout_url = None
login_url = users.create_login_url('/')

template_values = {
'logged_in': logged_in,
'nickname': nickname,
'logout_url': logout_url,
'login_url': login_url,
}

return flask.render_template('index.html', **template_values)


# Fake status
@app.route('/status')
def status():
return 'Success'
35 changes: 35 additions & 0 deletions iap/refresh/main_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright 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.

import main
import webtest


def test_index(testbed, login):
app = webtest.TestApp(main.app)

response = app.get('/')
assert 'Login' in response.body

login()
response = app.get('/')
assert 'Logout' in response.body
assert 'user@example.com' in response.body


def test_status(testbed):
app = webtest.TestApp(main.app)

response = app.get('/status')
assert 'Success' in response.body
1 change: 1 addition & 0 deletions iap/refresh/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Flask==0.12.2
13 changes: 13 additions & 0 deletions iap/refresh/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title> Fake Status Page </title>
<div id="welcome">
{% if logged_in %}
Welcome, {{ nickname }} ! (<a href="{{ logout_url }}">sign out</a>)
{% else %}
<a href="{{ login_url }}">Sign in</a>
{% endif %}
</div>
<div id="message">Live status below:</div>
<div id="status">No status yet.</div>
<script src="/js/poll.js"></script>

0 comments on commit 87f67e6

Please sign in to comment.