Merge pull request #371 from patriot1burke/master
keycloak.js admin login
This commit is contained in:
commit
5568c8dc7d
33 changed files with 676 additions and 1188 deletions
|
@ -61,12 +61,12 @@
|
|||
|
||||
<filter-mapping>
|
||||
<filter-name>Keycloak Session Management</filter-name>
|
||||
<url-pattern>/rest/*</url-pattern>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>Keycloak Client Connection Filter</filter-name>
|
||||
<url-pattern>/rest/*</url-pattern>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
|
@ -109,7 +109,7 @@
|
|||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>deny</web-resource-name>
|
||||
<url-pattern>/rest/customers/*</url-pattern>
|
||||
<url-pattern>/customers/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint/>
|
||||
</security-constraint>
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
</head>
|
||||
<body bgcolor="#E3F6CE">
|
||||
<%
|
||||
String logoutUri = KeycloakUriBuilder.fromUri("http://localhost:8080/app-bundle/rest/realms/demo/tokens/logout")
|
||||
String logoutUri = KeycloakUriBuilder.fromUri("http://localhost:8080/app-bundle/realms/demo/tokens/logout")
|
||||
.queryParam("redirect_uri", "http://localhost:8080/app-bundle").build().toString();
|
||||
String acctUri = "http://localhost:8080/app-bundle/rest/realms/demo/account?referrer=customer-portal";
|
||||
String acctUri = "http://localhost:8080/app-bundle/realms/demo/account?referrer=customer-portal";
|
||||
IDToken idToken = CustomerDatabaseClient.getIDToken(request);
|
||||
%>
|
||||
<p><a href="<%=logoutUri%>">logout</a> | <a
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<script src="lib/angular/select2.js" type="text/javascript"></script>
|
||||
<script src="lib/fileupload/angular-file-upload.min.js"></script>
|
||||
|
||||
<script src="js/keycloak.js" type="text/javascript"></script>
|
||||
<script src="js/app.js" type="text/javascript"></script>
|
||||
<script src="js/controllers/realm.js" type="text/javascript"></script>
|
||||
<script src="js/controllers/applications.js" type="text/javascript"></script>
|
||||
|
@ -76,12 +77,12 @@
|
|||
$.idleTimeout('#idletimeout', '#idletimeout a', {
|
||||
idleAfter: 300,
|
||||
pollingInterval: 60,
|
||||
keepAliveURL: authUrl + '/rest/admin/keepalive',
|
||||
// keepAliveURL: authUrl + '/admin/keepalive', would need to change this path
|
||||
serverResponseEquals: '',
|
||||
failedRequests: 1,
|
||||
onTimeout: function(){
|
||||
$(this).slideUp();
|
||||
window.location = authUrl + '/rest/admin/logout';
|
||||
logout();
|
||||
},
|
||||
onIdle: function(){
|
||||
$(this).slideDown(); // show the warning bar
|
||||
|
|
|
@ -1,28 +1,68 @@
|
|||
'use strict';
|
||||
|
||||
var indexUrl = window.location.href;
|
||||
var consoleBaseUrl = window.location.href;
|
||||
consoleBaseUrl = consoleBaseUrl.substring(0, consoleBaseUrl.indexOf("/console"));
|
||||
consoleBaseUrl = consoleBaseUrl + "/console";
|
||||
var configUrl = consoleBaseUrl + "/config";
|
||||
var logoutUrl = consoleBaseUrl + "/logout";
|
||||
var auth = {};
|
||||
var logout = function(){
|
||||
console.log('*** LOGOUT');
|
||||
auth.loggedIn = false;
|
||||
auth.authz = null;
|
||||
auth.user = null;
|
||||
window.location = logoutUrl;
|
||||
};
|
||||
|
||||
|
||||
var authUrl = window.location.href;
|
||||
authUrl = authUrl.substring(0, authUrl.indexOf('/admin/'));
|
||||
|
||||
|
||||
var module = angular.module('keycloak', [ 'keycloak.services', 'keycloak.loaders', 'ui.bootstrap', 'ui.select2', 'angularFileUpload' ]);
|
||||
var resourceRequests = 0;
|
||||
var loadingTimer = -1;
|
||||
|
||||
angular.element(document).ready(function ($http) {
|
||||
$http.get(authUrl + '/rest/admin/whoami').success(function(data) {
|
||||
var auth = {};
|
||||
auth.user = data;
|
||||
auth.loggedIn = true;
|
||||
var keycloakAuth = new Keycloak(configUrl);
|
||||
var auth = {};
|
||||
auth.loggedIn = false;
|
||||
|
||||
keycloakAuth.init('login-required').success(function () {
|
||||
auth.loggedIn = true;
|
||||
auth.authz = keycloakAuth;
|
||||
module.factory('Auth', function() {
|
||||
return auth;
|
||||
});
|
||||
angular.bootstrap(document, ["keycloak"]);
|
||||
}).error(function() {
|
||||
var path = window.location.hash && window.location.hash.substring(1) || '/';
|
||||
window.location = authUrl + '/rest/admin/login?path=' + path;
|
||||
});
|
||||
}).error(function () {
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
module.factory('authInterceptor', function($q, Auth) {
|
||||
return {
|
||||
request: function (config) {
|
||||
var deferred = $q.defer();
|
||||
if (Auth.authz.token) {
|
||||
Auth.authz.updateToken(5).success(function() {
|
||||
config.headers = config.headers || {};
|
||||
config.headers.Authorization = 'Bearer ' + Auth.authz.token;
|
||||
|
||||
deferred.resolve(config);
|
||||
}).error(function() {
|
||||
deferred.reject('Failed to refresh token');
|
||||
});
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
module.config([ '$routeProvider', function($routeProvider) {
|
||||
|
||||
|
@ -675,7 +715,10 @@ module.config([ '$routeProvider', function($routeProvider) {
|
|||
},
|
||||
controller : 'RealmSessionStatsCtrl'
|
||||
})
|
||||
|
||||
.when('/logout', {
|
||||
templateUrl : 'partials/home.html',
|
||||
controller : 'LogoutCtrl'
|
||||
})
|
||||
.otherwise({
|
||||
templateUrl : 'partials/notfound.html'
|
||||
});
|
||||
|
@ -697,19 +740,19 @@ module.config(function($httpProvider) {
|
|||
$httpProvider.defaults.transformRequest.push(spinnerFunction);
|
||||
|
||||
$httpProvider.responseInterceptors.push('spinnerInterceptor');
|
||||
$httpProvider.interceptors.push('authInterceptor');
|
||||
|
||||
});
|
||||
|
||||
module.factory('errorInterceptor', function($q, $window, $rootScope, $location, Auth, Notifications) {
|
||||
module.factory('errorInterceptor', function($q, $window, $rootScope, $location,Notifications) {
|
||||
return function(promise) {
|
||||
return promise.then(function(response) {
|
||||
return response;
|
||||
}, function(response) {
|
||||
if (response.status == 401) {
|
||||
console.log('session timeout?');
|
||||
Auth.loggedIn = false;
|
||||
window.location = authUrl + '/rest/admin/login?path=' + $location.path();
|
||||
} else if (response.status == 403) {
|
||||
logout();
|
||||
} else if (response.status == 403) {
|
||||
Notifications.error("Forbidden");
|
||||
} else if (response.status == 404) {
|
||||
Notifications.error("Not found");
|
||||
|
|
|
@ -361,7 +361,7 @@ module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm,
|
|||
});
|
||||
|
||||
$scope.addRealmRole = function() {
|
||||
$http.post(authUrl + '/rest/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm',
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm',
|
||||
$scope.selectedRealmRoles).success(function() {
|
||||
for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
|
||||
var role = $scope.selectedRealmRoles[i];
|
||||
|
@ -376,7 +376,7 @@ module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm,
|
|||
};
|
||||
|
||||
$scope.deleteRealmRole = function() {
|
||||
$http.delete(authUrl + '/rest/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm',
|
||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm',
|
||||
{data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
||||
for (var i = 0; i < $scope.selectedRealmMappings.length; i++) {
|
||||
var role = $scope.selectedRealmMappings[i];
|
||||
|
@ -391,7 +391,7 @@ module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm,
|
|||
};
|
||||
|
||||
$scope.addApplicationRole = function() {
|
||||
$http.post(authUrl + '/rest/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/applications/' + $scope.targetApp.name,
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/applications/' + $scope.targetApp.name,
|
||||
$scope.selectedApplicationRoles).success(function() {
|
||||
for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
|
||||
var role = $scope.selectedApplicationRoles[i];
|
||||
|
@ -406,7 +406,7 @@ module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm,
|
|||
};
|
||||
|
||||
$scope.deleteApplicationRole = function() {
|
||||
$http.delete(authUrl + '/rest/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/applications/' + $scope.targetApp.name,
|
||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/applications/' + $scope.targetApp.name,
|
||||
{data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
||||
for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
|
||||
var role = $scope.selectedApplicationMappings[i];
|
||||
|
|
|
@ -211,7 +211,7 @@ module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm,
|
|||
});
|
||||
|
||||
$scope.addRealmRole = function() {
|
||||
$http.post(authUrl + '/rest/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/realm',
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/realm',
|
||||
$scope.selectedRealmRoles).success(function() {
|
||||
for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
|
||||
var role = $scope.selectedRealmRoles[i];
|
||||
|
@ -226,7 +226,7 @@ module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm,
|
|||
};
|
||||
|
||||
$scope.deleteRealmRole = function() {
|
||||
$http.delete(authUrl + '/rest/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/realm',
|
||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/realm',
|
||||
{data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
||||
for (var i = 0; i < $scope.selectedRealmMappings.length; i++) {
|
||||
var role = $scope.selectedRealmMappings[i];
|
||||
|
@ -241,7 +241,7 @@ module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm,
|
|||
};
|
||||
|
||||
$scope.addApplicationRole = function() {
|
||||
$http.post(authUrl + '/rest/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/applications/' + $scope.targetApp.name,
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/applications/' + $scope.targetApp.name,
|
||||
$scope.selectedApplicationRoles).success(function() {
|
||||
for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
|
||||
var role = $scope.selectedApplicationRoles[i];
|
||||
|
@ -256,7 +256,7 @@ module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm,
|
|||
};
|
||||
|
||||
$scope.deleteApplicationRole = function() {
|
||||
$http.delete(authUrl + '/rest/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/applications/' + $scope.targetApp.name,
|
||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/applications/' + $scope.targetApp.name,
|
||||
{data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
||||
for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
|
||||
var role = $scope.selectedApplicationMappings[i];
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location, Notifications) {
|
||||
module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $location, Notifications) {
|
||||
$scope.addMessage = function() {
|
||||
Notifications.success("test");
|
||||
};
|
||||
|
||||
$scope.authUrl = authUrl;
|
||||
$scope.logout = logout;
|
||||
|
||||
$scope.auth = Auth;
|
||||
$http.get(authUrl + '/rest/admin/whoami').success(function(data, status) {
|
||||
WhoAmI.get(function(data) {
|
||||
Auth.user = data;
|
||||
Auth.loggedIn = true;
|
||||
|
||||
|
@ -68,10 +69,7 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location
|
|||
return getAccess('manage-audit');
|
||||
}
|
||||
}
|
||||
})
|
||||
.error(function(data, status) {
|
||||
Auth.loggedIn = false;
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$watch(function() {
|
||||
return $location.path();
|
||||
|
@ -123,7 +121,7 @@ module.controller('RealmDropdownCtrl', function($scope, Realm, Current, Auth, $l
|
|||
}
|
||||
});
|
||||
|
||||
module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, $location, Dialog, Notifications, Auth) {
|
||||
module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, WhoAmI, $location, Dialog, Notifications, Auth) {
|
||||
console.log('RealmCreateCtrl');
|
||||
|
||||
Current.realm = null;
|
||||
|
@ -150,7 +148,7 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
|
|||
for (var i = 0; i < $scope.files.length; i++) {
|
||||
var $file = $scope.files[i];
|
||||
$scope.upload = $upload.upload({
|
||||
url: authUrl + '/rest/admin/realms', //upload.php script, node.js route, or servlet url
|
||||
url: authUrl + '/admin/realms', //upload.php script, node.js route, or servlet url
|
||||
// method: POST or PUT,
|
||||
// headers: {'headerKey': 'headerValue'}, withCredential: true,
|
||||
data: {myObj: ""},
|
||||
|
@ -165,7 +163,8 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
|
|||
Realm.query(function(data) {
|
||||
Current.realms = data;
|
||||
|
||||
$http.get(authUrl + '/rest/admin/whoami').success(function(user) {
|
||||
|
||||
WhoAmI.get(function(user) {
|
||||
Auth.user = user;
|
||||
|
||||
Notifications.success("The realm has been uploaded.");
|
||||
|
@ -202,7 +201,7 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
|
|||
Realm.query(function(data) {
|
||||
Current.realms = data;
|
||||
|
||||
$http.get(authUrl + '/rest/admin/whoami').success(function(user) {
|
||||
$http.get(authUrl + '/admin/whoami').success(function(user) {
|
||||
Auth.user = user;
|
||||
|
||||
$location.url("/realms/" + realmCopy.realm);
|
||||
|
@ -573,7 +572,7 @@ module.controller('RealmSocialCtrl', function($scope, realm, Realm, serverInfo,
|
|||
|
||||
var oldCopy = angular.copy($scope.realm);
|
||||
$scope.changed = false;
|
||||
$scope.callbackUrl = $location.absUrl().replace(/\/admin.*/, "/rest/social/callback");
|
||||
$scope.callbackUrl = $location.absUrl().replace(/\/admin.*/, "/social/callback");
|
||||
|
||||
$scope.addProvider = function(pId) {
|
||||
if (!$scope.realm.socialProviders) {
|
||||
|
|
|
@ -28,7 +28,7 @@ module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, ro
|
|||
});
|
||||
|
||||
$scope.addRealmRole = function() {
|
||||
$http.post(authUrl + '/rest/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/realm',
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/realm',
|
||||
$scope.selectedRealmRoles).success(function() {
|
||||
for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
|
||||
var role = $scope.selectedRealmRoles[i];
|
||||
|
@ -43,7 +43,7 @@ module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, ro
|
|||
};
|
||||
|
||||
$scope.deleteRealmRole = function() {
|
||||
$http.delete(authUrl + '/rest/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/realm',
|
||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/realm',
|
||||
{data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
||||
for (var i = 0; i < $scope.selectedRealmMappings.length; i++) {
|
||||
var role = $scope.selectedRealmMappings[i];
|
||||
|
@ -58,7 +58,7 @@ module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, ro
|
|||
};
|
||||
|
||||
$scope.addApplicationRole = function() {
|
||||
$http.post(authUrl + '/rest/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications/' + $scope.application.name,
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications/' + $scope.application.name,
|
||||
$scope.selectedApplicationRoles).success(function() {
|
||||
for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
|
||||
var role = $scope.selectedApplicationRoles[i];
|
||||
|
@ -73,7 +73,7 @@ module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, ro
|
|||
};
|
||||
|
||||
$scope.deleteApplicationRole = function() {
|
||||
$http.delete(authUrl + '/rest/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications/' + $scope.application.name,
|
||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications/' + $scope.application.name,
|
||||
{data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
||||
for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
|
||||
var role = $scope.selectedApplicationMappings[i];
|
||||
|
|
|
@ -127,8 +127,12 @@ module.factory('Notifications', function($rootScope, $timeout) {
|
|||
return notifications;
|
||||
});
|
||||
|
||||
module.factory('WhoAmI', function($resource) {
|
||||
return $resource(consoleBaseUrl + '/whoami');
|
||||
});
|
||||
|
||||
module.factory('Realm', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:id', {
|
||||
return $resource(authUrl + '/admin/realms/:id', {
|
||||
id : '@realm'
|
||||
}, {
|
||||
update : {
|
||||
|
@ -143,7 +147,7 @@ module.factory('Realm', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('RealmAudit', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:id/audit', {
|
||||
return $resource(authUrl + '/admin/realms/:id/audit', {
|
||||
id : '@realm'
|
||||
}, {
|
||||
update : {
|
||||
|
@ -153,17 +157,17 @@ module.factory('RealmAudit', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('RealmAuditEvents', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:id/audit/events', {
|
||||
return $resource(authUrl + '/admin/realms/:id/audit/events', {
|
||||
id : '@realm'
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('ServerInfo', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/serverinfo');
|
||||
return $resource(authUrl + '/admin/serverinfo');
|
||||
});
|
||||
|
||||
module.factory('User', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/users/:userId', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/users/:userId', {
|
||||
realm : '@realm',
|
||||
userId : '@userId'
|
||||
}, {
|
||||
|
@ -174,13 +178,13 @@ module.factory('User', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('UserSessionStats', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/users/:user/session-stats', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/users/:user/session-stats', {
|
||||
realm : '@realm',
|
||||
user : '@user'
|
||||
});
|
||||
});
|
||||
module.factory('UserLogout', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/users/:user/logout', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/users/:user/logout', {
|
||||
realm : '@realm',
|
||||
user : '@user'
|
||||
});
|
||||
|
@ -195,7 +199,7 @@ module.factory('UserSocialLinks', function($resource) {
|
|||
module.factory('UserCredentials', function($resource) {
|
||||
var credentials = {};
|
||||
|
||||
credentials.resetPassword = $resource(authUrl + '/rest/admin/realms/:realm/users/:userId/reset-password', {
|
||||
credentials.resetPassword = $resource(authUrl + '/admin/realms/:realm/users/:userId/reset-password', {
|
||||
realm : '@realm',
|
||||
userId : '@userId'
|
||||
}, {
|
||||
|
@ -204,7 +208,7 @@ module.factory('UserCredentials', function($resource) {
|
|||
}
|
||||
}).update;
|
||||
|
||||
credentials.removeTotp = $resource(authUrl + '/rest/admin/realms/:realm/users/:userId/remove-totp', {
|
||||
credentials.removeTotp = $resource(authUrl + '/admin/realms/:realm/users/:userId/remove-totp', {
|
||||
realm : '@realm',
|
||||
userId : '@userId'
|
||||
}, {
|
||||
|
@ -213,7 +217,7 @@ module.factory('UserCredentials', function($resource) {
|
|||
}
|
||||
}).update;
|
||||
|
||||
credentials.resetPasswordEmail = $resource(authUrl + '/rest/admin/realms/:realm/users/:userId/reset-password-email', {
|
||||
credentials.resetPasswordEmail = $resource(authUrl + '/admin/realms/:realm/users/:userId/reset-password-email', {
|
||||
realm : '@realm',
|
||||
userId : '@userId'
|
||||
}, {
|
||||
|
@ -226,14 +230,14 @@ module.factory('UserCredentials', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('RealmRoleMapping', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/users/:userId/role-mappings/realm', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/realm', {
|
||||
realm : '@realm',
|
||||
userId : '@userId'
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('ApplicationRoleMapping', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/users/:userId/role-mappings/applications/:application', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/applications/:application', {
|
||||
realm : '@realm',
|
||||
userId : '@userId',
|
||||
application : "@application"
|
||||
|
@ -241,14 +245,14 @@ module.factory('ApplicationRoleMapping', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('ApplicationRealmScopeMapping', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application/scope-mappings/realm', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application/scope-mappings/realm', {
|
||||
realm : '@realm',
|
||||
application : '@application'
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('ApplicationApplicationScopeMapping', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application/scope-mappings/applications/:targetApp', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application/scope-mappings/applications/:targetApp', {
|
||||
realm : '@realm',
|
||||
application : '@application',
|
||||
targetApp : '@targetApp'
|
||||
|
@ -258,33 +262,33 @@ module.factory('ApplicationApplicationScopeMapping', function($resource) {
|
|||
|
||||
|
||||
module.factory('RealmRoles', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/roles', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/roles', {
|
||||
realm : '@realm'
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('RoleRealmComposites', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/roles-by-id/:role/composites/realm', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/composites/realm', {
|
||||
realm : '@realm',
|
||||
role : '@role'
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('RealmPushRevocation', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/push-revocation', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/push-revocation', {
|
||||
realm : '@realm'
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('RealmSessionStats', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/session-stats', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/session-stats', {
|
||||
realm : '@realm'
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
module.factory('RoleApplicationComposites', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/roles-by-id/:role/composites/applications/:application', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/composites/applications/:application', {
|
||||
realm : '@realm',
|
||||
role : '@role',
|
||||
application : "@application"
|
||||
|
@ -367,7 +371,7 @@ function roleControl($scope, realm, role, roles, applications,
|
|||
|
||||
$scope.addRealmRole = function() {
|
||||
$scope.compositeSwitchDisabled=true;
|
||||
$http.post(authUrl + '/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
||||
$scope.selectedRealmRoles).success(function() {
|
||||
for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
|
||||
var role = $scope.selectedRealmRoles[i];
|
||||
|
@ -383,7 +387,7 @@ function roleControl($scope, realm, role, roles, applications,
|
|||
|
||||
$scope.deleteRealmRole = function() {
|
||||
$scope.compositeSwitchDisabled=true;
|
||||
$http.delete(authUrl + '/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
||||
{data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
||||
for (var i = 0; i < $scope.selectedRealmMappings.length; i++) {
|
||||
var role = $scope.selectedRealmMappings[i];
|
||||
|
@ -399,7 +403,7 @@ function roleControl($scope, realm, role, roles, applications,
|
|||
|
||||
$scope.addApplicationRole = function() {
|
||||
$scope.compositeSwitchDisabled=true;
|
||||
$http.post(authUrl + '/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
||||
$scope.selectedApplicationRoles).success(function() {
|
||||
for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
|
||||
var role = $scope.selectedApplicationRoles[i];
|
||||
|
@ -415,7 +419,7 @@ function roleControl($scope, realm, role, roles, applications,
|
|||
|
||||
$scope.deleteApplicationRole = function() {
|
||||
$scope.compositeSwitchDisabled=true;
|
||||
$http.delete(authUrl + '/rest/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
|
||||
{data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
||||
for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
|
||||
var role = $scope.selectedApplicationMappings[i];
|
||||
|
@ -466,7 +470,7 @@ function roleControl($scope, realm, role, roles, applications,
|
|||
|
||||
|
||||
module.factory('Role', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/roles/:role', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/roles/:role', {
|
||||
realm : '@realm',
|
||||
role : '@role'
|
||||
}, {
|
||||
|
@ -477,7 +481,7 @@ module.factory('Role', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('RoleById', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/roles-by-id/:role', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role', {
|
||||
realm : '@realm',
|
||||
role : '@role'
|
||||
}, {
|
||||
|
@ -488,7 +492,7 @@ module.factory('RoleById', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('ApplicationRole', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application/roles/:role', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application/roles/:role', {
|
||||
realm : '@realm',
|
||||
application : "@application",
|
||||
role : '@role'
|
||||
|
@ -500,7 +504,7 @@ module.factory('ApplicationRole', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('ApplicationClaims', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application/claims', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application/claims', {
|
||||
realm : '@realm',
|
||||
application : "@application"
|
||||
}, {
|
||||
|
@ -511,40 +515,40 @@ module.factory('ApplicationClaims', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('ApplicationSessionStats', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application/session-stats', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application/session-stats', {
|
||||
realm : '@realm',
|
||||
application : "@application"
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('ApplicationSessionStatsWithUsers', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application/session-stats?users=true', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application/session-stats?users=true', {
|
||||
realm : '@realm',
|
||||
application : "@application"
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('ApplicationLogoutAll', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application/logout-all', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application/logout-all', {
|
||||
realm : '@realm',
|
||||
application : "@application"
|
||||
});
|
||||
});
|
||||
module.factory('ApplicationLogoutUser', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application/logout-user/:user', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application/logout-user/:user', {
|
||||
realm : '@realm',
|
||||
application : "@application",
|
||||
user : "@user"
|
||||
});
|
||||
});
|
||||
module.factory('RealmLogoutAll', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/logout-all', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/logout-all', {
|
||||
realm : '@realm'
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('ApplicationPushRevocation', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application/push-revocation', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application/push-revocation', {
|
||||
realm : '@realm',
|
||||
application : "@application"
|
||||
});
|
||||
|
@ -553,7 +557,7 @@ module.factory('ApplicationPushRevocation', function($resource) {
|
|||
|
||||
|
||||
module.factory('Application', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application', {
|
||||
realm : '@realm',
|
||||
application : '@application'
|
||||
}, {
|
||||
|
@ -564,7 +568,7 @@ module.factory('Application', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('ApplicationInstallation', function($resource) {
|
||||
var url = authUrl + '/rest/admin/realms/:realm/applications/:application/installation/json';
|
||||
var url = authUrl + '/admin/realms/:realm/applications/:application/installation/json';
|
||||
return {
|
||||
url : function(parameters)
|
||||
{
|
||||
|
@ -573,7 +577,7 @@ module.factory('ApplicationInstallation', function($resource) {
|
|||
}
|
||||
});
|
||||
module.factory('ApplicationInstallationJBoss', function($resource) {
|
||||
var url = authUrl + '/rest/admin/realms/:realm/applications/:application/installation/jboss';
|
||||
var url = authUrl + '/admin/realms/:realm/applications/:application/installation/jboss';
|
||||
return {
|
||||
url : function(parameters)
|
||||
{
|
||||
|
@ -583,7 +587,7 @@ module.factory('ApplicationInstallationJBoss', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('ApplicationCredentials', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application/client-secret', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application/client-secret', {
|
||||
realm : '@realm',
|
||||
application : '@application'
|
||||
}, {
|
||||
|
@ -594,7 +598,7 @@ module.factory('ApplicationCredentials', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('ApplicationOrigins', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/applications/:application/allowed-origins', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/applications/:application/allowed-origins', {
|
||||
realm : '@realm',
|
||||
application : '@application'
|
||||
}, {
|
||||
|
@ -606,7 +610,7 @@ module.factory('ApplicationOrigins', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('OAuthClient', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/oauth-clients/:id', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/oauth-clients/:id', {
|
||||
realm : '@realm',
|
||||
id : '@id'
|
||||
}, {
|
||||
|
@ -617,7 +621,7 @@ module.factory('OAuthClient', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('OAuthClientClaims', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/oauth-clients/:oauth/claims', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/oauth-clients/:oauth/claims', {
|
||||
realm : '@realm',
|
||||
oauth : "@oauth"
|
||||
}, {
|
||||
|
@ -629,7 +633,7 @@ module.factory('OAuthClientClaims', function($resource) {
|
|||
|
||||
|
||||
module.factory('OAuthClientCredentials', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/oauth-clients/:oauth/client-secret', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/oauth-clients/:oauth/client-secret', {
|
||||
realm : '@realm',
|
||||
oauth : '@oauth'
|
||||
}, {
|
||||
|
@ -641,14 +645,14 @@ module.factory('OAuthClientCredentials', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('OAuthClientRealmScopeMapping', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/oauth-clients/:oauth/scope-mappings/realm', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/oauth-clients/:oauth/scope-mappings/realm', {
|
||||
realm : '@realm',
|
||||
oauth : '@oauth'
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('OAuthClientApplicationScopeMapping', function($resource) {
|
||||
return $resource(authUrl + '/rest/admin/realms/:realm/oauth-clients/:oauth/scope-mappings/applications/:targetApp', {
|
||||
return $resource(authUrl + '/admin/realms/:realm/oauth-clients/:oauth/scope-mappings/applications/:targetApp', {
|
||||
realm : '@realm',
|
||||
oauth : '@oauth',
|
||||
targetApp : '@targetApp'
|
||||
|
@ -656,8 +660,8 @@ module.factory('OAuthClientApplicationScopeMapping', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('OAuthClientInstallation', function($resource) {
|
||||
var url = authUrl + '/rest/admin/realms/:realm/oauth-clients/:oauth/installation';
|
||||
var resource = $resource(authUrl + '/rest/admin/realms/:realm/oauth-clients/:oauth/installation', {
|
||||
var url = authUrl + '/admin/realms/:realm/oauth-clients/:oauth/installation';
|
||||
var resource = $resource(authUrl + '/admin/realms/:realm/oauth-clients/:oauth/installation', {
|
||||
realm : '@realm',
|
||||
oauth : '@oauth'
|
||||
}, {
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
{{auth.user.displayName}}<b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="{{authUrl}}/rest/realms/{{auth.user.realm}}/account?referrer=admin-console">Manage Account</a></li>
|
||||
<li class="separator"><a href="{{authUrl}}/rest/admin/logout">Sign Out</a></li>
|
||||
<li><a href="{{authUrl}}/realms/{{auth.user.realm}}/account?referrer=security-admin-console">Manage Account</a></li>
|
||||
<li class="separator"><a href="" ng-click="logout()">Sign Out</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -5,7 +5,7 @@ package org.keycloak.models;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface Constants {
|
||||
String ADMIN_CONSOLE_APPLICATION = "admin-console";
|
||||
String ADMIN_CONSOLE_APPLICATION = "security-admin-console";
|
||||
|
||||
String ACCOUNT_MANAGEMENT_APP = "account";
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.jboss.resteasy.spi.BadRequestException;
|
|||
import javax.ws.rs.core.Cookie;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.NewCookie;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
|
@ -25,151 +26,32 @@ import java.net.URI;
|
|||
public class AppAuthManager extends AuthenticationManager {
|
||||
protected static Logger logger = Logger.getLogger(AppAuthManager.class);
|
||||
|
||||
private String cookieName;
|
||||
private TokenManager tokenManager;
|
||||
|
||||
public AppAuthManager(ProviderSession providerSession, String cookieName, TokenManager tokenManager) {
|
||||
public AppAuthManager(ProviderSession providerSession) {
|
||||
super(providerSession);
|
||||
this.cookieName = cookieName;
|
||||
this.tokenManager = tokenManager;
|
||||
}
|
||||
|
||||
public NewCookie createCookie(RealmModel realm, ClientModel client, String code, URI uri) {
|
||||
JWSInput input = new JWSInput(code);
|
||||
boolean verifiedCode = false;
|
||||
try {
|
||||
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
||||
} catch (Exception ignored) {
|
||||
logger.debug("Failed to verify signature", ignored);
|
||||
}
|
||||
if (!verifiedCode) {
|
||||
logger.debug("unverified access code");
|
||||
throw new BadRequestException("unverified access code");
|
||||
}
|
||||
String key = input.readContentAsString();
|
||||
AccessCodeEntry accessCode = tokenManager.pullAccessCode(key);
|
||||
if (accessCode == null) {
|
||||
logger.debug("bad access code");
|
||||
throw new BadRequestException("bad access code");
|
||||
}
|
||||
if (accessCode.isExpired()) {
|
||||
logger.debug("access code expired");
|
||||
throw new BadRequestException("access code expired");
|
||||
}
|
||||
if (!accessCode.getToken().isActive()) {
|
||||
logger.debug("access token expired");
|
||||
throw new BadRequestException("access token expired");
|
||||
}
|
||||
if (!accessCode.getRealm().getId().equals(realm.getId())) {
|
||||
logger.debug("bad realm");
|
||||
throw new BadRequestException("bad realm");
|
||||
|
||||
}
|
||||
if (!client.getClientId().equals(accessCode.getClient().getClientId())) {
|
||||
logger.debug("bad client");
|
||||
throw new BadRequestException("bad client");
|
||||
}
|
||||
|
||||
return createLoginCookie(realm, accessCode.getUser(), accessCode.getClient(), cookieName, uri.getRawPath(), false);
|
||||
public UserModel authenticateRequest(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
|
||||
UserModel user = authenticateIdentityCookie(realm, uriInfo, headers);
|
||||
if (user != null) return user;
|
||||
return authenticateBearerToken(realm, uriInfo, headers);
|
||||
}
|
||||
|
||||
public NewCookie createRefreshCookie(RealmModel realm, UserModel user, ClientModel client, URI uri) {
|
||||
return createLoginCookie(realm, user, client, cookieName, uri.getRawPath(), false);
|
||||
}
|
||||
|
||||
public void expireCookie(URI uri) {
|
||||
expireCookie(cookieName, uri.getRawPath());
|
||||
}
|
||||
|
||||
public Auth authenticateCookie(RealmModel realm, HttpHeaders headers) {
|
||||
return authenticateCookie(realm, headers, cookieName, true);
|
||||
}
|
||||
|
||||
public Auth authenticate(RealmModel realm, HttpHeaders headers) {
|
||||
Auth auth = authenticateCookie(realm, headers);
|
||||
if (auth != null) return auth;
|
||||
return authenticateBearerToken(realm, headers);
|
||||
}
|
||||
|
||||
private Auth authenticateCookie(RealmModel realm, HttpHeaders headers, String cookieName, boolean checkActive) {
|
||||
logger.info("authenticateCookie");
|
||||
Cookie cookie = headers.getCookies().get(cookieName);
|
||||
if (cookie == null) {
|
||||
logger.infov("authenticateCookie could not find cookie: {0}", cookieName);
|
||||
return null;
|
||||
}
|
||||
|
||||
String tokenString = cookie.getValue();
|
||||
try {
|
||||
AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getName(), checkActive);
|
||||
logger.info("token verified");
|
||||
if (checkActive && !token.isActive()) {
|
||||
logger.info("cookie expired");
|
||||
expireCookie(cookie.getName(), cookie.getPath());
|
||||
return null;
|
||||
}
|
||||
|
||||
UserModel user = realm.getUserById(token.getSubject());
|
||||
if (user == null || !user.isEnabled()) {
|
||||
logger.info("Unknown user in cookie");
|
||||
expireCookie(cookie.getName(), cookie.getPath());
|
||||
return null;
|
||||
}
|
||||
|
||||
ClientModel client = null;
|
||||
if (token.getIssuedFor() != null) {
|
||||
client = realm.findClient(token.getIssuedFor());
|
||||
if (client == null || !client.isEnabled()) {
|
||||
logger.info("Unknown client in cookie");
|
||||
expireCookie(cookie.getName(), cookie.getPath());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return new Auth(realm, user, client);
|
||||
} catch (VerificationException e) {
|
||||
logger.info("Failed to verify cookie", e);
|
||||
expireCookie(cookie.getName(), cookie.getPath());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Auth authenticateBearerToken(RealmModel realm, HttpHeaders headers) {
|
||||
String tokenString;
|
||||
public String extractAuthorizationHeaderToken(HttpHeaders headers) {
|
||||
String tokenString = null;
|
||||
String authHeader = headers.getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
|
||||
if (authHeader == null) {
|
||||
return null;
|
||||
} else {
|
||||
if (authHeader != null) {
|
||||
String[] split = authHeader.trim().split("\\s+");
|
||||
if (split == null || split.length != 2) throw new UnauthorizedException("Bearer");
|
||||
if (!split[0].equalsIgnoreCase("Bearer")) throw new UnauthorizedException("Bearer");
|
||||
tokenString = split[1];
|
||||
}
|
||||
return tokenString;
|
||||
}
|
||||
|
||||
try {
|
||||
AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getName());
|
||||
if (!token.isActive()) {
|
||||
throw new UnauthorizedException("token_expired");
|
||||
}
|
||||
|
||||
UserModel user = realm.getUserById(token.getSubject());
|
||||
if (user == null || !user.isEnabled()) {
|
||||
throw new UnauthorizedException("invalid_user");
|
||||
}
|
||||
|
||||
ClientModel client = null;
|
||||
if (token.getIssuedFor() != null) {
|
||||
client = realm.findClient(token.getIssuedFor());
|
||||
if (client == null || !client.isEnabled()) {
|
||||
throw new UnauthorizedException("invalid_user");
|
||||
}
|
||||
}
|
||||
|
||||
return new Auth(token, user, client);
|
||||
} catch (VerificationException e) {
|
||||
logger.error("Failed to verify token", e);
|
||||
throw new UnauthorizedException("invalid_token");
|
||||
}
|
||||
public UserModel authenticateBearerToken(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
|
||||
String tokenString = extractAuthorizationHeaderToken(headers);
|
||||
if (tokenString == null) return null;
|
||||
return verifyIdentityToken(realm, uriInfo, true, tokenString);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@ public class ApplianceBootstrap {
|
|||
ApplicationModel adminConsole = new ApplicationManager(manager).createApplication(realm, Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
adminConsole.setBaseUrl(contextPath + "/admin/index.html");
|
||||
adminConsole.setEnabled(true);
|
||||
adminConsole.setPublicClient(true);
|
||||
adminConsole.addRedirectUri(contextPath + "/admin/" + realm.getName() + "/console/*");
|
||||
|
||||
realm.setAuditListeners(Collections.singleton("jboss-logging"));
|
||||
|
||||
|
|
|
@ -155,6 +155,14 @@ public class AuthenticationManager {
|
|||
}
|
||||
|
||||
String tokenString = cookie.getValue();
|
||||
UserModel user = verifyIdentityToken(realm, uriInfo, checkActive, tokenString);
|
||||
if (user == null) {
|
||||
expireIdentityCookie(realm, uriInfo);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
protected UserModel verifyIdentityToken(RealmModel realm, UriInfo uriInfo, boolean checkActive, String tokenString) {
|
||||
try {
|
||||
AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getName(), checkActive);
|
||||
logger.info("identity token verified");
|
||||
|
@ -173,22 +181,19 @@ public class AuthenticationManager {
|
|||
|
||||
UserModel user = realm.getUserById(token.getSubject());
|
||||
if (user == null || !user.isEnabled() ) {
|
||||
logger.info("Unknown user in identity cookie");
|
||||
expireIdentityCookie(realm, uriInfo);
|
||||
logger.info("Unknown user in identity token");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (token.getIssuedAt() < user.getNotBefore()) {
|
||||
logger.info("Stale cookie");
|
||||
expireIdentityCookie(realm, uriInfo);
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
return user;
|
||||
} catch (VerificationException e) {
|
||||
logger.info("Failed to verify identity cookie", e);
|
||||
expireCookie(cookie.getName(), cookie.getPath());
|
||||
logger.info("Failed to verify identity token", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ public class AccountService {
|
|||
this.realm = realm;
|
||||
this.application = application;
|
||||
this.audit = audit;
|
||||
this.authManager = new AppAuthManager(providers, KEYCLOAK_ACCOUNT_IDENTITY_COOKIE, tokenManager);
|
||||
this.authManager = new AppAuthManager(providers);
|
||||
this.socialRequestManager = socialRequestManager;
|
||||
}
|
||||
|
||||
|
@ -148,8 +148,9 @@ public class AccountService {
|
|||
account = AccountLoader.load().createAccount(uriInfo).setRealm(realm);
|
||||
|
||||
boolean passwordUpdateSupported = false;
|
||||
auth = authManager.authenticate(realm, headers);
|
||||
if (auth != null) {
|
||||
UserModel user = authManager.authenticateRequest(realm, uriInfo, headers);
|
||||
if (user != null) {
|
||||
auth = new Auth(realm, user, application);
|
||||
account.setUser(auth.getUser());
|
||||
|
||||
AuthenticationLinkModel authLinkModel = realm.getAuthenticationLink(auth.getUser());
|
||||
|
@ -487,20 +488,19 @@ public class AccountService {
|
|||
redirectUri = redirectUri.resolve("?referrer=" + referrer);
|
||||
}
|
||||
|
||||
NewCookie cookie = authManager.createCookie(realm, application, code, Urls.accountBase(uriInfo.getBaseUri()).build(realm.getName()));
|
||||
return Response.status(302).cookie(cookie).location(redirectUri).build();
|
||||
return Response.status(302).location(redirectUri).build();
|
||||
} finally {
|
||||
authManager.expireCookie(Urls.accountBase(uriInfo.getBaseUri()).build(realm.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Path("logout")
|
||||
@GET
|
||||
public Response logout() {
|
||||
URI baseUri = Urls.accountBase(uriInfo.getBaseUri()).build(realm.getName());
|
||||
authManager.expireIdentityCookie(realm, uriInfo);
|
||||
authManager.expireCookie(baseUri);
|
||||
return Response.status(302).location(baseUri).build();
|
||||
URI redirect = Urls.accountBase(uriInfo.getBaseUri()).build(realm.getName());
|
||||
|
||||
return Response.status(302).location(
|
||||
TokenService.logoutUrl(uriInfo).queryParam("redirect_uri", redirect.toString()).build(realm.getName())
|
||||
).build();
|
||||
}
|
||||
|
||||
private Response login(String path) {
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
package org.keycloak.services.resources;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.models.Config;
|
||||
import org.keycloak.freemarker.Theme;
|
||||
import org.keycloak.freemarker.ThemeLoader;
|
||||
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
@Path("/admin")
|
||||
public class AdminResource {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AdminResource.class);
|
||||
|
||||
private static FileTypeMap mimeTypes = MimetypesFileTypeMap.getDefaultFileTypeMap();
|
||||
|
||||
@Context
|
||||
private UriInfo uriInfo;
|
||||
|
||||
@GET
|
||||
public Response getResource() throws URISyntaxException {
|
||||
String requestUri = uriInfo.getRequestUri().toString();
|
||||
if (!requestUri.endsWith("/")) {
|
||||
return Response.seeOther(new URI(requestUri + "/")).build();
|
||||
} else {
|
||||
return getResource("index.html");
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{path:.*}")
|
||||
public Response getResource(@PathParam("path") String path) {
|
||||
try {
|
||||
Theme theme = ThemeLoader.createTheme(Config.getThemeAdmin(), Theme.Type.ADMIN);
|
||||
InputStream resource = theme.getResourceAsStream(path);
|
||||
if (resource != null) {
|
||||
String contentType = mimeTypes.getContentType(path);
|
||||
return Response.ok(resource).type(contentType).build();
|
||||
} else {
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to get theme resource", e);
|
||||
return Response.serverError().build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -27,7 +27,7 @@ import org.keycloak.services.managers.BruteForceProtector;
|
|||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.SocialRequestManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
import org.keycloak.services.resources.admin.AdminService;
|
||||
import org.keycloak.services.resources.admin.AdminRoot;
|
||||
import org.keycloak.models.utils.ModelProviderUtils;
|
||||
import org.keycloak.timer.TimerProvider;
|
||||
import org.keycloak.timer.TimerProviderFactory;
|
||||
|
@ -82,11 +82,10 @@ public class KeycloakApplication extends Application {
|
|||
SocialRequestManager socialRequestManager = new SocialRequestManager();
|
||||
|
||||
singletons.add(new RealmsResource(tokenManager, socialRequestManager));
|
||||
singletons.add(new AdminService(tokenManager));
|
||||
singletons.add(new SocialResource(tokenManager, socialRequestManager));
|
||||
singletons.add(new AdminRoot(tokenManager));
|
||||
classes.add(SkeletonKeyContextResolver.class);
|
||||
classes.add(QRCodeResource.class);
|
||||
classes.add(AdminResource.class);
|
||||
classes.add(ThemeResource.class);
|
||||
classes.add(JsResource.class);
|
||||
classes.add(WelcomeResource.class);
|
||||
|
|
|
@ -4,7 +4,7 @@ import org.jboss.logging.Logger;
|
|||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.representations.idm.PublishedRealmRepresentation;
|
||||
import org.keycloak.services.resources.admin.AdminService;
|
||||
import org.keycloak.services.resources.admin.AdminRoot;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PathParam;
|
||||
|
@ -38,9 +38,9 @@ public class PublicRealmResource {
|
|||
public static PublishedRealmRepresentation realmRep(RealmModel realm, UriInfo uriInfo) {
|
||||
PublishedRealmRepresentation rep = new PublishedRealmRepresentation();
|
||||
rep.setRealm(realm.getName());
|
||||
rep.setTokenServiceUrl(TokenService.tokenServiceBaseUrl(uriInfo).build(realm.getId()).toString());
|
||||
rep.setAccountServiceUrl(AccountService.accountServiceBaseUrl(uriInfo).build(realm.getId()).toString());
|
||||
rep.setAdminApiUrl(AdminService.adminApiUrl(uriInfo).build(realm.getId()).toString());
|
||||
rep.setTokenServiceUrl(TokenService.tokenServiceBaseUrl(uriInfo).build(realm.getName()).toString());
|
||||
rep.setAccountServiceUrl(AccountService.accountServiceBaseUrl(uriInfo).build(realm.getName()).toString());
|
||||
rep.setAdminApiUrl(uriInfo.getBaseUriBuilder().path(AdminRoot.class).build().toString());
|
||||
rep.setPublicKeyPem(realm.getPublicKeyPem());
|
||||
rep.setNotBefore(realm.getNotBefore());
|
||||
return rep;
|
||||
|
|
|
@ -74,7 +74,6 @@ public class RealmsResource {
|
|||
public static UriBuilder accountUrl(UriBuilder base) {
|
||||
return base.path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
|
||||
}
|
||||
|
||||
@Path("{realm}/tokens")
|
||||
public TokenService getTokenService(final @PathParam("realm") String name) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
|
@ -124,13 +123,6 @@ public class RealmsResource {
|
|||
return realmResource;
|
||||
}
|
||||
|
||||
@Path("{realm}/admin/resources")
|
||||
public AdminResource adminResource() {
|
||||
AdminResource adminResource = new AdminResource();
|
||||
ResteasyProviderFactory.getInstance().injectProperties(adminResource);
|
||||
return adminResource;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ import java.util.Map.Entry;
|
|||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
@Path("/rest/social")
|
||||
@Path("/social")
|
||||
public class SocialResource {
|
||||
|
||||
protected static Logger logger = Logger.getLogger(SocialResource.class);
|
||||
|
|
|
@ -15,7 +15,7 @@ import java.io.InputStream;
|
|||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
@Path("/rest/theme")
|
||||
@Path("/theme")
|
||||
public class ThemeResource {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ThemeResource.class);
|
||||
|
|
285
services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
Executable file
285
services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
Executable file
|
@ -0,0 +1,285 @@
|
|||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.jboss.resteasy.spi.HttpResponse;
|
||||
import org.jboss.resteasy.spi.NotFoundException;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.jboss.resteasy.spi.UnauthorizedException;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.freemarker.Theme;
|
||||
import org.keycloak.freemarker.ThemeLoader;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.models.AdminRoles;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Config;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.services.managers.AppAuthManager;
|
||||
import org.keycloak.services.managers.ApplicationManager;
|
||||
import org.keycloak.services.managers.Auth;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
import org.keycloak.services.resources.RealmsResource;
|
||||
import org.keycloak.services.resources.TokenService;
|
||||
import org.keycloak.services.resources.flows.Flows;
|
||||
import org.keycloak.services.resources.flows.OAuthRedirect;
|
||||
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import javax.ws.rs.ext.Providers;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class AdminConsole {
|
||||
protected static final Logger logger = Logger.getLogger(AdminConsole.class);
|
||||
|
||||
@Context
|
||||
protected UriInfo uriInfo;
|
||||
|
||||
@Context
|
||||
protected HttpRequest request;
|
||||
|
||||
@Context
|
||||
protected HttpResponse response;
|
||||
|
||||
@Context
|
||||
protected KeycloakSession session;
|
||||
|
||||
/*
|
||||
@Context
|
||||
protected ResourceContext resourceContext;
|
||||
*/
|
||||
|
||||
@Context
|
||||
protected Providers providers;
|
||||
|
||||
@Context
|
||||
protected ProviderSession providerSession;
|
||||
|
||||
@Context
|
||||
protected KeycloakApplication keycloak;
|
||||
|
||||
protected AppAuthManager authManager;
|
||||
protected RealmModel realm;
|
||||
|
||||
public AdminConsole(RealmModel realm) {
|
||||
this.realm = realm;
|
||||
this.authManager = new AppAuthManager(providerSession);
|
||||
}
|
||||
|
||||
public static class WhoAmI {
|
||||
protected String userId;
|
||||
protected String realm;
|
||||
protected String displayName;
|
||||
|
||||
@JsonProperty("createRealm")
|
||||
protected boolean createRealm;
|
||||
@JsonProperty("realm_access")
|
||||
protected Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
|
||||
|
||||
public WhoAmI() {
|
||||
}
|
||||
|
||||
public WhoAmI(String userId, String realm, String displayName, boolean createRealm, Map<String, Set<String>> realmAccess) {
|
||||
this.userId = userId;
|
||||
this.realm = realm;
|
||||
this.displayName = displayName;
|
||||
this.createRealm = createRealm;
|
||||
this.realmAccess = realmAccess;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
public void setRealm(String realm) {
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public boolean isCreateRealm() {
|
||||
return createRealm;
|
||||
}
|
||||
|
||||
public void setCreateRealm(boolean createRealm) {
|
||||
this.createRealm = createRealm;
|
||||
}
|
||||
|
||||
public Map<String, Set<String>> getRealmAccess() {
|
||||
return realmAccess;
|
||||
}
|
||||
|
||||
public void setRealmAccess(Map<String, Set<String>> realmAccess) {
|
||||
this.realmAccess = realmAccess;
|
||||
}
|
||||
}
|
||||
|
||||
@Path("config")
|
||||
@GET
|
||||
@Produces("application/json")
|
||||
@NoCache
|
||||
public ApplicationManager.InstallationAdapterConfig config() {
|
||||
ApplicationModel consoleApp = realm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
if (consoleApp == null) {
|
||||
throw new NotFoundException("Could not find admin console application");
|
||||
}
|
||||
return new ApplicationManager().toInstallationRepresentation(realm, consoleApp, keycloak.getBaseUri(uriInfo));
|
||||
|
||||
}
|
||||
|
||||
@Path("whoami")
|
||||
@GET
|
||||
@Produces("application/json")
|
||||
@NoCache
|
||||
public Response whoAmI(final @Context HttpHeaders headers) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
UserModel user = authManager.authenticateBearerToken(realm, uriInfo, headers);
|
||||
if (user == null) {
|
||||
return Response.status(401).build();
|
||||
}
|
||||
String displayName;
|
||||
if (user.getFirstName() != null || user.getLastName() != null) {
|
||||
displayName = user.getFirstName();
|
||||
if (user.getLastName() != null) {
|
||||
displayName = displayName != null ? displayName + " " + user.getLastName() : user.getLastName();
|
||||
}
|
||||
} else {
|
||||
displayName = user.getLoginName();
|
||||
}
|
||||
|
||||
RealmModel masterRealm = getAdminstrationRealm(realmManager);
|
||||
if (masterRealm == null)
|
||||
throw new NotFoundException("No realm found");
|
||||
boolean createRealm = false;
|
||||
if (realm.equals(masterRealm)) {
|
||||
createRealm = masterRealm.hasRole(user, masterRealm.getRole(AdminRoles.CREATE_REALM));
|
||||
}
|
||||
|
||||
Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
|
||||
addRealmAdminAccess(realmAccess, realm.getRoleMappings(user));
|
||||
|
||||
return Response.ok(new WhoAmI(user.getId(), realm.getName(), displayName, createRealm, realmAccess)).build();
|
||||
}
|
||||
|
||||
private void addRealmAdminAccess(Map<String, Set<String>> realmAdminAccess, Set<RoleModel> roles) {
|
||||
for (RoleModel r : roles) {
|
||||
if (r.getContainer() instanceof ApplicationModel) {
|
||||
ApplicationModel app = (ApplicationModel) r.getContainer();
|
||||
if (app.getName().endsWith(AdminRoles.APP_SUFFIX)) {
|
||||
String realm = app.getName().substring(0, app.getName().length() - AdminRoles.APP_SUFFIX.length());
|
||||
if (!realmAdminAccess.containsKey(realm)) {
|
||||
realmAdminAccess.put(realm, new HashSet<String>());
|
||||
}
|
||||
realmAdminAccess.get(realm).add(r.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (r.isComposite()) {
|
||||
addRealmAdminAccess(realmAdminAccess, r.getComposites());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Path("logout")
|
||||
@GET
|
||||
@NoCache
|
||||
public Response logout() {
|
||||
URI redirect = AdminRoot.adminConsoleUrl(uriInfo).path("index.html").build(realm.getName());
|
||||
|
||||
return Response.status(302).location(
|
||||
TokenService.logoutUrl(uriInfo).queryParam("redirect_uri", redirect.toString()).build(realm.getName())
|
||||
).build();
|
||||
}
|
||||
|
||||
protected RealmModel getAdminstrationRealm(RealmManager realmManager) {
|
||||
return realmManager.getKeycloakAdminstrationRealm();
|
||||
}
|
||||
|
||||
private static FileTypeMap mimeTypes = MimetypesFileTypeMap.getDefaultFileTypeMap();
|
||||
|
||||
@GET
|
||||
public Response getMainPage() throws URISyntaxException {
|
||||
return Response.status(302).location(
|
||||
AdminRoot.adminConsoleUrl(uriInfo).path("index.html").build(realm.getName())
|
||||
).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("js/keycloak.js")
|
||||
@Produces("text/javascript")
|
||||
public Response getKeycloakJs() {
|
||||
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("keycloak.js");
|
||||
if (inputStream != null) {
|
||||
return Response.ok(inputStream).build();
|
||||
} else {
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("{path:.+}")
|
||||
public Response getResource(@PathParam("path") String path) {
|
||||
try {
|
||||
Theme theme = ThemeLoader.createTheme(Config.getThemeAdmin(), Theme.Type.ADMIN);
|
||||
InputStream resource = theme.getResourceAsStream(path);
|
||||
if (resource != null) {
|
||||
String contentType = mimeTypes.getContentType(path);
|
||||
return Response.ok(resource).type(contentType).build();
|
||||
} else {
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to get theme resource", e);
|
||||
return Response.serverError().build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
162
services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
Executable file
162
services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
Executable file
|
@ -0,0 +1,162 @@
|
|||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.spi.NotFoundException;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.jboss.resteasy.spi.UnauthorizedException;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.services.managers.AppAuthManager;
|
||||
import org.keycloak.services.managers.Auth;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@Path("/admin")
|
||||
public class AdminRoot {
|
||||
protected static final Logger logger = Logger.getLogger(AdminRoot.class);
|
||||
|
||||
@Context
|
||||
protected UriInfo uriInfo;
|
||||
|
||||
protected AppAuthManager authManager;
|
||||
protected TokenManager tokenManager;
|
||||
|
||||
@Context
|
||||
protected KeycloakSession session;
|
||||
|
||||
public AdminRoot(TokenManager tokenManager) {
|
||||
this.tokenManager = tokenManager;
|
||||
this.authManager = new AppAuthManager(null);
|
||||
}
|
||||
|
||||
public static UriBuilder adminBaseUrl(UriInfo uriInfo) {
|
||||
return adminBaseUrl(uriInfo.getBaseUriBuilder());
|
||||
}
|
||||
|
||||
public static UriBuilder adminBaseUrl(UriBuilder base) {
|
||||
return base.path(AdminRoot.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GET
|
||||
public Response masterRealmAdminConsoleRedirect() {
|
||||
RealmModel master = new RealmManager(session).getKeycloakAdminstrationRealm();
|
||||
return Response.status(302).location(
|
||||
uriInfo.getBaseUriBuilder().path(AdminRoot.class).path(AdminRoot.class, "getAdminConsole").path("index.html").build(master.getName())
|
||||
).build();
|
||||
}
|
||||
|
||||
@Path("index.html")
|
||||
@GET
|
||||
public Response masterRealmAdminConsoleRedirectHtml() {
|
||||
return masterRealmAdminConsoleRedirect();
|
||||
}
|
||||
|
||||
protected RealmModel locateRealm(String name, RealmManager realmManager) {
|
||||
RealmModel realm = realmManager.getRealmByName(name);
|
||||
if (realm == null) {
|
||||
throw new NotFoundException("Realm " + name + " not found");
|
||||
}
|
||||
return realm;
|
||||
}
|
||||
|
||||
|
||||
public static UriBuilder adminConsoleUrl(UriInfo uriInfo) {
|
||||
return adminConsoleUrl(uriInfo.getBaseUriBuilder());
|
||||
}
|
||||
|
||||
public static UriBuilder adminConsoleUrl(UriBuilder base) {
|
||||
return adminBaseUrl(base).path(AdminRoot.class, "getAdminConsole");
|
||||
}
|
||||
|
||||
@Path("{realm}/console")
|
||||
public AdminConsole getAdminConsole(final @PathParam("realm") String name) {
|
||||
logger.info("*** get console for realm: " + name);
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = locateRealm(name, realmManager);
|
||||
AdminConsole service = new AdminConsole(realm);
|
||||
ResteasyProviderFactory.getInstance().injectProperties(service);
|
||||
logger.info("returning AdminConsole");
|
||||
return service;
|
||||
}
|
||||
|
||||
|
||||
protected Auth authenticateRealmAdminRequest(HttpHeaders headers) {
|
||||
String tokenString = authManager.extractAuthorizationHeaderToken(headers);
|
||||
if (tokenString == null) throw new UnauthorizedException("Bearer");
|
||||
JWSInput input = new JWSInput(tokenString);
|
||||
AccessToken token;
|
||||
try {
|
||||
token = input.readJsonContent(AccessToken.class);
|
||||
} catch (IOException e) {
|
||||
throw new UnauthorizedException("Bearer token format error");
|
||||
}
|
||||
String realmName = token.getAudience();
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = realmManager.getRealmByName(realmName);
|
||||
if (realm == null) {
|
||||
throw new UnauthorizedException("Unknown realm in token");
|
||||
}
|
||||
UserModel user = authManager.authenticateBearerToken(realm, uriInfo, headers);
|
||||
if (user == null) {
|
||||
logger.debug("Token not valid");
|
||||
throw new UnauthorizedException("Bearer");
|
||||
}
|
||||
|
||||
ApplicationModel consoleApp = realm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
if (consoleApp == null) {
|
||||
throw new NotFoundException("Could not find admin console application");
|
||||
}
|
||||
Auth auth = new Auth(realm, user, consoleApp);
|
||||
return auth;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static UriBuilder realmsUrl(UriInfo uriInfo) {
|
||||
return realmsUrl(uriInfo.getBaseUriBuilder());
|
||||
}
|
||||
|
||||
public static UriBuilder realmsUrl(UriBuilder base) {
|
||||
return adminBaseUrl(base).path(AdminRoot.class, "getRealmsAdmin");
|
||||
}
|
||||
|
||||
@Path("realms")
|
||||
public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
|
||||
Auth auth = authenticateRealmAdminRequest(headers);
|
||||
RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager);
|
||||
ResteasyProviderFactory.getInstance().injectProperties(adminResource);
|
||||
//resourceContext.initResource(adminResource);
|
||||
return adminResource;
|
||||
}
|
||||
|
||||
@Path("serverinfo")
|
||||
public ServerInfoAdminResource getServerInfo(@Context final HttpHeaders headers) {
|
||||
ServerInfoAdminResource adminResource = new ServerInfoAdminResource();
|
||||
ResteasyProviderFactory.getInstance().injectProperties(adminResource);
|
||||
//resourceContext.initResource(adminResource);
|
||||
return adminResource;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,409 +0,0 @@
|
|||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.jboss.resteasy.spi.HttpResponse;
|
||||
import org.jboss.resteasy.spi.NotFoundException;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.jboss.resteasy.spi.UnauthorizedException;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.models.AdminRoles;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Config;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.services.managers.AppAuthManager;
|
||||
import org.keycloak.services.managers.Auth;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
import org.keycloak.services.resources.TokenService;
|
||||
import org.keycloak.services.resources.flows.Flows;
|
||||
import org.keycloak.services.resources.flows.OAuthRedirect;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
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.ext.Providers;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@Path("/rest/admin")
|
||||
public class AdminService {
|
||||
protected static final Logger logger = Logger.getLogger(AdminService.class);
|
||||
|
||||
@Context
|
||||
protected UriInfo uriInfo;
|
||||
|
||||
@Context
|
||||
protected HttpRequest request;
|
||||
|
||||
@Context
|
||||
protected HttpResponse response;
|
||||
|
||||
@Context
|
||||
protected KeycloakSession session;
|
||||
|
||||
/*
|
||||
@Context
|
||||
protected ResourceContext resourceContext;
|
||||
*/
|
||||
|
||||
@Context
|
||||
protected Providers providers;
|
||||
|
||||
@Context
|
||||
protected ProviderSession providerSession;
|
||||
|
||||
protected String adminPath = "/admin/";
|
||||
protected AppAuthManager authManager;
|
||||
protected TokenManager tokenManager;
|
||||
|
||||
public AdminService(TokenManager tokenManager) {
|
||||
this.tokenManager = tokenManager;
|
||||
this.authManager = new AppAuthManager(providerSession, "KEYCLOAK_ADMIN_CONSOLE_IDENTITY", tokenManager);
|
||||
}
|
||||
|
||||
public static UriBuilder adminApiUrl(UriInfo uriInfo) {
|
||||
UriBuilder base = uriInfo.getBaseUriBuilder().path(AdminService.class).path(AdminService.class, "getRealmsAdmin").path(RealmsAdminResource.class, "getRealmAdmin");
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
public static class WhoAmI {
|
||||
protected String userId;
|
||||
protected String realm;
|
||||
protected String displayName;
|
||||
|
||||
@JsonProperty("createRealm")
|
||||
protected boolean createRealm;
|
||||
@JsonProperty("realm_access")
|
||||
protected Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
|
||||
|
||||
public WhoAmI() {
|
||||
}
|
||||
|
||||
public WhoAmI(String userId, String realm, String displayName, boolean createRealm, Map<String, Set<String>> realmAccess) {
|
||||
this.userId = userId;
|
||||
this.realm = realm;
|
||||
this.displayName = displayName;
|
||||
this.createRealm = createRealm;
|
||||
this.realmAccess = realmAccess;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
public void setRealm(String realm) {
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public boolean isCreateRealm() {
|
||||
return createRealm;
|
||||
}
|
||||
|
||||
public void setCreateRealm(boolean createRealm) {
|
||||
this.createRealm = createRealm;
|
||||
}
|
||||
|
||||
public Map<String, Set<String>> getRealmAccess() {
|
||||
return realmAccess;
|
||||
}
|
||||
|
||||
public void setRealmAccess(Map<String, Set<String>> realmAccess) {
|
||||
this.realmAccess = realmAccess;
|
||||
}
|
||||
}
|
||||
|
||||
@Path("keepalive")
|
||||
@GET
|
||||
@NoCache
|
||||
public Response keepalive(final @Context HttpHeaders headers) {
|
||||
logger.debug("keepalive");
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = getAdminstrationRealm(realmManager);
|
||||
if (realm == null)
|
||||
throw new NotFoundException("No realm found");
|
||||
Auth auth = authManager.authenticateCookie(realm, headers);
|
||||
if (auth == null) {
|
||||
return Response.status(401).build();
|
||||
}
|
||||
NewCookie refreshCookie = authManager.createRefreshCookie(realm, auth.getUser(), auth.getClient(), AdminService.saasCookiePath(uriInfo).build());
|
||||
return Response.noContent().cookie(refreshCookie).build();
|
||||
}
|
||||
|
||||
@Path("whoami")
|
||||
@GET
|
||||
@Produces("application/json")
|
||||
@NoCache
|
||||
public Response whoAmI(final @Context HttpHeaders headers) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = getAdminstrationRealm(realmManager);
|
||||
if (realm == null)
|
||||
throw new NotFoundException("No realm found");
|
||||
Auth auth = authManager.authenticateCookie(realm, headers);
|
||||
if (auth == null) {
|
||||
logger.debug("No auth cookie");
|
||||
return Response.status(401).build();
|
||||
}
|
||||
UserModel user = auth.getUser();
|
||||
if (user == null) {
|
||||
return Response.status(401).build();
|
||||
}
|
||||
|
||||
String displayName;
|
||||
if (user.getFirstName() != null || user.getLastName() != null) {
|
||||
displayName = user.getFirstName();
|
||||
if (user.getLastName() != null) {
|
||||
displayName = displayName != null ? displayName + " " + user.getLastName() : user.getLastName();
|
||||
}
|
||||
} else {
|
||||
displayName = user.getLoginName();
|
||||
}
|
||||
|
||||
boolean createRealm = realm.hasRole(user, realm.getRole(AdminRoles.CREATE_REALM));
|
||||
|
||||
Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
|
||||
addRealmAdminAccess(realmAccess, auth.getRealm().getRoleMappings(auth.getUser()));
|
||||
|
||||
return Response.ok(new WhoAmI(user.getId(), Config.getAdminRealm(), displayName, createRealm, realmAccess)).build();
|
||||
}
|
||||
|
||||
private void addRealmAdminAccess(Map<String, Set<String>> realmAdminAccess, Set<RoleModel> roles) {
|
||||
for (RoleModel r : roles) {
|
||||
if (r.getContainer() instanceof ApplicationModel) {
|
||||
ApplicationModel app = (ApplicationModel) r.getContainer();
|
||||
if (app.getName().endsWith(AdminRoles.APP_SUFFIX)) {
|
||||
String realm = app.getName().substring(0, app.getName().length() - AdminRoles.APP_SUFFIX.length());
|
||||
if (!realmAdminAccess.containsKey(realm)) {
|
||||
realmAdminAccess.put(realm, new HashSet<String>());
|
||||
}
|
||||
realmAdminAccess.get(realm).add(r.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (r.isComposite()) {
|
||||
addRealmAdminAccess(realmAdminAccess, r.getComposites());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Path("isLoggedIn.js")
|
||||
@GET
|
||||
@Produces("application/javascript")
|
||||
@NoCache
|
||||
public String isLoggedIn(final @Context HttpHeaders headers) {
|
||||
logger.debug("WHOAMI Javascript start.");
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = getAdminstrationRealm(realmManager);
|
||||
if (realm == null) {
|
||||
return "var keycloakCookieLoggedIn = false;";
|
||||
|
||||
}
|
||||
UserModel user = authManager.authenticateCookie(realm, headers).getUser();
|
||||
if (user == null) {
|
||||
return "var keycloakCookieLoggedIn = false;";
|
||||
}
|
||||
logger.debug("WHOAMI: " + user.getLoginName());
|
||||
return "var keycloakCookieLoggedIn = true;";
|
||||
}
|
||||
|
||||
public static UriBuilder contextRoot(UriInfo uriInfo) {
|
||||
return UriBuilder.fromUri(uriInfo.getBaseUri()).replacePath("/auth");
|
||||
}
|
||||
|
||||
public static UriBuilder saasCookiePath(UriInfo uriInfo) {
|
||||
return UriBuilder.fromUri(uriInfo.getBaseUri()).path(AdminService.class);
|
||||
}
|
||||
|
||||
@Path("realms")
|
||||
public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel adminRealm = getAdminstrationRealm(realmManager);
|
||||
if (adminRealm == null)
|
||||
throw new NotFoundException("Admin realm not found");
|
||||
Auth auth = authManager.authenticate(adminRealm, headers);
|
||||
if (auth == null) {
|
||||
throw new UnauthorizedException("Bearer");
|
||||
}
|
||||
|
||||
RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager);
|
||||
ResteasyProviderFactory.getInstance().injectProperties(adminResource);
|
||||
//resourceContext.initResource(adminResource);
|
||||
return adminResource;
|
||||
}
|
||||
|
||||
@Path("serverinfo")
|
||||
public ServerInfoAdminResource getServerInfo(@Context final HttpHeaders headers) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel adminRealm = getAdminstrationRealm(realmManager);
|
||||
if (adminRealm == null)
|
||||
throw new NotFoundException("Admin realm not found");
|
||||
Auth auth = authManager.authenticate(adminRealm, headers);
|
||||
UserModel admin = auth.getUser();
|
||||
if (admin == null) {
|
||||
throw new UnauthorizedException("Bearer");
|
||||
}
|
||||
ApplicationModel adminConsole = adminRealm.getApplicationNameMap().get(Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
if (adminConsole == null) {
|
||||
throw new NotFoundException("Admin console application not found");
|
||||
}
|
||||
ServerInfoAdminResource adminResource = new ServerInfoAdminResource();
|
||||
ResteasyProviderFactory.getInstance().injectProperties(adminResource);
|
||||
//resourceContext.initResource(adminResource);
|
||||
return adminResource;
|
||||
}
|
||||
|
||||
private void expireCookie() {
|
||||
authManager.expireCookie(AdminService.saasCookiePath(uriInfo).build());
|
||||
}
|
||||
|
||||
@Path("login")
|
||||
@GET
|
||||
@NoCache
|
||||
public Response loginPage(@QueryParam("path") String path) {
|
||||
logger.debug("loginPage ********************** <---");
|
||||
expireCookie();
|
||||
|
||||
OAuthRedirect oauth = new OAuthRedirect();
|
||||
String authUrl = TokenService.loginPageUrl(uriInfo).build(Config.getAdminRealm()).toString();
|
||||
logger.debugv("authUrl: {0}", authUrl);
|
||||
oauth.setAuthUrl(authUrl);
|
||||
oauth.setClientId(Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
|
||||
UriBuilder redirectBuilder = uriInfo.getBaseUriBuilder().path(AdminService.class).path(AdminService.class, "loginRedirect");
|
||||
if (path != null) {
|
||||
redirectBuilder.queryParam("path", path);
|
||||
}
|
||||
URI redirectUri = redirectBuilder.build();
|
||||
logger.debugv("redirectUri: {0}", redirectUri.toString());
|
||||
oauth.setStateCookiePath(redirectUri.getRawPath());
|
||||
return oauth.redirect(uriInfo, redirectUri.toString());
|
||||
}
|
||||
|
||||
@Path("login-error")
|
||||
@GET
|
||||
@NoCache
|
||||
public Response errorOnLoginRedirect(@QueryParam ("error") String message) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = getAdminstrationRealm(realmManager);
|
||||
return Flows.forms(realm, uriInfo).setError(message).createErrorPage();
|
||||
}
|
||||
|
||||
protected Response redirectOnLoginError(String message) {
|
||||
URI uri = uriInfo.getBaseUriBuilder().path(AdminService.class).path(AdminService.class, "errorOnLoginRedirect").queryParam(OAuth2Constants.ERROR, message).build();
|
||||
URI logout = TokenService.logoutUrl(uriInfo).queryParam(OAuth2Constants.REDIRECT_URI, uri.toString()).build(Config.getAdminRealm());
|
||||
return Response.status(302).location(logout).build();
|
||||
}
|
||||
|
||||
@Path("login-redirect")
|
||||
@GET
|
||||
@NoCache
|
||||
public Response loginRedirect(@QueryParam("code") String code,
|
||||
@QueryParam("state") String state,
|
||||
@QueryParam("error") String error,
|
||||
@QueryParam("path") String path,
|
||||
@Context HttpHeaders headers
|
||||
|
||||
) {
|
||||
try {
|
||||
logger.info("loginRedirect ********************** <---");
|
||||
if (error != null) {
|
||||
logger.debug("error from oauth");
|
||||
return redirectOnLoginError(error);
|
||||
}
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel adminRealm = getAdminstrationRealm(realmManager);
|
||||
if (!adminRealm.isEnabled()) {
|
||||
logger.debug("realm not enabled");
|
||||
return redirectOnLoginError("realm not enabled");
|
||||
}
|
||||
ApplicationModel adminConsole = adminRealm.getApplicationNameMap().get(Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
if (!adminConsole.isEnabled()) {
|
||||
logger.debug("admin app not enabled");
|
||||
return redirectOnLoginError("admin app not enabled");
|
||||
}
|
||||
|
||||
if (code == null) {
|
||||
logger.debug("code not specified");
|
||||
return redirectOnLoginError("invalid login data");
|
||||
}
|
||||
if (state == null) {
|
||||
logger.debug("state not specified");
|
||||
return redirectOnLoginError("invalid login data");
|
||||
}
|
||||
new OAuthRedirect().checkStateCookie(uriInfo, headers);
|
||||
|
||||
logger.debug("loginRedirect SUCCESS");
|
||||
NewCookie cookie = authManager.createCookie(adminRealm, adminConsole, code, AdminService.saasCookiePath(uriInfo).build());
|
||||
|
||||
URI redirectUri = UriBuilder.fromUri(uriInfo.getBaseUri()).path(adminPath).build();
|
||||
if (path != null) {
|
||||
redirectUri = redirectUri.resolve("#" + UriBuilder.fromPath(path).build().toString());
|
||||
}
|
||||
return Response.status(302).cookie(cookie).location(redirectUri).build();
|
||||
} finally {
|
||||
expireCookie();
|
||||
}
|
||||
}
|
||||
|
||||
@Path("logout")
|
||||
@GET
|
||||
@NoCache
|
||||
public Response logout() {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = getAdminstrationRealm(realmManager);
|
||||
expireCookie();
|
||||
authManager.expireIdentityCookie(realm, uriInfo);
|
||||
|
||||
return Response.status(302).location(uriInfo.getBaseUriBuilder().path(AdminService.class).path(AdminService.class, "loginPage").build()).build();
|
||||
}
|
||||
|
||||
@Path("logout-cookie")
|
||||
@GET
|
||||
@NoCache
|
||||
public void logoutCookie() {
|
||||
logger.debug("*** logoutCookie");
|
||||
expireCookie();
|
||||
}
|
||||
|
||||
protected RealmModel getAdminstrationRealm(RealmManager realmManager) {
|
||||
return realmManager.getKeycloakAdminstrationRealm();
|
||||
}
|
||||
}
|
|
@ -1,410 +0,0 @@
|
|||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.jboss.resteasy.spi.HttpResponse;
|
||||
import org.jboss.resteasy.spi.NotFoundException;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.jboss.resteasy.spi.UnauthorizedException;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.models.AdminRoles;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Config;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
import org.keycloak.services.managers.AppAuthManager;
|
||||
import org.keycloak.services.managers.Auth;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
import org.keycloak.services.resources.TokenService;
|
||||
import org.keycloak.services.resources.flows.Flows;
|
||||
import org.keycloak.services.resources.flows.OAuthRedirect;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
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.ext.Providers;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ConsoleLogin {
|
||||
protected static final Logger logger = Logger.getLogger(ConsoleLogin.class);
|
||||
|
||||
@Context
|
||||
protected UriInfo uriInfo;
|
||||
|
||||
@Context
|
||||
protected HttpRequest request;
|
||||
|
||||
@Context
|
||||
protected HttpResponse response;
|
||||
|
||||
@Context
|
||||
protected KeycloakSession session;
|
||||
|
||||
/*
|
||||
@Context
|
||||
protected ResourceContext resourceContext;
|
||||
*/
|
||||
|
||||
@Context
|
||||
protected Providers providers;
|
||||
|
||||
@Context
|
||||
protected ProviderSession providerSession;
|
||||
|
||||
protected String adminPath = "/admin/";
|
||||
protected AppAuthManager authManager;
|
||||
protected TokenManager tokenManager;
|
||||
protected RealmModel realm;
|
||||
|
||||
public ConsoleLogin(TokenManager tokenManager, RealmModel realm) {
|
||||
this.realm = realm;
|
||||
this.tokenManager = tokenManager;
|
||||
this.authManager = new AppAuthManager(providerSession, "KEYCLOAK_ADMIN_CONSOLE_IDENTITY", tokenManager);
|
||||
}
|
||||
|
||||
public static UriBuilder adminApiUrl(UriInfo uriInfo) {
|
||||
UriBuilder base = uriInfo.getBaseUriBuilder().path(ConsoleLogin.class).path(ConsoleLogin.class, "getRealmsAdmin").path(RealmsAdminResource.class, "getRealmAdmin");
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
public static class WhoAmI {
|
||||
protected String userId;
|
||||
protected String realm;
|
||||
protected String displayName;
|
||||
|
||||
@JsonProperty("createRealm")
|
||||
protected boolean createRealm;
|
||||
@JsonProperty("realm_access")
|
||||
protected Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
|
||||
|
||||
public WhoAmI() {
|
||||
}
|
||||
|
||||
public WhoAmI(String userId, String realm, String displayName, boolean createRealm, Map<String, Set<String>> realmAccess) {
|
||||
this.userId = userId;
|
||||
this.realm = realm;
|
||||
this.displayName = displayName;
|
||||
this.createRealm = createRealm;
|
||||
this.realmAccess = realmAccess;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
public void setRealm(String realm) {
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public boolean isCreateRealm() {
|
||||
return createRealm;
|
||||
}
|
||||
|
||||
public void setCreateRealm(boolean createRealm) {
|
||||
this.createRealm = createRealm;
|
||||
}
|
||||
|
||||
public Map<String, Set<String>> getRealmAccess() {
|
||||
return realmAccess;
|
||||
}
|
||||
|
||||
public void setRealmAccess(Map<String, Set<String>> realmAccess) {
|
||||
this.realmAccess = realmAccess;
|
||||
}
|
||||
}
|
||||
|
||||
@Path("keepalive")
|
||||
@GET
|
||||
@NoCache
|
||||
public Response keepalive(final @Context HttpHeaders headers) {
|
||||
logger.debug("keepalive");
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = getAdminstrationRealm(realmManager);
|
||||
if (realm == null)
|
||||
throw new NotFoundException("No realm found");
|
||||
Auth auth = authManager.authenticateCookie(realm, headers);
|
||||
if (auth == null) {
|
||||
return Response.status(401).build();
|
||||
}
|
||||
NewCookie refreshCookie = authManager.createRefreshCookie(realm, auth.getUser(), auth.getClient(), ConsoleLogin.saasCookiePath(uriInfo).build());
|
||||
return Response.noContent().cookie(refreshCookie).build();
|
||||
}
|
||||
|
||||
@Path("whoami")
|
||||
@GET
|
||||
@Produces("application/json")
|
||||
@NoCache
|
||||
public Response whoAmI(final @Context HttpHeaders headers) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = getAdminstrationRealm(realmManager);
|
||||
if (realm == null)
|
||||
throw new NotFoundException("No realm found");
|
||||
Auth auth = authManager.authenticateCookie(realm, headers);
|
||||
if (auth == null) {
|
||||
logger.debug("No auth cookie");
|
||||
return Response.status(401).build();
|
||||
}
|
||||
UserModel user = auth.getUser();
|
||||
if (user == null) {
|
||||
return Response.status(401).build();
|
||||
}
|
||||
|
||||
String displayName;
|
||||
if (user.getFirstName() != null || user.getLastName() != null) {
|
||||
displayName = user.getFirstName();
|
||||
if (user.getLastName() != null) {
|
||||
displayName = displayName != null ? displayName + " " + user.getLastName() : user.getLastName();
|
||||
}
|
||||
} else {
|
||||
displayName = user.getLoginName();
|
||||
}
|
||||
|
||||
boolean createRealm = realm.hasRole(user, realm.getRole(AdminRoles.CREATE_REALM));
|
||||
|
||||
Map<String, Set<String>> realmAccess = new HashMap<String, Set<String>>();
|
||||
addRealmAdminAccess(realmAccess, auth.getRealm().getRoleMappings(auth.getUser()));
|
||||
|
||||
return Response.ok(new WhoAmI(user.getId(), Config.getAdminRealm(), displayName, createRealm, realmAccess)).build();
|
||||
}
|
||||
|
||||
private void addRealmAdminAccess(Map<String, Set<String>> realmAdminAccess, Set<RoleModel> roles) {
|
||||
for (RoleModel r : roles) {
|
||||
if (r.getContainer() instanceof ApplicationModel) {
|
||||
ApplicationModel app = (ApplicationModel) r.getContainer();
|
||||
if (app.getName().endsWith(AdminRoles.APP_SUFFIX)) {
|
||||
String realm = app.getName().substring(0, app.getName().length() - AdminRoles.APP_SUFFIX.length());
|
||||
if (!realmAdminAccess.containsKey(realm)) {
|
||||
realmAdminAccess.put(realm, new HashSet<String>());
|
||||
}
|
||||
realmAdminAccess.get(realm).add(r.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (r.isComposite()) {
|
||||
addRealmAdminAccess(realmAdminAccess, r.getComposites());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Path("isLoggedIn.js")
|
||||
@GET
|
||||
@Produces("application/javascript")
|
||||
@NoCache
|
||||
public String isLoggedIn(final @Context HttpHeaders headers) {
|
||||
logger.debug("WHOAMI Javascript start.");
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = getAdminstrationRealm(realmManager);
|
||||
if (realm == null) {
|
||||
return "var keycloakCookieLoggedIn = false;";
|
||||
|
||||
}
|
||||
UserModel user = authManager.authenticateCookie(realm, headers).getUser();
|
||||
if (user == null) {
|
||||
return "var keycloakCookieLoggedIn = false;";
|
||||
}
|
||||
logger.debug("WHOAMI: " + user.getLoginName());
|
||||
return "var keycloakCookieLoggedIn = true;";
|
||||
}
|
||||
|
||||
public static UriBuilder contextRoot(UriInfo uriInfo) {
|
||||
return UriBuilder.fromUri(uriInfo.getBaseUri()).replacePath("/auth");
|
||||
}
|
||||
|
||||
public static UriBuilder saasCookiePath(UriInfo uriInfo) {
|
||||
return UriBuilder.fromUri(uriInfo.getBaseUri()).path(ConsoleLogin.class);
|
||||
}
|
||||
|
||||
@Path("realms")
|
||||
public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel adminRealm = getAdminstrationRealm(realmManager);
|
||||
if (adminRealm == null)
|
||||
throw new NotFoundException("Admin realm not found");
|
||||
Auth auth = authManager.authenticate(adminRealm, headers);
|
||||
if (auth == null) {
|
||||
throw new UnauthorizedException("Bearer");
|
||||
}
|
||||
|
||||
RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager);
|
||||
ResteasyProviderFactory.getInstance().injectProperties(adminResource);
|
||||
//resourceContext.initResource(adminResource);
|
||||
return adminResource;
|
||||
}
|
||||
|
||||
@Path("serverinfo")
|
||||
public ServerInfoAdminResource getServerInfo(@Context final HttpHeaders headers) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel adminRealm = getAdminstrationRealm(realmManager);
|
||||
if (adminRealm == null)
|
||||
throw new NotFoundException("Admin realm not found");
|
||||
Auth auth = authManager.authenticate(adminRealm, headers);
|
||||
UserModel admin = auth.getUser();
|
||||
if (admin == null) {
|
||||
throw new UnauthorizedException("Bearer");
|
||||
}
|
||||
ApplicationModel adminConsole = adminRealm.getApplicationNameMap().get(Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
if (adminConsole == null) {
|
||||
throw new NotFoundException("Admin console application not found");
|
||||
}
|
||||
ServerInfoAdminResource adminResource = new ServerInfoAdminResource();
|
||||
ResteasyProviderFactory.getInstance().injectProperties(adminResource);
|
||||
//resourceContext.initResource(adminResource);
|
||||
return adminResource;
|
||||
}
|
||||
|
||||
private void expireCookie() {
|
||||
authManager.expireCookie(ConsoleLogin.saasCookiePath(uriInfo).build());
|
||||
}
|
||||
|
||||
@Path("login")
|
||||
@GET
|
||||
@NoCache
|
||||
public Response loginPage(@QueryParam("path") String path) {
|
||||
logger.debug("loginPage ********************** <---");
|
||||
expireCookie();
|
||||
|
||||
OAuthRedirect oauth = new OAuthRedirect();
|
||||
String authUrl = TokenService.loginPageUrl(uriInfo).build(Config.getAdminRealm()).toString();
|
||||
logger.debugv("authUrl: {0}", authUrl);
|
||||
oauth.setAuthUrl(authUrl);
|
||||
oauth.setClientId(Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
|
||||
UriBuilder redirectBuilder = uriInfo.getBaseUriBuilder().path(ConsoleLogin.class).path(ConsoleLogin.class, "loginRedirect");
|
||||
if (path != null) {
|
||||
redirectBuilder.queryParam("path", path);
|
||||
}
|
||||
URI redirectUri = redirectBuilder.build();
|
||||
logger.debugv("redirectUri: {0}", redirectUri.toString());
|
||||
oauth.setStateCookiePath(redirectUri.getRawPath());
|
||||
return oauth.redirect(uriInfo, redirectUri.toString());
|
||||
}
|
||||
|
||||
@Path("login-error")
|
||||
@GET
|
||||
@NoCache
|
||||
public Response errorOnLoginRedirect(@QueryParam ("error") String message) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = getAdminstrationRealm(realmManager);
|
||||
return Flows.forms(realm, uriInfo).setError(message).createErrorPage();
|
||||
}
|
||||
|
||||
protected Response redirectOnLoginError(String message) {
|
||||
URI uri = uriInfo.getBaseUriBuilder().path(ConsoleLogin.class).path(ConsoleLogin.class, "errorOnLoginRedirect").queryParam(OAuth2Constants.ERROR, message).build();
|
||||
URI logout = TokenService.logoutUrl(uriInfo).queryParam(OAuth2Constants.REDIRECT_URI, uri.toString()).build(Config.getAdminRealm());
|
||||
return Response.status(302).location(logout).build();
|
||||
}
|
||||
|
||||
@Path("login-redirect")
|
||||
@GET
|
||||
@NoCache
|
||||
public Response loginRedirect(@QueryParam("code") String code,
|
||||
@QueryParam("state") String state,
|
||||
@QueryParam("error") String error,
|
||||
@QueryParam("path") String path,
|
||||
@Context HttpHeaders headers
|
||||
|
||||
) {
|
||||
try {
|
||||
logger.info("loginRedirect ********************** <---");
|
||||
if (error != null) {
|
||||
logger.debug("error from oauth");
|
||||
return redirectOnLoginError(error);
|
||||
}
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel adminRealm = getAdminstrationRealm(realmManager);
|
||||
if (!adminRealm.isEnabled()) {
|
||||
logger.debug("realm not enabled");
|
||||
return redirectOnLoginError("realm not enabled");
|
||||
}
|
||||
ApplicationModel adminConsole = adminRealm.getApplicationNameMap().get(Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
if (!adminConsole.isEnabled()) {
|
||||
logger.debug("admin app not enabled");
|
||||
return redirectOnLoginError("admin app not enabled");
|
||||
}
|
||||
|
||||
if (code == null) {
|
||||
logger.debug("code not specified");
|
||||
return redirectOnLoginError("invalid login data");
|
||||
}
|
||||
if (state == null) {
|
||||
logger.debug("state not specified");
|
||||
return redirectOnLoginError("invalid login data");
|
||||
}
|
||||
new OAuthRedirect().checkStateCookie(uriInfo, headers);
|
||||
|
||||
logger.debug("loginRedirect SUCCESS");
|
||||
NewCookie cookie = authManager.createCookie(adminRealm, adminConsole, code, ConsoleLogin.saasCookiePath(uriInfo).build());
|
||||
|
||||
URI redirectUri = UriBuilder.fromUri(uriInfo.getBaseUri()).path(adminPath).build();
|
||||
if (path != null) {
|
||||
redirectUri = redirectUri.resolve("#" + UriBuilder.fromPath(path).build().toString());
|
||||
}
|
||||
return Response.status(302).cookie(cookie).location(redirectUri).build();
|
||||
} finally {
|
||||
expireCookie();
|
||||
}
|
||||
}
|
||||
|
||||
@Path("logout")
|
||||
@GET
|
||||
@NoCache
|
||||
public Response logout() {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = getAdminstrationRealm(realmManager);
|
||||
expireCookie();
|
||||
authManager.expireIdentityCookie(realm, uriInfo);
|
||||
|
||||
return Response.status(302).location(uriInfo.getBaseUriBuilder().path(ConsoleLogin.class).path(ConsoleLogin.class, "loginPage").build()).build();
|
||||
}
|
||||
|
||||
@Path("logout-cookie")
|
||||
@GET
|
||||
@NoCache
|
||||
public void logoutCookie() {
|
||||
logger.debug("*** logoutCookie");
|
||||
expireCookie();
|
||||
}
|
||||
|
||||
protected RealmModel getAdminstrationRealm(RealmManager realmManager) {
|
||||
return realmManager.getKeycloakAdminstrationRealm();
|
||||
}
|
||||
}
|
|
@ -72,44 +72,48 @@ public class RealmsAdminResource {
|
|||
@NoCache
|
||||
@Produces("application/json")
|
||||
public List<RealmRepresentation> getRealms() {
|
||||
logger.debug(("getRealms()"));
|
||||
List<RealmModel> realms = session.getRealms();
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
|
||||
for (RealmModel realm : realms) {
|
||||
if (auth.hasAppRole(realm.getAdminApp(), AdminRoles.MANAGE_REALM)) {
|
||||
reps.add(ModelToRepresentation.toRepresentation(realm));
|
||||
} else if (auth.hasOneOfAppRole(realm.getAdminApp(), AdminRoles.ALL_REALM_ROLES)) {
|
||||
RealmRepresentation rep = new RealmRepresentation();
|
||||
rep.setRealm(realm.getName());
|
||||
reps.add(rep);
|
||||
if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
|
||||
List<RealmModel> realms = session.getRealms();
|
||||
for (RealmModel realm : realms) {
|
||||
addRealmRep(reps, realm);
|
||||
}
|
||||
} else {
|
||||
addRealmRep(reps, auth.getRealm());
|
||||
}
|
||||
logger.debug(("getRealms()"));
|
||||
return reps;
|
||||
}
|
||||
|
||||
public static UriBuilder realmUrl(UriInfo uriInfo) {
|
||||
return realmsUrl(uriInfo).path("{id}");
|
||||
}
|
||||
|
||||
public static UriBuilder realmsUrl(UriInfo uriInfo) {
|
||||
return uriInfo.getBaseUriBuilder().path(AdminService.class).path(AdminService.class, "getRealmsAdmin");
|
||||
protected void addRealmRep(List<RealmRepresentation> reps, RealmModel realm) {
|
||||
if (auth.hasAppRole(realm.getAdminApp(), AdminRoles.MANAGE_REALM)) {
|
||||
reps.add(ModelToRepresentation.toRepresentation(realm));
|
||||
} else if (auth.hasOneOfAppRole(realm.getAdminApp(), AdminRoles.ALL_REALM_ROLES)) {
|
||||
RealmRepresentation rep = new RealmRepresentation();
|
||||
rep.setRealm(realm.getName());
|
||||
reps.add(rep);
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes("application/json")
|
||||
public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
if (!auth.hasRealmRole(AdminRoles.CREATE_REALM)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
logger.debugv("importRealm: {0}", rep.getRealm());
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
|
||||
try {
|
||||
RealmModel realm = realmManager.importRealm(rep);
|
||||
grantPermissionsToRealmCreator(realm);
|
||||
|
||||
URI location = realmUrl(uriInfo).build(realm.getName());
|
||||
URI location = AdminRoot.realmsUrl(uriInfo).path(realm.getName()).build();
|
||||
logger.debugv("imported realm success, sending back: {0}", location.toString());
|
||||
return Response.created(location).build();
|
||||
} catch (ModelDuplicateException e) {
|
||||
|
@ -120,6 +124,10 @@ public class RealmsAdminResource {
|
|||
@POST
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
public Response uploadRealm(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
if (!auth.hasRealmRole(AdminRoles.CREATE_REALM)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
@ -127,7 +135,6 @@ public class RealmsAdminResource {
|
|||
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
|
||||
List<InputPart> inputParts = uploadForm.get("file");
|
||||
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
for (InputPart inputPart : inputParts) {
|
||||
inputPart.setMediaType(MediaType.APPLICATION_JSON_TYPE);
|
||||
RealmRepresentation rep = inputPart.getBody(new GenericType<RealmRepresentation>() {
|
||||
|
@ -143,7 +150,7 @@ public class RealmsAdminResource {
|
|||
grantPermissionsToRealmCreator(realm);
|
||||
|
||||
if (inputParts.size() == 1) {
|
||||
URI location = realmUrl(uriInfo).build(realm.getName());
|
||||
URI location = AdminRoot.realmsUrl(uriInfo).path(realm.getName()).build();
|
||||
return Response.created(location).build();
|
||||
}
|
||||
}
|
||||
|
@ -172,6 +179,10 @@ public class RealmsAdminResource {
|
|||
RealmModel realm = realmManager.getRealmByName(name);
|
||||
if (realm == null) throw new NotFoundException("{realm} = " + name);
|
||||
|
||||
if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())
|
||||
&& !auth.getRealm().equals(realm)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
RealmAuth realmAuth = new RealmAuth(auth, realm.getAdminApp());
|
||||
|
||||
RealmAdminResource adminResource = new RealmAdminResource(realmAuth, realm, tokenManager);
|
||||
|
|
|
@ -23,14 +23,12 @@ package org.keycloak.services.resources.flows;
|
|||
|
||||
import org.keycloak.services.resources.AccountService;
|
||||
import org.keycloak.services.resources.ThemeResource;
|
||||
import org.keycloak.services.resources.admin.AdminService;
|
||||
import org.keycloak.services.resources.RealmsResource;
|
||||
import org.keycloak.services.resources.RequiredActionsService;
|
||||
import org.keycloak.services.resources.SocialResource;
|
||||
import org.keycloak.services.resources.TokenService;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
|
@ -146,26 +144,6 @@ public class Urls {
|
|||
return tokenBase(baseUri).path(TokenService.class, "accessCodeToToken").build(realmId);
|
||||
}
|
||||
|
||||
private static UriBuilder saasBase(URI baseUri) {
|
||||
return UriBuilder.fromUri(baseUri).path(AdminService.class);
|
||||
}
|
||||
|
||||
public static URI saasLoginAction(URI baseUri) {
|
||||
return saasBase(baseUri).path(AdminService.class, "processLogin").build();
|
||||
}
|
||||
|
||||
public static URI saasLoginPage(URI baseUri) {
|
||||
return saasBase(baseUri).path(AdminService.class, "loginPage").build();
|
||||
}
|
||||
|
||||
public static URI saasRegisterAction(URI baseUri) {
|
||||
return saasBase(baseUri).path(AdminService.class, "processRegister").build();
|
||||
}
|
||||
|
||||
public static URI saasRegisterPage(URI baseUri) {
|
||||
return saasBase(baseUri).path(AdminService.class, "registerPage").build();
|
||||
}
|
||||
|
||||
public static UriBuilder socialBase(URI baseUri) {
|
||||
return UriBuilder.fromUri(baseUri).path(SocialResource.class);
|
||||
}
|
||||
|
|
3
testsuite/integration/src/test/java/org/keycloak/testsuite/AssertEvents.java
Normal file → Executable file
3
testsuite/integration/src/test/java/org/keycloak/testsuite/AssertEvents.java
Normal file → Executable file
|
@ -170,6 +170,9 @@ public class AssertEvents implements TestRule, AuditListenerFactory {
|
|||
return new AuditListener() {
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
if (event == null) {
|
||||
throw new RuntimeException("Added null event");
|
||||
}
|
||||
events.add(event);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.keycloak.models.utils.TimeBasedOTP;
|
|||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.resources.AccountService;
|
||||
import org.keycloak.services.resources.RealmsResource;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.OAuthClient;
|
||||
import org.keycloak.testsuite.Retry;
|
||||
|
@ -92,7 +93,9 @@ public class AccountTest {
|
|||
}
|
||||
});
|
||||
|
||||
public static String ACCOUNT_REDIRECT = AccountService.loginRedirectUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build("test").toString();
|
||||
private static final UriBuilder BASE = UriBuilder.fromUri("http://localhost:8081/auth");
|
||||
private static final String ACCOUNT_URL = RealmsResource.accountUrl(BASE.clone()).build("test").toString();
|
||||
public static String ACCOUNT_REDIRECT = AccountService.loginRedirectUrl(BASE.clone()).build("test").toString();
|
||||
|
||||
@Rule
|
||||
public AssertEvents events = new AssertEvents(keycloakRule);
|
||||
|
@ -209,6 +212,8 @@ public class AccountTest {
|
|||
|
||||
changePasswordPage.logout();
|
||||
|
||||
events.expectLogout().detail(Details.REDIRECT_URI, ACCOUNT_URL).assertEvent();
|
||||
|
||||
loginPage.open();
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
|
||||
|
@ -378,8 +383,6 @@ public class AccountTest {
|
|||
|
||||
logPage.open();
|
||||
|
||||
e.add(events.poll());
|
||||
|
||||
Collections.reverse(e);
|
||||
|
||||
Assert.assertTrue(logPage.isCurrent());
|
||||
|
|
|
@ -188,10 +188,6 @@ public class RequiredActionTotpSetupTest {
|
|||
accountTotpPage.open();
|
||||
accountTotpPage.assertCurrent();
|
||||
|
||||
events.expectLogin().user(userId).detail(Details.AUTH_METHOD, "sso").client("account")
|
||||
.detail(Details.REDIRECT_URI, AccountService.loginRedirectUrl(UriBuilder.fromUri("http://localhost:8081/auth")).queryParam("path", "totp").build("test").toString())
|
||||
.removeDetail(Details.USERNAME).assertEvent();
|
||||
|
||||
// Remove google authentificator
|
||||
accountTotpPage.removeTotp();
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ import org.keycloak.representations.idm.RealmRepresentation;
|
|||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
import org.keycloak.services.resources.TokenService;
|
||||
import org.keycloak.services.resources.admin.AdminRoot;
|
||||
import org.keycloak.services.resources.admin.RealmAdminResource;
|
||||
import org.keycloak.testsuite.OAuthClient;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||
|
@ -123,7 +125,8 @@ public class AdapterTest {
|
|||
|
||||
// View stats
|
||||
Client client = ClientBuilder.newClient();
|
||||
WebTarget adminTarget = client.target("http://localhost:8081/auth/rest/admin/realms/demo");
|
||||
UriBuilder authBase = UriBuilder.fromUri("http://localhost:8081/auth");
|
||||
WebTarget adminTarget = client.target(AdminRoot.realmsUrl(authBase)).path("demo");
|
||||
Map<String, SessionStats> stats = adminTarget.path("session-stats").request()
|
||||
.header(HttpHeaders.AUTHORIZATION, "Bearer " + adminToken)
|
||||
.get(new GenericType<Map<String, SessionStats>>(){});
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.keycloak.representations.idm.RealmRepresentation;
|
|||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
import org.keycloak.services.resources.TokenService;
|
||||
import org.keycloak.services.resources.admin.AdminRoot;
|
||||
import org.keycloak.testsuite.OAuthClient;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||
|
@ -126,7 +127,8 @@ public class RelativeUriAdapterTest {
|
|||
|
||||
// View stats
|
||||
Client client = ClientBuilder.newClient();
|
||||
WebTarget adminTarget = client.target("http://localhost:8081/auth/rest/admin/realms/demo");
|
||||
UriBuilder authBase = UriBuilder.fromUri("http://localhost:8081/auth");
|
||||
WebTarget adminTarget = client.target(AdminRoot.realmsUrl(authBase)).path("demo");
|
||||
Map<String, SessionStats> stats = adminTarget.path("session-stats").request()
|
||||
.header(HttpHeaders.AUTHORIZATION, "Bearer " + adminToken)
|
||||
.get(new GenericType<Map<String, SessionStats>>(){});
|
||||
|
|
|
@ -92,7 +92,6 @@ public class SSOTest {
|
|||
Assert.assertTrue(profilePage.isCurrent());
|
||||
|
||||
events.expectLogin().detail(Details.AUTH_METHOD, "sso").removeDetail(Details.USERNAME).client("test-app").assertEvent();
|
||||
events.expectLogin().detail(Details.AUTH_METHOD, "sso").removeDetail(Details.USERNAME).client("account").detail(Details.REDIRECT_URI, AccountService.loginRedirectUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build("test").toString()).assertEvent();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue