From 3480cb5646a20203a0a64ecc3334629122a6dce7 Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Thu, 8 Aug 2013 09:53:18 -0400 Subject: [PATCH] session timeout improvements --- .../main/resources/META-INF/testrealm.json | 4 +- .../src/main/webapp/saas/admin/index.html | 41 ++----------- .../src/main/webapp/saas/admin/js/app.js | 12 +++- .../main/webapp/saas/admin/js/controllers.js | 11 +++- .../src/main/webapp/saas/admin/js/services.js | 22 +------ .../admin/lib/jquery/jquery.idletimeout.js | 15 +++-- .../services/resources/SaasService.java | 60 +++++++++++-------- 7 files changed, 73 insertions(+), 92 deletions(-) diff --git a/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json b/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json index 642af04a29..b333aab903 100755 --- a/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json +++ b/examples/as7-eap-demo/server/src/main/resources/META-INF/testrealm.json @@ -1,8 +1,8 @@ { "realm" : "demo", "enabled" : true, - "tokenLifespan" : 6000, - "accessCodeLifespan" : 30, + "tokenLifespan" : 10, + "accessCodeLifespan" : 10, "sslNotRequired" : true, "cookieLoginAllowed" : true, "privateKey" : "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=", diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/index.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/index.html index 3983457b35..d792b3013e 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/index.html +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/index.html @@ -22,7 +22,6 @@ - @@ -63,13 +62,14 @@ - - diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js index dd295d7e68..9fe75a59de 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js @@ -160,13 +160,19 @@ module.config(function($httpProvider) { }); -module.factory('errorInterceptor', function($q, $window, $rootScope, $location) { +module.factory('errorInterceptor', function($q, $window, $rootScope, $location, Auth) { return function(promise) { return promise.then(function(response) { $rootScope.httpProviderError = null; return response; }, function(response) { - $rootScope.httpProviderError = response.status; + if (response.status == 401) { + console.log('session timeout?'); + Auth.loggedIn = false; + $location.url('/'); + } else { + $rootScope.httpProviderError = response.status; + } return $q.reject(response); }); }; @@ -191,6 +197,7 @@ module.factory('spinnerInterceptor', function($q, $window, $rootScope, $location }; }); +/* module.directive('kcInput', function() { var d = { scope : true, @@ -235,6 +242,7 @@ module.directive('kcEnter', function() { }); }; }); +*/ module.filter('remove', function() { return function(input, remove, attribute) { diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js index 860426ac41..ef872b3118 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js @@ -11,6 +11,13 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location }; $scope.auth = Auth; + $http.get('/auth-server/rest/saas/whoami').success(function(data, status) { + Auth.user = data; + Auth.loggedIn = true; + }) + .error(function(data, status) { + Auth.loggedIn = false; + }); $scope.$watch(function() { return $location.path(); @@ -34,11 +41,11 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location } if (showrealm) { - console.log('redirecting'); + console.log('default redirect to realm: ' + id); Current.realm = Current.realms[id]; $location.url("/realms/" + id); } else { - console.log('not redirecting'); + //console.log('not redirecting'); } }); }); diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js index d31cd1cdae..4d542353c5 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js @@ -2,32 +2,14 @@ var module = angular.module('keycloak.services', [ 'ngResource' ]); -module.service('Auth', function($resource, $http, $location, $routeParams) { +module.service('Auth', function() { var auth = { - loggedIn : keycloakCookieLoggedIn + loggedIn : false }; auth.user = { userId : null, displayName : null }; - auth.logout = function() { - auth.user = { - userId : null, - displayName : null - }; - auth.loggedIn = false; - $http.get('/auth-server/rest/saas/logout-cookie'); - }; - if (!auth.loggedIn) { - return auth; - } - $http.get('/auth-server/rest/saas/whoami').success(function(data, status) { - auth.user = data; - //alert(data.userId); - }) - .error(function(data, status) { - alert("Failed!"); - }); return auth; }); diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/jquery/jquery.idletimeout.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/jquery/jquery.idletimeout.js index c1a6c3d7ab..025fc3dcdc 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/jquery/jquery.idletimeout.js +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/lib/jquery/jquery.idletimeout.js @@ -82,9 +82,11 @@ _startTimer: function(){ var self = this; - this.timer = win.setTimeout(function(){ - self._keepAlive(); - }, this.options.pollingInterval * 1000); + if (this.options.pollingInterval > 0) { + this.timer = win.setTimeout(function () { + self._keepAlive(); + }, this.options.pollingInterval * 1000); + } }, _stopTimer: function(){ @@ -103,6 +105,7 @@ // if too many requests failed, abort if( !this.failedRequests ){ + console.log('aborting...'); this._stopTimer(); options.onAbort.call( this.warning[0] ); return; @@ -112,12 +115,14 @@ timeout: options.AJAXTimeout, url: options.keepAliveURL, error: function(){ + console.log('failure for keepalive'); self.failedRequests--; }, success: function(response){ - if($.trim(response) !== options.serverResponseEquals){ + console.log('success for keepalive'); +/* if($.trim(response) !== options.serverResponseEquals){ self.failedRequests--; - } + }*/ }, complete: function(){ if( recurse ){ diff --git a/services/src/main/java/org/keycloak/services/resources/SaasService.java b/services/src/main/java/org/keycloak/services/resources/SaasService.java index edbde02045..61466369f3 100755 --- a/services/src/main/java/org/keycloak/services/resources/SaasService.java +++ b/services/src/main/java/org/keycloak/services/resources/SaasService.java @@ -1,5 +1,6 @@ package org.keycloak.services.resources; +import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.logging.Logger; import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.HttpResponse; @@ -11,27 +12,12 @@ import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RoleModel; -import org.keycloak.services.models.UserModel; import org.keycloak.services.models.UserCredentialModel; +import org.keycloak.services.models.UserModel; import org.keycloak.services.resources.admin.RealmsAdminResource; -import javax.ws.rs.Consumes; -import javax.ws.rs.ForbiddenException; -import javax.ws.rs.FormParam; -import javax.ws.rs.GET; -import javax.ws.rs.NotAuthorizedException; -import javax.ws.rs.NotFoundException; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.NewCookie; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; +import javax.ws.rs.*; +import javax.ws.rs.core.*; import java.net.URI; /** @@ -87,22 +73,42 @@ public class SaasService { } } - @Path("whoami") + @Path("keepalive") @GET - @Produces("application/json") - public Response whoAmI(final @Context HttpHeaders headers) { + @NoCache + public Response keepalive(final @Context HttpHeaders headers) { + logger.info("keepalive"); return new Transaction() { @Override public Response callImpl() { - logger.info("WHOAMI start."); RealmManager realmManager = new RealmManager(session); RealmModel realm = realmManager.defaultRealm(); if (realm == null) throw new NotFoundException(); UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers); if (user == null) { - return Response.status(404).build(); + return Response.status(401).build(); + } + NewCookie refreshCookie = authManager.createSaasIdentityCookie(realm, user, uriInfo); + return Response.noContent().cookie(refreshCookie).build(); + } + }.call(); + } + + @Path("whoami") + @GET + @Produces("application/json") + @NoCache + public Response whoAmI(final @Context HttpHeaders headers) { + return new Transaction() { + @Override + public Response callImpl() { + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.defaultRealm(); + if (realm == null) throw new NotFoundException(); + UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers); + if (user == null) { + return Response.status(401).build(); } - logger.info("WHOAMI: " + user.getLoginName()); return Response.ok(new WhoAmI(user.getLoginName(), user.getLoginName())).build(); } }.call(); @@ -111,6 +117,7 @@ public class SaasService { @Path("isLoggedIn.js") @GET @Produces("application/javascript") + @NoCache public String isLoggedIn(final @Context HttpHeaders headers) { return new Transaction() { @Override @@ -165,6 +172,7 @@ public class SaasService { @Path("loginPage.html") @GET + @NoCache public void loginPage() { new Transaction() { @Override @@ -179,6 +187,7 @@ public class SaasService { @Path("logout") @GET + @NoCache public void logout() { new Transaction() { @Override @@ -194,6 +203,7 @@ public class SaasService { @Path("logout-cookie") @GET + @NoCache public void logoutCookie() { logger.info("*** logoutCookie"); new Transaction() { @@ -205,6 +215,7 @@ public class SaasService { } public final static String loginFormPath = "/sdk/login.xhtml"; + protected void forwardToLoginForm(RealmModel realm) { request.setAttribute(RealmModel.class.getName(), realm); URI action = uriInfo.getBaseUriBuilder().path(SaasService.class).path(SaasService.class, "processLogin").build(); @@ -216,7 +227,6 @@ public class SaasService { } - @Path("login") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED)