diff --git a/assets/app/scripts/controllers/util/oauth.js b/assets/app/scripts/controllers/util/oauth.js index adbbbba9e42c..473d48b5c8b7 100644 --- a/assets/app/scripts/controllers/util/oauth.js +++ b/assets/app/scripts/controllers/util/oauth.js @@ -15,6 +15,7 @@ angular.module('openshiftConsole') .then(function(data) { var token = data.token; var then = data.then; + var ttl = data.ttl; // Try to fetch the user var opts = {errorNotification: false, http: {auth: {token: token, triggerLogin: false}}}; @@ -24,7 +25,7 @@ angular.module('openshiftConsole') .then(function(user) { // Set the new user and token in the auth service authLogger.log("OAuthController, got user", user); - AuthService.setUser(user, token); + AuthService.setUser(user, token, ttl); // Redirect to original destination (or default to '/') var destination = then || './'; diff --git a/assets/app/scripts/services/auth.js b/assets/app/scripts/services/auth.js index c7ef95657eca..ac40ede44dea 100644 --- a/assets/app/scripts/services/auth.js +++ b/assets/app/scripts/services/auth.js @@ -7,8 +7,9 @@ angular.module('openshiftConsole') // withUser() // returns a promise that resolves when there is a current user // starts a login if there is no current user -// setUser(user, token) +// setUser(user, token[, ttl]) // sets the current user and token to use for authenticated requests +// if ttl is specified, it indicates how many seconds the user and token are valid // triggers onUserChanged callbacks if the new user is different than the current user // requestRequiresAuth(config) // returns true if the request is to a protected URL @@ -91,11 +92,11 @@ angular.module('openshiftConsole') } }, - setUser: function(user, token) { - authLogger.log('AuthService.setUser()', user, token); + setUser: function(user, token, ttl) { + authLogger.log('AuthService.setUser()', user, token, ttl); var oldUser = userStore.getUser(); - userStore.setUser(user); - userStore.setToken(token); + userStore.setUser(user, ttl); + userStore.setToken(token, ttl); $rootScope.user = user; @@ -146,7 +147,7 @@ angular.module('openshiftConsole') } var self = this; _loginPromise = loginService.login().then(function(result) { - self.setUser(result.user, result.token); + self.setUser(result.user, result.token, result.ttl); _loginCallbacks.fire(result.user); }).catch(function(err) { Logger.error(err); diff --git a/assets/app/scripts/services/login.js b/assets/app/scripts/services/login.js index 650273dceefe..d5c7b5452308 100644 --- a/assets/app/scripts/services/login.js +++ b/assets/app/scripts/services/login.js @@ -28,7 +28,7 @@ angular.module('openshiftConsole') var authLogger = Logger.get("auth"); return { - // Returns a promise that resolves with {user:{...}, token:''}, or rejects with {error:'...'[,error_description:'...',error_uri:'...']} + // Returns a promise that resolves with {user:{...}, token:'...', ttl:X}, or rejects with {error:'...'[,error_description:'...',error_uri:'...']} login: function() { if (_oauth_client_id == "") { return $q.reject({error:'invalid_request', error_description:'RedirectLoginServiceProvider.OAuthClientID() not set'}); @@ -45,7 +45,7 @@ angular.module('openshiftConsole') uri.query({ client_id: _oauth_client_id, response_type: 'token', - state: $location.url(), // TODO: get state working + state: $location.url(), redirect_uri: _oauth_redirect_uri, }); authLogger.log("RedirectLoginService.login(), redirecting", uri.toString()); @@ -86,6 +86,7 @@ angular.module('openshiftConsole') var deferred = $q.defer(); deferred.resolve({ token: fragmentParams.access_token, + ttl: fragmentParams.expires_in, then: fragmentParams.state }); return deferred.promise; diff --git a/assets/app/scripts/services/userstore.js b/assets/app/scripts/services/userstore.js index 2d31b70675ed..a50346541b7a 100644 --- a/assets/app/scripts/services/userstore.js +++ b/assets/app/scripts/services/userstore.js @@ -13,7 +13,8 @@ angular.module('openshiftConsole') authLogger.log("MemoryUserStore.getUser", _user); return _user; }, - setUser: function(user) { + setUser: function(user, ttl) { + // TODO: honor ttl authLogger.log("MemoryUserStore.setUser", user); _user = user; }, @@ -21,7 +22,8 @@ angular.module('openshiftConsole') authLogger.log("MemoryUserStore.getToken", _token); return _token; }, - setToken: function(token) { + setToken: function(token, ttl) { + // TODO: honor ttl authLogger.log("MemoryUserStore.setToken", token); _token = token; } @@ -55,7 +57,8 @@ angular.module('openshiftConsole') return null; } }, - setUser: function(user) { + setUser: function(user, ttl) { + // TODO: honor ttl if (user) { authLogger.log("SessionStorageUserStore.setUser", user); sessionStorage[userkey] = JSON.stringify(user); @@ -74,7 +77,8 @@ angular.module('openshiftConsole') return null; } }, - setToken: function(token) { + setToken: function(token, ttl) { + // TODO: honor ttl if (token) { authLogger.log("SessionStorageUserStore.setToken", token); sessionStorage[tokenkey] = token; @@ -91,6 +95,30 @@ angular.module('openshiftConsole') var authLogger = Logger.get("auth"); var userkey = "LocalStorageUserStore.user"; var tokenkey = "LocalStorageUserStore.token"; + + var ttlKey = function(key) { + return key + ".ttl"; + }; + var setTTL = function(key, ttl) { + if (ttl) { + var expires = new Date().getTime() + ttl*1000; + localStorage[ttlKey(key)] = expires; + authLogger.log("LocalStorageUserStore.setTTL", key, ttl, new Date(expires).toString()); + } else { + localStorage.removeItem(ttlKey(key)); + authLogger.log("LocalStorageUserStore.setTTL deleting", key); + } + }; + var isTTLExpired = function(key) { + var ttl = localStorage[ttlKey(key)]; + if (!ttl) { + return false; + } + var expired = parseInt(ttl) < new Date().getTime(); + authLogger.log("LocalStorageUserStore.isTTLExpired", key, expired); + return expired; + }; + return { available: function() { try { @@ -105,6 +133,12 @@ angular.module('openshiftConsole') }, getUser: function(){ try { + if (isTTLExpired(userkey)) { + authLogger.log("LocalStorageUserStore.getUser expired"); + localStorage.removeItem(userkey); + setTTL(userkey, null); + return null; + } var user = JSON.parse(localStorage[userkey]); authLogger.log("LocalStorageUserStore.getUser", user); return user; @@ -113,17 +147,25 @@ angular.module('openshiftConsole') return null; } }, - setUser: function(user) { + setUser: function(user, ttl) { if (user) { - authLogger.log("LocalStorageUserStore.setUser", user); + authLogger.log("LocalStorageUserStore.setUser", user, ttl); localStorage[userkey] = JSON.stringify(user); + setTTL(userkey, ttl); } else { authLogger.log("LocalStorageUserStore.setUser", user, "deleting"); localStorage.removeItem(userkey); + setTTL(userkey, null); } }, getToken: function() { try { + if (isTTLExpired(tokenkey)) { + authLogger.log("LocalStorageUserStore.getToken expired"); + localStorage.removeItem(tokenkey); + setTTL(tokenkey, null); + return null; + } var token = localStorage[tokenkey]; authLogger.log("LocalStorageUserStore.getToken", token); return token; @@ -132,13 +174,15 @@ angular.module('openshiftConsole') return null; } }, - setToken: function(token) { + setToken: function(token, ttl) { if (token) { - authLogger.log("LocalStorageUserStore.setToken", token); + authLogger.log("LocalStorageUserStore.setToken", token, ttl); localStorage[tokenkey] = token; + setTTL(tokenkey, ttl); } else { - authLogger.log("LocalStorageUserStore.setToken", token, "deleting"); + authLogger.log("LocalStorageUserStore.setToken", token, ttl, "deleting"); localStorage.removeItem(tokenkey); + setTTL(tokenkey, null); } } } diff --git a/assets/package.json b/assets/package.json index 60707cb8f8d8..810c9731bb17 100644 --- a/assets/package.json +++ b/assets/package.json @@ -44,7 +44,7 @@ "karma-phantomjs-launcher": "0.1.4", "less": "2.4.0", "load-grunt-tasks": "0.4.0", - "lodash": "^3.8.0", + "lodash": "3.2.0", "phantomjs": "1.9.15", "pretty-bytes": "1.0.4", "protractor": "1.7.0", diff --git a/pkg/assets/bindata.go b/pkg/assets/bindata.go index 0c174d38e21d..d5bacc838651 100644 --- a/pkg/assets/bindata.go +++ b/pkg/assets/bindata.go @@ -20363,7 +20363,19 @@ a ? (b.log("SessionStorageUserStore.setToken", a), sessionStorage[d] = a) :(b.lo } ]; }).provider("LocalStorageUserStore", function() { this.$get = [ "Logger", function(a) { -var b = a.get("auth"), c = "LocalStorageUserStore.user", d = "LocalStorageUserStore.token"; +var b = a.get("auth"), c = "LocalStorageUserStore.user", d = "LocalStorageUserStore.token", e = function(a) { +return a + ".ttl"; +}, f = function(a, c) { +if (c) { +var d = new Date().getTime() + 1e3 * c; +localStorage[e(a)] = d, b.log("LocalStorageUserStore.setTTL", a, c, new Date(d).toString()); +} else localStorage.removeItem(e(a)), b.log("LocalStorageUserStore.setTTL deleting", a); +}, g = function(a) { +var c = localStorage[e(a)]; +if (!c) return !1; +var d = parseInt(c) < new Date().getTime(); +return b.log("LocalStorageUserStore.isTTLExpired", a, d), d; +}; return { available:function() { try { @@ -20377,25 +20389,27 @@ return !1; }, getUser:function() { try { +if (g(c)) return b.log("LocalStorageUserStore.getUser expired"), localStorage.removeItem(c), f(c, null), null; var a = JSON.parse(localStorage[c]); return b.log("LocalStorageUserStore.getUser", a), a; } catch (d) { return b.error("LocalStorageUserStore.getUser", d), null; } }, -setUser:function(a) { -a ? (b.log("LocalStorageUserStore.setUser", a), localStorage[c] = JSON.stringify(a)) :(b.log("LocalStorageUserStore.setUser", a, "deleting"), localStorage.removeItem(c)); +setUser:function(a, d) { +a ? (b.log("LocalStorageUserStore.setUser", a, d), localStorage[c] = JSON.stringify(a), f(c, d)) :(b.log("LocalStorageUserStore.setUser", a, "deleting"), localStorage.removeItem(c), f(c, null)); }, getToken:function() { try { +if (g(d)) return b.log("LocalStorageUserStore.getToken expired"), localStorage.removeItem(d), f(d, null), null; var a = localStorage[d]; return b.log("LocalStorageUserStore.getToken", a), a; } catch (c) { return b.error("LocalStorageUserStore.getToken", c), null; } }, -setToken:function(a) { -a ? (b.log("LocalStorageUserStore.setToken", a), localStorage[d] = a) :(b.log("LocalStorageUserStore.setToken", a, "deleting"), localStorage.removeItem(d)); +setToken:function(a, c) { +a ? (b.log("LocalStorageUserStore.setToken", a, c), localStorage[d] = a, f(d, c)) :(b.log("LocalStorageUserStore.setToken", a, c, "deleting"), localStorage.removeItem(d), f(d, null)); } }; } ]; @@ -20430,12 +20444,12 @@ withUser:function() { var a = p.getUser(); return a ? (h.user = a, j.log("AuthService.withUser()", a), e.when(a)) :(j.log("AuthService.withUser(), calling startLogin()"), this.startLogin()); }, -setUser:function(a, b) { -j.log("AuthService.setUser()", a, b); -var c = p.getUser(); -p.setUser(a), p.setToken(b), h.user = a; -var d = c && c.metadata && c.metadata.name, e = a && a.metadata && a.metadata.name; -d != e && (j.log("AuthService.setUser(), user changed", c, a), m.fire(a)); +setUser:function(a, b, c) { +j.log("AuthService.setUser()", a, b, c); +var d = p.getUser(); +p.setUser(a, c), p.setToken(b, c), h.user = a; +var e = d && d.metadata && d.metadata.name, f = a && a.metadata && a.metadata.name; +e != f && (j.log("AuthService.setUser(), user changed", d, a), m.fire(a)); }, requestRequiresAuth:function(a) { var b = a.url.toString().indexOf("api/") > 0; @@ -20451,7 +20465,7 @@ startLogin:function() { if (n) return j.log("Login already in progress"), n; var a = this; return n = q.login().then(function(b) { -a.setUser(b.user, b.token), k.fire(b.user); +a.setUser(b.user, b.token, b.ttl), k.fire(b.user); })["catch"](function(a) { i.error(a); })["finally"](function() { @@ -21085,6 +21099,7 @@ if (c.access_token && "bearer" == c.token_type) { var j = e.defer(); return j.resolve({ token:c.access_token, +ttl:c.expires_in, then:c.state }), j.promise; } @@ -21814,7 +21829,7 @@ b.unwatchAll(d); } ]), angular.module("openshiftConsole").controller("OAuthController", [ "$location", "$q", "RedirectLoginService", "DataService", "AuthService", "Logger", function(a, b, c, d, e, f) { var g = f.get("auth"); c.finish().then(function(b) { -var c = b.token, f = b.then, h = { +var c = b.token, f = b.then, h = b.ttl, i = { errorNotification:!1, http:{ auth:{ @@ -21823,8 +21838,8 @@ triggerLogin:!1 } } }; -g.log("OAuthController, got token, fetching user", h), d.get("users", "~", {}, h).then(function(b) { -g.log("OAuthController, got user", b), e.setUser(b, c); +g.log("OAuthController, got token, fetching user", i), d.get("users", "~", {}, i).then(function(b) { +g.log("OAuthController, got user", b), e.setUser(b, c, h); var d = f || "./"; URI(d).is("absolute") && (g.log("OAuthController, invalid absolute redirect", d), d = "./"), g.log("OAuthController, redirecting", d), a.url(d); })["catch"](function(b) {