Skip to content

Commit

Permalink
Adding ARENA Auth 1 (of 3): auth-server and browser flow (arenaxr#18)
Browse files Browse the repository at this point in the history
Auth Part 1: auth-server and browser flow
- Depends on github.com/conix-center/ARENA-auth.
- Adds `onauth` event to listen for before connecting to MQTT.
- Usage in `auth.js`.
- Adds Google OAuth2 authentication.
- Linking `auth.js` will start authentication flow and sends `onauth` only when full authorization is complete.

Auth Part 2: command line user flow
- (pending)

Auth Part 3: mqtt broker requires a token and username passed into every connection
- (pending) installed and running but not linked to Part 1 in production
  • Loading branch information
mwfarb authored Sep 4, 2020
1 parent 179cd96 commit 73504c2
Show file tree
Hide file tree
Showing 17 changed files with 579 additions and 23 deletions.
118 changes: 118 additions & 0 deletions auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// auth.js
//
// Authentication and Authorization for the following ARENA assets:
// - MQTT broker
//
// Required:
// <script src="https://apis.google.com/js/platform.js"></script>
// <script src="./defaults.js"></script> <!-- for window.defaults -->
// <script src="./auth.js"></script> <!-- browser authorization flow -->
//
// Optional:
// <script src="./events.js"></script> <!-- for window.globals -->
//
// Implement the following 'onauth' event handler and use it to start code that would
// automatically connects to the MQTT broker so that authentication and access tokens
// can be present when making a broker connection which will need username (email) and
// password (access token).
//
// window.addEventListener('onauth', function (e) {
// client.connect({
// onSuccess: onConnect,
// userName: e.detail.mqtt_username,
// password: e.detail.mqtt_token
// });
// });

'use strict';

var auth2;
// check if the current user is already signed in
gapi.load('auth2', function () {
auth2 = gapi.auth2.init({
client_id: defaults.gAuthClientId
}).then(function () {
auth2 = gapi.auth2.getAuthInstance();
if (!auth2.isSignedIn.get()) {
console.log("User is not signed in.");
// send login with redirection url from this page
location.href = "./signin?redirect_uri=" + encodeURI(location.href);;
} else {
console.log("User is already signed in.");
var googleUser = auth2.currentUser.get();
onSignIn(googleUser);
}
});
});

function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId());
console.log('Full Name: ' + profile.getName());
console.log('Email: ' + profile.getEmail());

// add auth name to objects when user has not defined their name
if (typeof globals !== 'undefined') {
if (typeof defaults !== 'undefined' && globals.userParam == defaults.userParam) {
var cam = globals.camName.split('_');
globals.userParam = profile.getName().replace(/[^a-zA-Z0-9]/g, '');
cam[2] = globals.userParam;
globals.camName = cam.join('_');
}
}
// request mqtt-auth
var id_token = googleUser.getAuthResponse().id_token;
requestMqttToken(profile.getEmail(), id_token);
}

function signOut(rootPath) {
// logout, and disassociate user
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
auth2.disconnect();
// back to signin page
location.href = rootPath + "/signin?redirect_uri=" + encodeURI(location.href);
}

function requestMqttToken(mqtt_username, id_token) {
// Request JWT before connection
let xhr = new XMLHttpRequest();
var params = "username=" + mqtt_username + "&id_token=" + id_token;
params += "&id_auth=google";
// provide user control topics for token construction
if (typeof globals !== 'undefined') {
if (globals.scenenameParam) {
params += "&scene=" + globals.scenenameParam;
}
if (globals.camName) {
params += "&camid=" + globals.camName;
}
if (globals.viveLName) {
params += "&ctrlid1=" + globals.viveLName;
}
if (globals.viveRName) {
params += "&ctrlid2=" + globals.viveRName;
}
}
xhr.open('POST', defaults.urlMqttAuth);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(params);
xhr.responseType = 'json';
xhr.onload = () => {
if (xhr.status !== 200) {
alert(`Error loading token: ${xhr.status}: ${xhr.statusText}`);
} else {
console.log("got user/token:", xhr.response.username, xhr.response.token);
// token must be set to authorize access to MQTT broker
const authCompleteEvent = new CustomEvent('onauth', {
detail: {
mqtt_username: xhr.response.username,
mqtt_token: xhr.response.token
}
});
window.dispatchEvent(authCompleteEvent);
}
};
}
18 changes: 16 additions & 2 deletions build.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@
console.log("Message arrived");
}

client.connect({
onSuccess: onConnect
window.addEventListener('onauth', function (e) {
client.connect({
onSuccess: onConnect,
userName: e.detail.mqtt_username,
password: e.detail.mqtt_token
});
});

// Callback for client.connect()
Expand Down Expand Up @@ -78,9 +82,14 @@
.json_div {
font-family: monospace;
}

#logout {
float: right;
}
</style>
</head>
<body>
<a id="logout" href="#" onclick="signOut('.');">Logout</a>
<br><br>
<table style="display:inline-block">
<tr>
Expand Down Expand Up @@ -578,5 +587,10 @@ <H1>ARENA Build</H1>
</div>
<p>raw JSON:</p>
<div class="json_div" id="rawjson" type="text" size="40" value=""></div>

<!-- login auth check with calls to mqtt connect placed in an `onauth` event listener -->
<script src="https://apis.google.com/js/platform.js"></script>
<script src="./defaults.js"></script>
<script src="./auth.js"></script>
</body>
</html>
10 changes: 10 additions & 0 deletions build/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
font-family: GeneralFoundicons;
font-style: normal;
}
#logout {
float: right;
}
</style>
<script language="javascript" src="third-party/jsoneditor.min.js"></script>
<script src="third-party/clipboard.min.js"></script>
Expand All @@ -28,6 +31,8 @@
<div class='span8 col-md-8 columns eight large-8'>
<h2>Scene Editor</h2>

<a id="logout" href="#" onclick="signOut('..');">Logout</a>

<div id="alert" class="alert alert-error" style="z-index:1000; position: fixed; top: 1em; left: 1em; opacity: 0.9; width: 400px; display: none">
Alert Message.
</div>
Expand Down Expand Up @@ -118,6 +123,11 @@ <h2>Validation</h2>
<textarea id='validate' class='infopanel' readonly disabled class='form-control'></textarea>
</div>
</div>

<!-- login auth check with calls to mqtt connect placed in an `onauth` event listener -->
<script src="https://apis.google.com/js/platform.js"></script>
<script src="../defaults.js"></script>
<script src="../auth.js"></script>
</body>

</html>
12 changes: 8 additions & 4 deletions build/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ var displayAlert = window.displayAlert = function(msg, type, timeMs) {

}

document.addEventListener("DOMContentLoaded", async function() {
window.addEventListener('onauth', async function (e) {
//document.addEventListener("DOMContentLoaded", async function() {

var schema;
var jsoneditor;
Expand Down Expand Up @@ -64,7 +65,7 @@ document.addEventListener("DOMContentLoaded", async function() {
var data = await fetch("dft-config.json");
var dfts = await data.json();

// load values from fedaults or local storage, if they exist
// load values from defaults or local storage, if they exist
select_schema.value = localStorage.getItem("schema_file") === null ? dfts.schema_file : localStorage.getItem("schema_file");
select_schema.dispatchEvent(new Event("change"));
scene.value = localStorage.getItem("scene") === null ? dfts.scene : localStorage.getItem("scene");
Expand Down Expand Up @@ -230,7 +231,9 @@ document.addEventListener("DOMContentLoaded", async function() {
scene_list: document.getElementById("scenelist"),
scene_textbox: document.getElementById("arena_scene"),
log_panel: document.getElementById("logpanel"),
editobj_handler: editobjHandler
editobj_handler: editobjHandler,
mqtt_username: e.detail.mqtt_username,
mqtt_token: e.detail.mqtt_token,
});

// update options (including persist_url) from inputs
Expand Down Expand Up @@ -272,7 +275,7 @@ document.addEventListener("DOMContentLoaded", async function() {
localStorage.setItem("mqtthost", mqtthost.value);
});

// listners for buttons
// listeners for buttons
clear_button.addEventListener("click", function() {
PersistObjects.clearSelected();
});
Expand Down Expand Up @@ -302,6 +305,7 @@ document.addEventListener("DOMContentLoaded", async function() {
PersistObjects.mqttReconnect(mqttConnData);
updateHost();
});
//});
});

displayAlert("Loading..", "info", 3000);
6 changes: 5 additions & 1 deletion build/mqtt-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export default class MqttClient {
onMessageCallback: st.onMessageCallback,
useSSL: st.useSSL !== undefined ? st.useSSL : true,
dbg: st.dbg !== undefined ? st.dbg : false,
mqtt_username: st.mqtt_username,
mqtt_token: st.mqtt_token,
};

if (this.settings.dbg == true) console.log(this.settings);
Expand Down Expand Up @@ -76,7 +78,9 @@ export default class MqttClient {
onFailure: () => {
throw new Error('Could not connect!')
},
useSSL: _this.settings.useSSL
useSSL: _this.settings.useSSL,
userName: _this.settings.mqtt_username,
password: _this.settings.mqtt_token
});
});
}
Expand Down
14 changes: 10 additions & 4 deletions build/persist-objects.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ export async function init(settings) {
scene_list: settings.scene_list,
scene_textbox: settings.scene_textbox,
log_panel: settings.log_panel,
editobj_handler: settings.editobj_handler
editobj_handler: settings.editobj_handler,
mqtt_username: settings.mqtt_username,
mqtt_token: settings.mqtt_token,
}

// Add a "checked" symbol when clicking on a list item
Expand All @@ -36,7 +38,9 @@ export async function init(settings) {
persist.mc = new MqttClient({
host: persist.mqtt_host,
port: persist.mqtt_port,
onMessageCallback: onMqttMessage
onMessageCallback: onMqttMessage,
mqtt_username: persist.mqtt_username,
mqtt_token: persist.mqtt_token,
});

log("Starting connection to " + persist.mqtt_host + ":" + persist.mqtt_port + "...");
Expand Down Expand Up @@ -248,13 +252,15 @@ export function mqttReconnect(settings) {
if (persist.mc)
persist.mc.disconnect();

log("Disconected.");
log("Disconnected.");

// start mqtt client
persist.mc = new MqttClient({
host: persist.mqtt_host,
port: persist.mqtt_port,
onMessageCallback: onMqttMessage
onMessageCallback: onMqttMessage,
mqtt_username: persist.mqtt_username,
mqtt_token: persist.mqtt_token,
});

try {
Expand Down
6 changes: 4 additions & 2 deletions defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const defaults = {
localvidboxHeight:240,
vioTopic:"/topic/vio/",
graphTopic:"$NETWORK/latency",
mqqtPath:"/mqtt/",
persistPath:"/persist/"
mqttPath:"/mqtt/",
persistPath:"/persist/",
urlMqttAuth:"https://oz.andrew.cmu.edu:8888",
gAuthClientId:'173603117246-7lehsb3tpq4i17e7sla5bue1an4ps9t6.apps.googleusercontent.com'
};
5 changes: 5 additions & 0 deletions dev.html
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,11 @@
});
*/
</script>

<!-- login auth check with calls to mqtt connect placed in an `onauth` event listener -->
<script src="https://apis.google.com/js/platform.js"></script>
<script src="./defaults.js"></script>
<script src="./auth.js"></script>
</body>

</html>
2 changes: 1 addition & 1 deletion events.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ if (urlLat && urlLong) {
}

globals.persistenceUrl = '//' + globals.mqttParamZ + defaults.persistPath + globals.scenenameParam;
globals.mqttParam = 'wss://' + globals.mqttParamZ + defaults.mqqtPath;
globals.mqttParam = 'wss://' + globals.mqttParamZ + defaults.mqttPath;
globals.outputTopic = "realm/s/" + globals.scenenameParam + "/";
globals.renderTopic = globals.outputTopic + "#";
globals.camName = "";
Expand Down
11 changes: 8 additions & 3 deletions icons/icons.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ function createIconButton(img, onClick) {
iconButton = document.createElement('button');
iconButton.style.backgroundImage = `url('images/icons/${img}.png')`;
iconButton.className = ICON_BTN_CLASS;
iconButton.setAttribute("id", "btn-"+img);
iconButton.setAttribute("id", "btn-" + img);

// Insert elements.
wrapper.appendChild(iconButton);
iconButton.addEventListener('click', function(evt) {
iconButton.addEventListener('click', function (evt) {
onClick();
evt.stopPropagation();
});
Expand Down Expand Up @@ -91,15 +91,20 @@ function setupIcons() {
console.log("clicked settings");
});

const logoutBtn = createIconButton("roundedlogout", () => {
signOut('.'); // --> ./auth.js
});

var iconsDiv = document.getElementById('iconsDiv');
iconsDiv.appendChild(audioBtn);
iconsDiv.appendChild(videoBtn);
iconsDiv.appendChild(avatarBtn);
iconsDiv.appendChild(logoutBtn);
iconsDiv.appendChild(settingsBtn);
}

AFRAME.registerComponent('iconsinit', {
init: function() {
init: function () {
setupIcons();
}
});
Binary file added images/icons/roundedlogout.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -188,5 +188,9 @@
</a-scene>

<div id="iconsDiv"></div>

<!-- login auth check with calls to mqtt connect placed in an `onauth` event listener -->
<script src="https://apis.google.com/js/platform.js"></script>
<script src="./auth.js"></script>
</body>
</html>
6 changes: 5 additions & 1 deletion mqtt-chat/main.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import MQTTChat from './mqtt-chat.js';

window.addEventListener('load', (event) => {
window.addEventListener('onauth', (e) => {
// window.addEventListener('load', (event) => {
console.log("Loading MQTTChat");
let mqttChat = new MQTTChat({
cameraid: window.globals.camName,
Expand All @@ -9,7 +10,10 @@ window.addEventListener('load', (event) => {
scene: window.globals.scenenameParam,
ping_interval_ms: 30000,
mqtt_host: window.globals.mqttParam,
mqtt_username: e.detail.mqtt_username,
mqtt_token: e.detail.mqtt_token,
});

mqttChat.connect();
// });
});
Loading

0 comments on commit 73504c2

Please sign in to comment.