NIFI-655:

- Adding automatic client side token renewal.
This commit is contained in:
Matt Gilman 2015-11-13 16:19:05 -05:00
parent 06cb7cfc10
commit 749f4e9be1
12 changed files with 1117 additions and 978 deletions

View File

@ -28,6 +28,7 @@
<link rel="stylesheet" href="js/jquery/qtip2/jquery.qtip.min.css?" type="text/css" />
<link rel="stylesheet" href="js/jquery/ui-smoothness/jquery-ui-1.10.4.min.css" type="text/css" />
<script type="text/javascript" src="js/jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery.base64.js"></script>
<script type="text/javascript" src="js/jquery/jquery.center.js"></script>
<script type="text/javascript" src="js/jquery/combo/jquery.combo.js?${project.version}"></script>
<script type="text/javascript" src="js/jquery/modal/jquery.modal.js?${project.version}"></script>

View File

@ -40,6 +40,7 @@
<script type="text/javascript" src="js/codemirror/lib/codemirror-compressed.js"></script>
<script type="text/javascript" src="js/jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery/ui-smoothness/jquery-ui-1.10.4.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery.base64.js"></script>
<script type="text/javascript" src="js/jquery/jquery.center.js"></script>
<script type="text/javascript" src="js/jquery/jquery.ellipsis.js"></script>
<script type="text/javascript" src="js/jquery/jquery.each.js"></script>

View File

@ -30,6 +30,7 @@
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />
<script type="text/javascript" src="js/jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery.base64.js"></script>
<script type="text/javascript" src="js/jquery/jquery.center.js"></script>
<script type="text/javascript" src="js/jquery/combo/jquery.combo.js?${project.version}"></script>
<script type="text/javascript" src="js/jquery/modal/jquery.modal.js?${project.version}"></script>

View File

@ -30,6 +30,7 @@
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />
<script type="text/javascript" src="js/jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery.base64.js"></script>
<script type="text/javascript" src="js/jquery/jquery.center.js"></script>
<script type="text/javascript" src="js/jquery/combo/jquery.combo.js?${project.version}"></script>
<script type="text/javascript" src="js/jquery/modal/jquery.modal.js?${project.version}"></script>

View File

@ -30,6 +30,7 @@
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />
<script type="text/javascript" src="js/jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery.base64.js"></script>
<script type="text/javascript" src="js/jquery/jquery.center.js"></script>
<script type="text/javascript" src="js/jquery/modal/jquery.modal.js?${project.version}"></script>
<script type="text/javascript" src="js/jquery/combo/jquery.combo.js?${project.version}"></script>

View File

@ -31,6 +31,7 @@
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />
<script type="text/javascript" src="js/jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery.base64.js"></script>
<script type="text/javascript" src="js/jquery/jquery.center.js"></script>
<script type="text/javascript" src="js/jquery/modal/jquery.modal.js?${project.version}"></script>
<script type="text/javascript" src="js/jquery/tabbs/jquery.tabbs.js?${project.version}"></script>

View File

@ -38,6 +38,7 @@
<script type="text/javascript" src="js/codemirror/lib/codemirror-compressed.js"></script>
<script type="text/javascript" src="js/jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery/ui-smoothness/jquery-ui-1.10.4.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery.base64.js"></script>
<script type="text/javascript" src="js/jquery/jquery.center.js"></script>
<script type="text/javascript" src="js/jquery/tabbs/jquery.tabbs.js?${project.version}"></script>
<script type="text/javascript" src="js/jquery/combo/jquery.combo.js?${project.version}"></script>

View File

@ -30,6 +30,7 @@
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />
<script type="text/javascript" src="js/jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery.base64.js"></script>
<script type="text/javascript" src="js/jquery/jquery.center.js"></script>
<script type="text/javascript" src="js/jquery/jquery.form.min.js"></script>
<script type="text/javascript" src="js/jquery/combo/jquery.combo.js?${project.version}"></script>

View File

@ -31,6 +31,7 @@
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick.grid.css" type="text/css" />
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />
<script type="text/javascript" src="js/jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery.base64.js"></script>
<script type="text/javascript" src="js/jquery/jquery.center.js"></script>
<script type="text/javascript" src="js/jquery/tabbs/jquery.tabbs.js?${project.version}"></script>
<script type="text/javascript" src="js/jquery/combo/jquery.combo.js?${project.version}"></script>

View File

@ -98,7 +98,7 @@ nf.Login = (function () {
}
}).done(function (jwt) {
// store the jwt and reload the page
nf.Storage.setItem('jwt', jwt);
nf.Storage.setItem('jwt', jwt, nf.Common.getJwtExpiration(jwt));
// check to see if they actually have access now
$.ajax({
@ -109,15 +109,18 @@ nf.Login = (function () {
if (response.identity === 'anonymous') {
showLogoutLink();
// schedule automatic token refresh
nf.Common.scheduleTokenRefresh();
// show the user
var user = getJwtSubject(jwt);
var user = nf.Common.getJwtSubject(jwt);
$('#nifi-user-submit-justification').text(user);
// show the registration form
initializeNiFiRegistration();
showNiFiRegistration();
} else {
// reload as appropriate
// reload as appropriate - no need to schedule token refresh as the page is reloading
if (top !== window) {
parent.window.location = '/nifi';
} else {
@ -127,8 +130,11 @@ nf.Login = (function () {
}).fail(function (xhr, status, error) {
showLogoutLink();
// schedule automatic token refresh
nf.Common.scheduleTokenRefresh();
// show the user
var user = getJwtSubject(jwt);
var user = nf.Common.getJwtSubject(jwt);
$('#nifi-user-submit-justification').text(user);
if (xhr.status === 401) {
@ -189,33 +195,6 @@ nf.Login = (function () {
});
};
/**
* Extracts the subject from the specified jwt. If the jwt is not as expected
* an empty string is returned.
*
* @param {string} jwt
* @returns {string}
*/
var getJwtSubject = function (jwt) {
if (nf.Common.isDefinedAndNotNull(jwt)) {
var segments = jwt.split(/\./);
if (segments.length !== 3) {
return '';
}
var rawPayload = $.base64.atob(segments[1]);
var payload = JSON.parse(rawPayload);
if (nf.Common.isDefinedAndNotNull(payload['preferred_username'])) {
return payload['preferred_username'];
} else {
'';
}
}
return '';
};
var logout = function () {
nf.Storage.removeItem('jwt');
};
@ -272,7 +251,7 @@ nf.Login = (function () {
$('#login-message').text('Your account is active and you are already logged in.');
}).fail(function (xhr, status, error) {
if (xhr.status === 401) {
var user = getJwtSubject(jwt);
var user = nf.Common.getJwtSubject(jwt);
// show the user
$('#nifi-user-submit-justification').text(user);
@ -316,7 +295,7 @@ nf.Login = (function () {
if (xhr.status === 401) {
// attempt to get a token for the current user without passing login credentials
token.done(function (jwt) {
var user = getJwtSubject(jwt);
var user = nf.Common.getJwtSubject(jwt);
// show the user
$('#nifi-user-submit-justification').text(user);

View File

@ -20,7 +20,61 @@
nf.Storage = (function () {
// Store items for two days before being eligible for removal.
var TWO_DAYS = 86400000 * 2;
var TWO_DAYS = nf.Common.MILLIS_PER_DAY * 2;
/**
* Checks the expiration for the specified entry.
*
* @param {object} entry
* @returns {boolean}
*/
var checkExpiration = function (entry) {
if (nf.Common.isDefinedAndNotNull(entry.expires)) {
// get the expiration
var expires = new Date(entry.expires);
var now = new Date();
// return whether the expiration date has passed
return expires.valueOf() < now.valueOf();
} else {
return false;
}
};
/**
* If the item at key is not expired, the value of field is returned. Otherwise, null.
*
* @param {string} key
* @param {string} field
* @return {object} the value
*/
var getEntryField = function (key, field) {
try {
// parse the entry
var entry = JSON.parse(localStorage.getItem(key));
// ensure the entry and item are present
if (nf.Common.isDefinedAndNotNull(entry)) {
// if the entry is expired, drop it and return null
if (checkExpiration(entry)) {
nf.Storage.removeItem(key);
return null;
}
// if the entry has the specified field return its value
if (nf.Common.isDefinedAndNotNull(entry[field])) {
return entry[field];
} else {
return null;
}
} else {
return null;
}
} catch (e) {
return null;
}
};
return {
/**
@ -34,16 +88,10 @@ nf.Storage = (function () {
var key = localStorage.key(i);
var entry = JSON.parse(localStorage.getItem(key));
// get the expiration
var expires = new Date(entry.expires);
var now = new Date();
// if the expiration date has passed, remove it
if (expires.valueOf() < now.valueOf()) {
localStorage.removeItem(key);
if (checkExpiration(entry)) {
nf.Storage.removeItem(key);
}
} catch (e) {
// likely unable to parse the item
}
}
},
@ -51,12 +99,13 @@ nf.Storage = (function () {
/**
* Stores the specified item.
*
* @param {type} key
* @param {type} item
* @param {string} key
* @param {object} item
* @param {integer} expires
*/
setItem: function (key, item) {
setItem: function (key, item, expires) {
// calculate the expiration
var expires = new Date().valueOf() + TWO_DAYS;
expires = nf.Common.isDefinedAndNotNull(expires) ? expires : new Date().valueOf() + TWO_DAYS;
// create the entry
var entry = {
@ -76,19 +125,18 @@ nf.Storage = (function () {
* @param {type} key
*/
getItem: function (key) {
try {
// parse the entry
var entry = JSON.parse(localStorage.getItem(key));
// ensure the entry and item are present
if (nf.Common.isDefinedAndNotNull(entry) && nf.Common.isDefinedAndNotNull(entry.item)) {
return entry.item;
} else {
return null;
}
} catch (e) {
return null;
}
return getEntryField(key, 'item');
},
/**
* Gets the expiration for the specified item. If the item does not exists our could
* not be parsed, returns null.
*
* @param {string} key
* @returns {integer}
*/
getItemExpiration: function (key) {
return getEntryField(key, 'expires');
},
/**