session timeout improvements
This commit is contained in:
parent
095b4c62fb
commit
3480cb5646
7 changed files with 73 additions and 92 deletions
|
@ -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=",
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
<script src="lib/angular/angular-resource.js"></script>
|
||||
<script src="lib/angular/ui-bootstrap-tpls-0.4.0.js"></script>
|
||||
|
||||
<script src="/auth-server/rest/saas/isLoggedIn.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
<script src="js/controllers.js"></script>
|
||||
<script src="js/loaders.js"></script>
|
||||
|
@ -63,13 +62,14 @@
|
|||
<script src="lib/jquery/jquery.idletimeout.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$.idleTimeout('#idletimeout', '#idletimeout a', {
|
||||
idleAfter: 5,
|
||||
pollingInterval: 0,
|
||||
keepAliveURL: '',
|
||||
idleAfter: 300,
|
||||
pollingInterval: 60,
|
||||
keepAliveURL: '/auth-server/rest/saas/keepalive',
|
||||
serverResponseEquals: '',
|
||||
failedRequests: 1,
|
||||
onTimeout: function(){
|
||||
$(this).slideUp();
|
||||
window.location = "timeout.html";
|
||||
window.location = "/auth-server/rest/saas/logout";
|
||||
},
|
||||
onIdle: function(){
|
||||
$(this).slideDown(); // show the warning bar
|
||||
|
@ -84,35 +84,4 @@
|
|||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
<!--
|
||||
<body data-ng-controller="GlobalCtrl">
|
||||
<div id="idletimeout">
|
||||
You will be logged off in <span></span> seconds due to inactivity.
|
||||
<a id="idletimeout-resume" href="#">Click here to continue using this web page</a>.
|
||||
</div>
|
||||
|
||||
|
||||
<div class="alert-container" data-ng-show="notification" data-ng-click="notification = null">
|
||||
<div class="alert alert-{{notification.type}}">{{notification.message}}</div>
|
||||
</div>
|
||||
|
||||
<div id="wrap">
|
||||
<div data-ng-include data-src="'partials/menu.html'"></div>
|
||||
|
||||
<div data-ng-view id="view" data-ng-hide="httpProviderError"></div>
|
||||
|
||||
<div id="httpProviderError" data-ng-show="httpProviderError">
|
||||
<button class="btn btn-danger" data-ng-click="httpProviderError=null">
|
||||
<strong>Error</strong> {{httpProviderError}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="loading">
|
||||
<i class="icon-spinner icon-spin"></i> Loading...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
-->
|
||||
</html>
|
||||
|
|
|
@ -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) {
|
||||
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) {
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
|
||||
|
|
|
@ -82,9 +82,11 @@
|
|||
_startTimer: function(){
|
||||
var self = this;
|
||||
|
||||
this.timer = win.setTimeout(function(){
|
||||
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 ){
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue