admin cors support
This commit is contained in:
commit
54cc095ff5
29 changed files with 425 additions and 473 deletions
|
@ -48,12 +48,12 @@
|
|||
"name": "js-console",
|
||||
"enabled": true,
|
||||
"publicClient": true,
|
||||
"baseUrl": "http://localhost/js-console",
|
||||
"baseUrl": "http://localhost:8080/js-console",
|
||||
"redirectUris": [
|
||||
"http://localhost/js-console/*"
|
||||
"http://localhost:8080/js-console/*"
|
||||
],
|
||||
"webOrigins": [
|
||||
"http://localhost"
|
||||
"http://localhost:8080"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="//localhost:8081/auth/js/keycloak.js"></script>
|
||||
<script src="//localhost:8080/auth/js/keycloak.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div>
|
||||
<button onclick="keycloak.login()">Login</button>
|
||||
<button onclick="keycloak.logout()">Logout</button>
|
||||
<button onclick="refreshToken()">Refresh Token</button>
|
||||
<button onclick="refreshToken(9999)">Refresh Token</button>
|
||||
<button onclick="refreshToken(30)">Refresh Token (if <30s validity)</button>
|
||||
<button onclick="loadProfile()">Get Profile</button>
|
||||
<button onclick="output(keycloak.tokenParsed)">Show Token</button>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"realm" : "example",
|
||||
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"auth-server-url" : "http://localhost:8081/auth",
|
||||
"auth-server-url" : "http://localhost:8080/auth",
|
||||
"ssl-not-required" : true,
|
||||
"resource" : "js-console",
|
||||
"public-client" : true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ public class ModelImporter {
|
|||
}
|
||||
}
|
||||
|
||||
logger.infof("%d roles imported: ", roles);
|
||||
logger.infof("%d roles imported: ", roles.size());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Imported roles: " + roles);
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ public class ModelImporter {
|
|||
addScopes(realm, client, clientEntity);
|
||||
}
|
||||
|
||||
logger.infof("OAuth clients imported: " + clients);
|
||||
logger.info("OAuth clients imported: " + clients);
|
||||
}
|
||||
|
||||
protected ApplicationModel findApplicationById(KeycloakSession keycloakSession, String applicationId) {
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
</style>
|
||||
</head>
|
||||
|
||||
<body class="admin-console" data-ng-controller="GlobalCtrl" data-ng-cloak>
|
||||
<body class="admin-console" data-ng-controller="GlobalCtrl" data-ng-cloak data-ng-show="auth.user">
|
||||
|
||||
<div id="idletimeout">
|
||||
You will be logged off in <strong><span></span> seconds</strong> due to inactivity.
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
var indexUrl = window.location.href;
|
||||
var consoleBaseUrl = window.location.href;
|
||||
consoleBaseUrl = consoleBaseUrl.substring(0, consoleBaseUrl.indexOf("/console"));
|
||||
consoleBaseUrl = consoleBaseUrl + "/console";
|
||||
|
@ -23,14 +22,12 @@ var loadingTimer = -1;
|
|||
|
||||
angular.element(document).ready(function ($http) {
|
||||
var keycloakAuth = new Keycloak(configUrl);
|
||||
auth.loggedIn = false;
|
||||
|
||||
keycloakAuth.onAuthLogout = function() {
|
||||
location.reload();
|
||||
}
|
||||
|
||||
keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
|
||||
auth.loggedIn = true;
|
||||
auth.authz = keycloakAuth;
|
||||
module.factory('Auth', function() {
|
||||
return auth;
|
||||
|
|
|
@ -195,7 +195,7 @@ module.controller('ApplicationInstallationCtrl', function($scope, realm, applica
|
|||
|
||||
});
|
||||
|
||||
module.controller('ApplicationDetailCtrl', function($scope, $document, realm, application, Application, $location, Dialog, Notifications) {
|
||||
module.controller('ApplicationDetailCtrl', function($scope, realm, application, Application, $location, Dialog, Notifications) {
|
||||
console.log('ApplicationDetailCtrl');
|
||||
|
||||
$scope.clientTypes = [
|
||||
|
@ -263,21 +263,10 @@ module.controller('ApplicationDetailCtrl', function($scope, $document, realm, ap
|
|||
}
|
||||
|
||||
$scope.save = function() {
|
||||
if ($scope.create) {
|
||||
if (!$scope.application.bearerOnly && (!$scope.application.redirectUris || $scope.application.redirectUris.length == 0)) {
|
||||
Notifications.error("You must specify at least one redirect uri");
|
||||
} else {
|
||||
// automatically add redirects to web origins
|
||||
var parser = document.createElement('a');
|
||||
var originSet = {};
|
||||
for (var i = 0; i < $scope.application.redirectUris.length; i++) {
|
||||
parser.href = $scope.application.redirectUris[i];
|
||||
var origin = parser.protocol + "//" + parser.host;
|
||||
originSet[origin] = true;
|
||||
}
|
||||
for (var key in originSet) {
|
||||
$scope.application.webOrigins.push(key);
|
||||
}
|
||||
if (!$scope.application.bearerOnly && (!$scope.application.redirectUris || $scope.application.redirectUris.length == 0)) {
|
||||
Notifications.error("You must specify at least one redirect uri");
|
||||
} else {
|
||||
if ($scope.create) {
|
||||
Application.save({
|
||||
realm: realm.realm,
|
||||
application: ''
|
||||
|
@ -288,16 +277,16 @@ module.controller('ApplicationDetailCtrl', function($scope, $document, realm, ap
|
|||
$location.url("/realms/" + realm.realm + "/applications/" + id);
|
||||
Notifications.success("The application has been created.");
|
||||
});
|
||||
} else {
|
||||
Application.update({
|
||||
realm : realm.realm,
|
||||
application : application.name
|
||||
}, $scope.application, function() {
|
||||
$scope.changed = false;
|
||||
application = angular.copy($scope.application);
|
||||
Notifications.success("Your changes have been saved to the application.");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Application.update({
|
||||
realm : realm.realm,
|
||||
application : application.name
|
||||
}, $scope.application, function() {
|
||||
$scope.changed = false;
|
||||
application = angular.copy($scope.application);
|
||||
Notifications.success("Your changes have been saved to the application.");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -342,195 +331,71 @@ module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm,
|
|||
$scope.applicationMappings = [];
|
||||
$scope.dummymodel = [];
|
||||
|
||||
function updateRealmRoles() {
|
||||
$scope.realmRoles = ApplicationAvailableRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
$scope.realmMappings = ApplicationRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
$scope.realmComposite = ApplicationCompositeRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
}
|
||||
|
||||
|
||||
$scope.realmMappings = ApplicationRealmScopeMapping.query({realm : realm.realm, application : application.name}, function(){
|
||||
for (var i = 0; i < $scope.realmMappings.length; i++) {
|
||||
var role = $scope.realmMappings[i];
|
||||
for (var j = 0; j < $scope.realmRoles.length; j++) {
|
||||
var realmRole = $scope.realmRoles[j];
|
||||
if (realmRole.id == role.id) {
|
||||
var idx = $scope.realmRoles.indexOf(realmRole);
|
||||
if (idx != -1) {
|
||||
$scope.realmRoles.splice(idx, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$scope.addRealmRole = function() {
|
||||
$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];
|
||||
var idx = $scope.realmRoles.indexOf($scope.selectedRealmRoles[i]);
|
||||
if (idx != -1) {
|
||||
$scope.realmRoles.splice(idx, 1);
|
||||
$scope.realmMappings.push(role);
|
||||
}
|
||||
}
|
||||
$scope.selectRealmRoles = [];
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteRealmRole = function() {
|
||||
$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];
|
||||
var idx = $scope.realmMappings.indexOf($scope.selectedRealmMappings[i]);
|
||||
if (idx != -1) {
|
||||
$scope.realmMappings.splice(idx, 1);
|
||||
$scope.realmRoles.push(role);
|
||||
}
|
||||
}
|
||||
$scope.selectedRealmMappings = [];
|
||||
});
|
||||
};
|
||||
|
||||
$scope.addApplicationRole = function() {
|
||||
$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];
|
||||
var idx = $scope.applicationRoles.indexOf($scope.selectedApplicationRoles[i]);
|
||||
if (idx != -1) {
|
||||
$scope.applicationRoles.splice(idx, 1);
|
||||
$scope.applicationMappings.push(role);
|
||||
}
|
||||
}
|
||||
$scope.selectedApplicationRoles = [];
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteApplicationRole = function() {
|
||||
$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];
|
||||
var idx = $scope.applicationMappings.indexOf($scope.selectedApplicationMappings[i]);
|
||||
if (idx != -1) {
|
||||
$scope.applicationMappings.splice(idx, 1);
|
||||
$scope.applicationRoles.push(role);
|
||||
}
|
||||
}
|
||||
$scope.selectedApplicationMappings = [];
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.changeApplication = function() {
|
||||
function updateAppRoles() {
|
||||
if ($scope.targetApp) {
|
||||
$scope.applicationRoles = ApplicationRole.query({realm : realm.realm, application : $scope.targetApp.name}, function() {
|
||||
$scope.applicationMappings = ApplicationApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name}, function(){
|
||||
for (var i = 0; i < $scope.applicationMappings.length; i++) {
|
||||
var role = $scope.applicationMappings[i];
|
||||
for (var j = 0; j < $scope.applicationRoles.length; j++) {
|
||||
var realmRole = $scope.applicationRoles[j];
|
||||
if (realmRole.id == role.id) {
|
||||
var idx = $scope.applicationRoles.indexOf(realmRole);
|
||||
if (idx != -1) {
|
||||
$scope.applicationRoles.splice(idx, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$scope.applicationRoles = null;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.realmMappings = ApplicationRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
$scope.realmRoles = ApplicationAvailableRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
$scope.realmComposite = ApplicationCompositeRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
|
||||
$scope.addRealmRole = function() {
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm',
|
||||
$scope.selectedRealmRoles).success(function() {
|
||||
$scope.realmMappings = ApplicationRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
$scope.realmRoles = ApplicationAvailableRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
$scope.realmComposite = ApplicationCompositeRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
$scope.selectedRealmMappings = [];
|
||||
$scope.selectRealmRoles = [];
|
||||
if ($scope.targetApp) {
|
||||
console.log('load available');
|
||||
$scope.applicationMappings = ApplicationApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name});
|
||||
$scope.applicationRoles = ApplicationAvailableApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name});
|
||||
$scope.applicationComposite = ApplicationCompositeApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name});
|
||||
$scope.selectedApplicationRoles = [];
|
||||
$scope.selectedApplicationMappings = [];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteRealmRole = function() {
|
||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm',
|
||||
{data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
|
||||
$scope.realmMappings = ApplicationRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
$scope.realmRoles = ApplicationAvailableRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
$scope.realmComposite = ApplicationCompositeRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||
$scope.selectedRealmMappings = [];
|
||||
$scope.selectRealmRoles = [];
|
||||
if ($scope.targetApp) {
|
||||
console.log('load available');
|
||||
$scope.applicationMappings = ApplicationApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name});
|
||||
$scope.applicationRoles = ApplicationAvailableApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name});
|
||||
$scope.applicationComposite = ApplicationCompositeApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name});
|
||||
$scope.selectedApplicationRoles = [];
|
||||
$scope.selectedApplicationMappings = [];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.addApplicationRole = function() {
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/applications/' + $scope.targetApp.name,
|
||||
$scope.selectedApplicationRoles).success(function() {
|
||||
$scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.name});
|
||||
$scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.name});
|
||||
$scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.name});
|
||||
$scope.selectedApplicationRoles = [];
|
||||
$scope.selectedApplicationMappings = [];
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deleteApplicationRole = function() {
|
||||
$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() {
|
||||
$scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.name});
|
||||
$scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.name});
|
||||
$scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.name});
|
||||
$scope.selectedApplicationRoles = [];
|
||||
$scope.selectedApplicationMappings = [];
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.changeApplication = function() {
|
||||
console.log('changeApplication');
|
||||
if ($scope.targetApp) {
|
||||
console.log('load available');
|
||||
$scope.applicationMappings = ApplicationApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name});
|
||||
console.debug($scope.targetApp.name);
|
||||
$scope.applicationRoles = ApplicationAvailableApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name});
|
||||
$scope.applicationMappings = ApplicationApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name});
|
||||
$scope.applicationComposite = ApplicationCompositeApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name});
|
||||
} else {
|
||||
$scope.applicationRoles = null;
|
||||
$scope.applicationMappings = null;
|
||||
$scope.applicationComposite = null;
|
||||
}
|
||||
$scope.selectedApplicationRoles = [];
|
||||
$scope.selectedApplicationMappings = [];
|
||||
}
|
||||
|
||||
$scope.addRealmRole = function() {
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm', $scope.selectedRealmRoles)
|
||||
.success(updateRealmRoles);
|
||||
};
|
||||
|
||||
$scope.deleteRealmRole = function() {
|
||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm',
|
||||
{data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}})
|
||||
.success(updateRealmRoles);
|
||||
};
|
||||
|
||||
$scope.addApplicationRole = function() {
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/applications/' + $scope.targetApp.name,
|
||||
$scope.selectedApplicationRoles).success(updateAppRoles);
|
||||
};
|
||||
|
||||
$scope.deleteApplicationRole = function() {
|
||||
$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(updateAppRoles);
|
||||
};
|
||||
|
||||
$scope.changeApplication = function() {
|
||||
updateAppRoles();
|
||||
};
|
||||
|
||||
$scope.addRealmRole = function() {
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm',
|
||||
$scope.selectedRealmRoles).success(updateRealmRoles);
|
||||
};
|
||||
|
||||
$scope.deleteRealmRole = function() {
|
||||
$http.delete(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm',
|
||||
{data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(updateRealmRoles);
|
||||
};
|
||||
|
||||
$scope.addApplicationRole = function() {
|
||||
$http.post(authUrl + '/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/applications/' + $scope.targetApp.name,
|
||||
$scope.selectedApplicationRoles).success(updateAppRoles);
|
||||
};
|
||||
|
||||
$scope.deleteApplicationRole = function() {
|
||||
$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(updateAppRoles);
|
||||
};
|
||||
|
||||
updateRealmRoles();
|
||||
});
|
||||
|
||||
module.controller('ApplicationRevocationCtrl', function($scope, realm, application, Application, ApplicationPushRevocation, $location, Dialog, Notifications) {
|
||||
|
|
|
@ -133,25 +133,29 @@ module.controller('OAuthClientDetailCtrl', function($scope, realm, oauth, OAuthC
|
|||
}
|
||||
|
||||
$scope.save = function() {
|
||||
if ($scope.create) {
|
||||
OAuthClient.save({
|
||||
realm: realm.realm
|
||||
}, $scope.oauth, function (data, headers) {
|
||||
$scope.changed = false;
|
||||
var l = headers().location;
|
||||
var id = l.substring(l.lastIndexOf("/") + 1);
|
||||
$location.url("/realms/" + realm.realm + "/oauth-clients/" + id);
|
||||
Notifications.success("The oauth client has been created.");
|
||||
});
|
||||
if (!$scope.oauth.redirectUris || $scope.oauth.redirectUris.length == 0) {
|
||||
Notifications.error("You must specify at least one redirect uri");
|
||||
} else {
|
||||
OAuthClient.update({
|
||||
realm : realm.realm,
|
||||
id : oauth.id
|
||||
}, $scope.oauth, function() {
|
||||
$scope.changed = false;
|
||||
oauth = angular.copy($scope.oauth);
|
||||
Notifications.success("Your changes have been saved to the oauth client.");
|
||||
});
|
||||
if ($scope.create) {
|
||||
OAuthClient.save({
|
||||
realm: realm.realm
|
||||
}, $scope.oauth, function (data, headers) {
|
||||
$scope.changed = false;
|
||||
var l = headers().location;
|
||||
var id = l.substring(l.lastIndexOf("/") + 1);
|
||||
$location.url("/realms/" + realm.realm + "/oauth-clients/" + id);
|
||||
Notifications.success("The oauth client has been created.");
|
||||
});
|
||||
} else {
|
||||
OAuthClient.update({
|
||||
realm : realm.realm,
|
||||
id : oauth.id
|
||||
}, $scope.oauth, function() {
|
||||
$scope.changed = false;
|
||||
oauth = angular.copy($scope.oauth);
|
||||
Notifications.success("Your changes have been saved to the oauth client.");
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ module.controller('UserSessionsCtrl', function($scope, realm, user, sessions, Us
|
|||
$scope.logoutAll = function() {
|
||||
UserLogout.save({realm : realm.realm, user: user.username}, function () {
|
||||
Notifications.success('Logged out user in all applications');
|
||||
UserSessions.get({realm: realm.realm, user: user.username}, function(updated) {
|
||||
UserSessions.query({realm: realm.realm, user: user.username}, function(updated) {
|
||||
$scope.sessions = updated;
|
||||
})
|
||||
});
|
||||
|
@ -116,9 +116,9 @@ module.controller('UserSessionsCtrl', function($scope, realm, user, sessions, Us
|
|||
$scope.logoutSession = function(sessionId) {
|
||||
console.log('here in logoutSession');
|
||||
UserSessionLogout.delete({realm : realm.realm, session: sessionId}, function() {
|
||||
Notifications.success('Logged out session');
|
||||
UserSessions.get({realm: realm.realm, user: user.username}, function(updated) {
|
||||
UserSessions.query({realm: realm.realm, user: user.username}, function(updated) {
|
||||
$scope.sessions = updated;
|
||||
Notifications.success('Logged out session');
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
|
@ -77,8 +77,6 @@ module.service('Dialog', function($modal) {
|
|||
}
|
||||
|
||||
dialog.confirm = function(title, message, success, cancel) {
|
||||
var title = title;
|
||||
var msg = '<span class="primary">' + message + '"</span>';
|
||||
var btns = {
|
||||
ok: {
|
||||
label: title,
|
||||
|
@ -90,7 +88,7 @@ module.service('Dialog', function($modal) {
|
|||
}
|
||||
}
|
||||
|
||||
openDialog(title, msg, btns).then(success).reject(cancel);
|
||||
openDialog(title, message, btns).then(success, cancel);
|
||||
}
|
||||
|
||||
return dialog
|
||||
|
|
|
@ -92,30 +92,24 @@
|
|||
</div>
|
||||
<div class="form-group" data-ng-show="!application.bearerOnly && !create">
|
||||
<label class="col-sm-2 control-label" for="newWebOrigin">Web Origin</label>
|
||||
<div class="col-sm-6">
|
||||
<div ng-repeat="webOrigin in application.webOrigins" class="row kc-item-deletable">
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control kc-button-control"
|
||||
type="text" data-ng-class="{'input-below':!$first}"
|
||||
name="webOrigin" id="webOrigin"
|
||||
data-ng-model="webOrigin" readonly/>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button class="btn btn-danger"
|
||||
type="button" data-ng-click="deleteWebOrigin($index)">Delete</button>
|
||||
</div>
|
||||
<div class="col-sm-4 multiple" ng-repeat="webOrigin in application.webOrigins">
|
||||
<div class="input-group kc-item-deletable">
|
||||
<input class="form-control" type="text" data-ng-class="{'input-below':!$first}"
|
||||
name="webOrigin" id="webOrigin" data-ng-model="webOrigin" readonly />
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button" data-ng-click="deleteWebOrigin($index)">
|
||||
Delete</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control kc-button-control"
|
||||
type="text" name="newWebOrigin" id="newWebOrigin"
|
||||
placeholder="New Web Origin..." data-ng-model="newWebOrigin"
|
||||
data-ng-class="{'input-below':application.webOrigins.length}"/>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button class="btn btn-primary"
|
||||
data-ng-click="addWebOrigin()" ng-show="newWebOrigin.length > 0">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 multiple">
|
||||
<div class="input-group">
|
||||
<input class="form-control" type="text" name="newWebOrigin" id="newWebOrigin"
|
||||
placeholder="New Web Origin..." data-ng-model="newWebOrigin"
|
||||
data-ng-class="{'input-below':application.webOrigins.length}" />
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" data-ng-click="addWebOrigin()" ng-show="newWebOrigin.length > 0">Add</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</div>
|
||||
<div class="collapse navbar-collapse navbar-collapse-1">
|
||||
<div class="container">
|
||||
<ul class="nav navbar-nav navbar-utility" data-ng-show="auth.loggedIn">
|
||||
<ul class="nav navbar-nav navbar-utility" data-ng-show="auth.user">
|
||||
<li class="dropdown">
|
||||
<a data-toggle="dropdown" class="dropdown-toggle" href="#">
|
||||
<span class="pficon pficon-user"></span>
|
||||
|
@ -36,9 +36,9 @@
|
|||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="active pull-right" data-ng-show="auth.loggedIn && access.createRealm">
|
||||
<li class="active pull-right" data-ng-show="auth.user && access.createRealm">
|
||||
<a class="button primary" href="#/create/realm" data-ng-class="path[0] == 'create' && path[1] == 'realm' && 'active'"
|
||||
data-ng-show="auth.loggedIn">Add Realm</a>
|
||||
data-ng-show="auth.user">Add Realm</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -77,26 +77,24 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="newWebOrigin">Web Origin</label>
|
||||
<div class="col-sm-6">
|
||||
<div ng-repeat="webOrigin in oauth.webOrigins" class="kc-item-deletable row">
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control" type="text" data-ng-class="{'input-below':!$first}"
|
||||
name="webOrigin" id="webOrigin" data-ng-model="webOrigin" readonly />
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button class="btn btn-danger" type="button" data-ng-click="deleteWebOrigin($index)">
|
||||
<div class="col-sm-4 multiple" ng-repeat="webOrigin in oauth.webOrigins">
|
||||
<div class="input-group kc-item-deletable">
|
||||
<input class="form-control" type="text" data-ng-class="{'input-below':!$first}"
|
||||
name="webOrigin" id="webOrigin" data-ng-model="webOrigin" readonly />
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button" data-ng-click="deleteWebOrigin($index)">
|
||||
Delete</button>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control" type="text" name="newWebOrigin" id="newWebOrigin"
|
||||
placeholder="New Web Origin..." data-ng-model="newWebOrigin"
|
||||
data-ng-class="{'input-below':oauth.webOrigins.length}" />
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button class="btn btn-primary" data-ng-click="addWebOrigin()" ng-show="newWebOrigin.length > 0">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4 multiple">
|
||||
<div class="input-group">
|
||||
<input class="form-control" type="text" name="newWebOrigin" id="newWebOrigin"
|
||||
placeholder="New Web Origin..." data-ng-model="newWebOrigin"
|
||||
data-ng-class="{'input-below':oauth.webOrigins.length}" />
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" data-ng-click="addWebOrigin()" ng-show="newWebOrigin.length > 0">Add</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<ul data-ng-hide="createRealm">
|
||||
<li data-ng-show="access.viewRealm" data-ng-class="((!path[2] || path[1] == 'role' || path[2] == 'roles' || path[2] == 'token-settings' ||
|
||||
<li data-ng-show="access.viewRealm" data-ng-class="((!path[2] || path[1] == 'role' || path[2] == 'roles' ||
|
||||
path[2] == 'social-settings' || path[2] == 'required-credentials' || path[2] == 'default-roles' || path[2] == 'registration-settings' ||
|
||||
path[2] == 'keys-settings' || path[2] == 'smtp-settings' || path[2] == 'ldap-settings' || path[2] == 'auth-settings') && path[3] != 'applications') && 'active'">
|
||||
<a href="#/realms/{{realm.realm}}">Settings</a>
|
||||
|
@ -8,6 +8,6 @@
|
|||
</li>
|
||||
<li data-ng-show="access.viewApplications" data-ng-class="(path[2] == 'applications' || path[1] == 'application' || path[3] == 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
|
||||
<li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'oauth-clients' || path[1] == 'oauth-client') && 'active'"><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
|
||||
<li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'sessions') && 'active'"><a href="#/realms/{{realm.realm}}/sessions/realm">Sessions and Tokens</a></li>
|
||||
<li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'sessions' || path[2] == 'token-settings') && 'active'"><a href="#/realms/{{realm.realm}}/sessions/realm">Sessions and Tokens</a></li>
|
||||
<li data-ng-show="access.viewAudit" data-ng-class="(path[2] == 'audit' || path[2] == 'audit-settings') && 'active'"><a href="#/realms/{{realm.realm}}/audit">Audit</a></li>
|
||||
</ul>
|
|
@ -38,19 +38,18 @@
|
|||
<td>{{session.ipAddress}}</td>
|
||||
<td>{{session.start | date:'medium'}}</td>
|
||||
<td>{{session.lastAccess | date:'medium'}}</td>
|
||||
<td><ul style="list-style: none; ">
|
||||
<li data-ng-repeat="app in session.applications">
|
||||
<td>
|
||||
<div data-ng-repeat="app in session.applications">
|
||||
<a href="#/realms/{{realm.realm}}/applications/{{app}}/sessions">{{app}}</a>
|
||||
</li>
|
||||
</div>
|
||||
</ul>
|
||||
</td>
|
||||
<td><ul style="list-style: none; ">
|
||||
<li data-ng-repeat="(clientId, clientName) in session.clients">
|
||||
<td>
|
||||
<div data-ng-repeat="(clientId, clientName) in session.clients">
|
||||
<a href="#/realms/{{realm.realm}}/oauth-clients/{{clientId}}">{{clientName}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
<td><a ng-click="logoutSession(session.id)">logout</a> </td>
|
||||
<td><a href="" ng-click="logoutSession(session.id)">logout</a> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -29,6 +29,10 @@ var Keycloak = function (config) {
|
|||
if (initOptions.checkLoginIframeInterval) {
|
||||
loginIframe.interval = initOptions.checkLoginIframeInterval;
|
||||
}
|
||||
|
||||
if (initOptions.onLoad === 'login-required') {
|
||||
kc.loginRequired = true;
|
||||
}
|
||||
}
|
||||
|
||||
var promise = createPromise();
|
||||
|
@ -374,6 +378,9 @@ var Keycloak = function (config) {
|
|||
if (kc.token) {
|
||||
setToken(null, null);
|
||||
kc.onAuthLogout && kc.onAuthLogout();
|
||||
if (kc.loginRequired) {
|
||||
kc.login();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -531,7 +538,7 @@ var Keycloak = function (config) {
|
|||
loginIframe.iframe = iframe;
|
||||
}
|
||||
|
||||
var src = getRealmUrl() + '/login-status-iframe.html?client_id=' + encodeURIComponent(kc.clientId);
|
||||
var src = getRealmUrl() + '/login-status-iframe.html?client_id=' + encodeURIComponent(kc.clientId) + '&origin=' + window.location.origin;
|
||||
iframe.setAttribute('src', src );
|
||||
iframe.style.display = 'none';
|
||||
document.body.appendChild(iframe);
|
||||
|
|
41
pom.xml
41
pom.xml
|
@ -12,6 +12,8 @@
|
|||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<bouncycastle.version>1.46</bouncycastle.version>
|
||||
<jackson.version>1.9.12</jackson.version>
|
||||
<keycloak.apache.httpcomponents.version>4.1.2</keycloak.apache.httpcomponents.version>
|
||||
<resteasy.version>2.3.7.Final</resteasy.version>
|
||||
<resteasy.version.eap.6.3>2.3.7.Final</resteasy.version.eap.6.3>
|
||||
|
@ -33,6 +35,13 @@
|
|||
<slf4j.version>1.5.10</slf4j.version>
|
||||
<jboss.version>7.1.1.Final</jboss.version>
|
||||
<wildfly.version>8.0.0.Final</wildfly.version>
|
||||
<servlet.api.30.version>1.0.1.Final</servlet.api.30.version>
|
||||
<google.zxing.version>2.2</google.zxing.version>
|
||||
<google.client.version>1.14.1-beta</google.client.version>
|
||||
<winzipaes.version>1.0.1</winzipaes.version>
|
||||
<freemarker.version>2.3.19</freemarker.version>
|
||||
<twitter4j.version>3.0.5</twitter4j.version>
|
||||
<selenium.version>2.35.0</selenium.version>
|
||||
|
||||
<!-- maven-compiler-plugin -->
|
||||
<maven.compiler.target>1.6</maven.compiler.target>
|
||||
|
@ -109,12 +118,12 @@
|
|||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk16</artifactId>
|
||||
<version>1.46</version>
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcmail-jdk16</artifactId>
|
||||
<version>1.46</version>
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.iharder</groupId>
|
||||
|
@ -179,27 +188,27 @@
|
|||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
<version>1.9.12</version>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
<version>1.9.12</version>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-xc</artifactId>
|
||||
<version>1.9.12</version>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-jaxrs</artifactId>
|
||||
<version>1.9.12</version>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
<version>1.0.1.Final</version>
|
||||
<version>${servlet.api.30.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
|
@ -282,19 +291,19 @@
|
|||
<dependency>
|
||||
<groupId>com.google.api-client</groupId>
|
||||
<artifactId>google-api-client</artifactId>
|
||||
<version>1.14.1-beta</version>
|
||||
<version>${google.client.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
<version>2.3.19</version>
|
||||
<version>${freemarker.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Google+ -->
|
||||
<dependency>
|
||||
<groupId>com.google.http-client</groupId>
|
||||
<artifactId>google-http-client-jackson</artifactId>
|
||||
<version>1.14.1-beta</version>
|
||||
<version>${google.client.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.apis</groupId>
|
||||
|
@ -306,19 +315,19 @@
|
|||
<dependency>
|
||||
<groupId>org.twitter4j</groupId>
|
||||
<artifactId>twitter4j-core</artifactId>
|
||||
<version>3.0.5</version>
|
||||
<version>${twitter4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- QR Code Generator -->
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>2.2</version>
|
||||
<version>${google.zxing.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>javase</artifactId>
|
||||
<version>2.2</version>
|
||||
<version>${google.zxing.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Email Test Servers -->
|
||||
|
@ -332,19 +341,19 @@
|
|||
<dependency>
|
||||
<groupId>de.idyl</groupId>
|
||||
<artifactId>winzipaes</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<version>${winzipaes.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Selenium -->
|
||||
<dependency>
|
||||
<groupId>org.seleniumhq.selenium</groupId>
|
||||
<artifactId>selenium-java</artifactId>
|
||||
<version>2.35.0</version>
|
||||
<version>${selenium.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.seleniumhq.selenium</groupId>
|
||||
<artifactId>selenium-chrome-driver</artifactId>
|
||||
<version>2.35.0</version>
|
||||
<version>${selenium.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
"theme": {
|
||||
"default": "keycloak",
|
||||
"dir": "${jboss.server.config.dir}/themes"
|
||||
"folder": {
|
||||
"dir": "${jboss.server.config.dir}/themes"
|
||||
}
|
||||
},
|
||||
|
||||
"login-forms": {
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
<properties>
|
||||
<property name="hibernate.hbm2ddl.auto" value="update" />
|
||||
<property name="jboss.as.jpa.managed" value="false" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
|
@ -37,7 +36,6 @@
|
|||
|
||||
<properties>
|
||||
<property name="hibernate.hbm2ddl.auto" value="update" />
|
||||
<property name="jboss.as.jpa.managed" value="false" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.keycloak.services.managers;
|
|||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.spi.UnauthorizedException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.ProviderSession;
|
||||
|
||||
import javax.ws.rs.core.Cookie;
|
||||
|
@ -21,18 +20,16 @@ public class AppAuthManager extends AuthenticationManager {
|
|||
super(providerSession);
|
||||
}
|
||||
|
||||
public AuthResult authenticateRequest(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
|
||||
AuthResult authResult = authenticateIdentityCookie(realm, uriInfo, headers);
|
||||
if (authResult != null) {
|
||||
Cookie remember = headers.getCookies().get(AuthenticationManager.KEYCLOAK_REMEMBER_ME);
|
||||
boolean rememberMe = remember != null;
|
||||
// refresh the cookies!
|
||||
createLoginCookie(realm, authResult.getUser(), authResult.getSession(), uriInfo, rememberMe);
|
||||
if (rememberMe) createRememberMeCookie(realm, uriInfo);
|
||||
return authResult;
|
||||
} else {
|
||||
return authenticateBearerToken(realm, uriInfo, headers);
|
||||
}
|
||||
@Override
|
||||
public AuthResult authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
|
||||
AuthResult authResult = super.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||
if (authResult == null) return null;
|
||||
Cookie remember = headers.getCookies().get(AuthenticationManager.KEYCLOAK_REMEMBER_ME);
|
||||
boolean rememberMe = remember != null;
|
||||
// refresh the cookies!
|
||||
createLoginCookie(realm, authResult.getUser(), authResult.getSession(), uriInfo, rememberMe);
|
||||
if (rememberMe) createRememberMeCookie(realm, uriInfo);
|
||||
return authResult;
|
||||
}
|
||||
|
||||
public String extractAuthorizationHeaderToken(HttpHeaders headers) {
|
||||
|
|
|
@ -17,26 +17,8 @@ public class Auth {
|
|||
private final UserModel user;
|
||||
private final ClientModel client;
|
||||
|
||||
public Auth(RealmModel realm, UserModel user, ClientModel client) {
|
||||
this.cookie = true;
|
||||
this.realm = realm;
|
||||
this.token = null;
|
||||
|
||||
this.user = user;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public Auth(AccessToken token, UserModel user, ClientModel client) {
|
||||
this.cookie = false;
|
||||
this.token = token;
|
||||
this.realm = null;
|
||||
|
||||
this.user = user;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public Auth(RealmModel realm, AccessToken token, UserModel user, ClientModel client) {
|
||||
this.cookie = false;
|
||||
public Auth(RealmModel realm, AccessToken token, UserModel user, ClientModel client, boolean cookie) {
|
||||
this.cookie = cookie;
|
||||
this.token = token;
|
||||
this.realm = realm;
|
||||
|
||||
|
|
|
@ -145,9 +145,16 @@ public class AccountService {
|
|||
account = providers.getProvider(AccountProvider.class).setRealm(realm).setUriInfo(uriInfo);
|
||||
|
||||
boolean passwordUpdateSupported = false;
|
||||
AuthenticationManager.AuthResult authResult = authManager.authenticateRequest(realm, uriInfo, headers);
|
||||
AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||
if (authResult != null) {
|
||||
auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, true);
|
||||
} else {
|
||||
authResult = authManager.authenticateBearerToken(realm, uriInfo, headers);
|
||||
if (authResult != null) {
|
||||
auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, false);
|
||||
}
|
||||
}
|
||||
if (authResult != null) {
|
||||
auth = new Auth(realm, authResult.getUser(), application);
|
||||
if (authResult.getSession() != null) {
|
||||
authResult.getSession().associateClient(application);
|
||||
}
|
||||
|
@ -208,7 +215,7 @@ public class AccountService {
|
|||
} else if (types.contains(MediaType.APPLICATION_JSON_TYPE)) {
|
||||
requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE);
|
||||
|
||||
return Cors.add(request, Response.ok(ModelToRepresentation.toRepresentation(auth.getUser()))).auth().allowedOrigins(auth.getClient()).build();
|
||||
return Cors.add(request, Response.ok(ModelToRepresentation.toRepresentation(auth.getUser()))).auth().allowedOrigins(auth.getToken()).build();
|
||||
} else {
|
||||
return Response.notAcceptable(Variant.VariantListBuilder.newInstance().mediaTypes(MediaType.TEXT_HTML_TYPE, MediaType.APPLICATION_JSON_TYPE).build()).build();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.jboss.resteasy.spi.HttpResponse;
|
||||
import org.keycloak.models.ClientModel;
|
||||
|
@ -18,6 +19,7 @@ import org.keycloak.util.CollectionUtil;
|
|||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class Cors {
|
||||
protected static final Logger logger = Logger.getLogger(Cors.class);
|
||||
|
||||
public static final long DEFAULT_MAX_AGE = TimeUnit.HOURS.toSeconds(1);
|
||||
public static final String DEFAULT_ALLOW_METHODS = "GET, HEAD, OPTIONS";
|
||||
|
@ -128,15 +130,18 @@ public class Cors {
|
|||
return builder.build();
|
||||
}
|
||||
public void build(HttpResponse response) {
|
||||
logger.info("build CORS");
|
||||
String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN_HEADER);
|
||||
if (origin == null) {
|
||||
logger.info("No origin returning");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!preflight && (allowedOrigins == null || !allowedOrigins.contains(origin))) {
|
||||
logger.info("!preflight and no origin");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("build CORS headers and return");
|
||||
response.getOutputHeaders().add(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
|
||||
|
||||
if (allowedMethods != null) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.keycloak.services.resources;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.BadRequestException;
|
||||
import org.jboss.resteasy.spi.NotFoundException;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.jboss.resteasy.spi.UnauthorizedException;
|
||||
|
@ -98,7 +99,8 @@ public class RealmsResource {
|
|||
@Produces(MediaType.TEXT_HTML)
|
||||
@NoCache
|
||||
public String getLoginStatusIframe(final @PathParam("realm") String name,
|
||||
@QueryParam("client_id") String client_id) {
|
||||
@QueryParam("client_id") String client_id,
|
||||
@QueryParam("origin") String origin) {
|
||||
logger.info("getLoginStatusIframe");
|
||||
AuthenticationManager auth = new AuthenticationManager(providers);
|
||||
|
||||
|
@ -116,31 +118,33 @@ public class RealmsResource {
|
|||
|
||||
InputStream is = getClass().getClassLoader().getResourceAsStream("login-status-iframe.html");
|
||||
if (is == null) throw new NotFoundException("Could not find login-status-iframe.html ");
|
||||
Set<String> redirectUris = TokenService.resolveValidRedirects(uriInfo, client.getRedirectUris());
|
||||
String origin = null;
|
||||
for (String redirect : redirectUris) {
|
||||
|
||||
int index = redirect.indexOf("://");
|
||||
if (index == -1) continue;
|
||||
index = redirect.indexOf('/', index + 3);
|
||||
if (index == -1) {
|
||||
origin = redirect;
|
||||
} else {
|
||||
origin = redirect.substring(0, index);
|
||||
boolean valid = false;
|
||||
for (String o : client.getWebOrigins()) {
|
||||
if (o.equals("*") || o.equals(origin)) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
String file = null;
|
||||
|
||||
for (String r : TokenService.resolveValidRedirects(uriInfo, client.getRedirectUris())) {
|
||||
r = r.substring(0, r.indexOf('/', 8));
|
||||
if (r.equals(origin)) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
throw new BadRequestException("Invalid origin");
|
||||
}
|
||||
|
||||
try {
|
||||
file = StreamUtil.readString(is);
|
||||
String file = StreamUtil.readString(is);
|
||||
return file.replace("ORIGIN", origin);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
file = file.replace("ORIGIN", origin);
|
||||
//System.out.println(file);
|
||||
return file;
|
||||
|
||||
}
|
||||
|
||||
@Path("{realm}/tokens")
|
||||
|
|
83
services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java
Executable file
83
services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java
Executable file
|
@ -0,0 +1,83 @@
|
|||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class AdminAuth {
|
||||
|
||||
private final RealmModel realm;
|
||||
private final AccessToken token;
|
||||
private final UserModel user;
|
||||
private final ClientModel client;
|
||||
|
||||
public AdminAuth(RealmModel realm, AccessToken token, UserModel user, ClientModel client) {
|
||||
this.token = token;
|
||||
this.realm = realm;
|
||||
|
||||
this.user = user;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public RealmModel getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
public UserModel getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public ClientModel getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public AccessToken getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasRealmRole(String role) {
|
||||
if (client instanceof ApplicationModel) {
|
||||
RoleModel roleModel = realm.getRole(role);
|
||||
return realm.hasRole(user, roleModel) && realm.hasScope(client, roleModel);
|
||||
} else {
|
||||
AccessToken.Access access = token.getRealmAccess();
|
||||
return access != null && access.isUserInRole(role);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasOneOfRealmRole(String... roles) {
|
||||
for (String r : roles) {
|
||||
if (hasRealmRole(r)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasAppRole(ApplicationModel app, String role) {
|
||||
if (client instanceof ApplicationModel) {
|
||||
RoleModel roleModel = app.getRole(role);
|
||||
return realm.hasRole(user, roleModel) && realm.hasScope(client, roleModel);
|
||||
} else {
|
||||
AccessToken.Access access = token.getResourceAccess(app.getName());
|
||||
return access != null && access.isUserInRole(role);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasOneOfAppRole(ApplicationModel app, String... roles) {
|
||||
for (String r : roles) {
|
||||
if (hasAppRole(app, r)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@ 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.ClientModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
@ -112,7 +113,7 @@ public class AdminRoot {
|
|||
}
|
||||
|
||||
|
||||
protected Auth authenticateRealmAdminRequest(HttpHeaders headers) {
|
||||
protected AdminAuth authenticateRealmAdminRequest(HttpHeaders headers) {
|
||||
String tokenString = authManager.extractAuthorizationHeaderToken(headers);
|
||||
if (tokenString == null) throw new UnauthorizedException("Bearer");
|
||||
JWSInput input = new JWSInput(tokenString);
|
||||
|
@ -134,14 +135,13 @@ public class AdminRoot {
|
|||
throw new UnauthorizedException("Bearer");
|
||||
}
|
||||
|
||||
ApplicationModel consoleApp = realm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
if (consoleApp == null) {
|
||||
throw new NotFoundException("Could not find admin console application");
|
||||
ClientModel client = realm.findClient(token.getIssuedFor());
|
||||
if (client == null) {
|
||||
throw new NotFoundException("Could not find client for authorization");
|
||||
|
||||
}
|
||||
Auth auth = new Auth(realm, token, authResult.getUser(), consoleApp);
|
||||
return auth;
|
||||
|
||||
|
||||
return new AdminAuth(realm, authResult.getToken(), authResult.getUser(), client);
|
||||
}
|
||||
|
||||
public static UriBuilder realmsUrl(UriInfo uriInfo) {
|
||||
|
@ -155,11 +155,12 @@ public class AdminRoot {
|
|||
@Path("realms")
|
||||
public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
|
||||
if (request.getHttpMethod().equalsIgnoreCase("OPTIONS")) {
|
||||
Response response = Cors.add(request, Response.ok()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build();
|
||||
logger.info("*** CORS ADMIN PREFLIGHT!!!!");
|
||||
Response response = Cors.add(request, Response.ok()).preflight().allowedMethods("GET", "PUT", "POST", "DELETE").auth().build();
|
||||
throw new WebApplicationException(response);
|
||||
}
|
||||
|
||||
Auth auth = authenticateRealmAdminRequest(headers);
|
||||
AdminAuth auth = authenticateRealmAdminRequest(headers);
|
||||
if (auth != null) {
|
||||
logger.info("authenticated admin access for: " + auth.getUser().getLoginName());
|
||||
}
|
||||
|
|
|
@ -1,95 +1,95 @@
|
|||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.keycloak.models.AdminRoles;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.services.ForbiddenException;
|
||||
import org.keycloak.services.managers.Auth;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class RealmAuth {
|
||||
|
||||
private Resource resource;
|
||||
|
||||
public enum Resource {
|
||||
APPLICATION, CLIENT, USER, REALM, AUDIT
|
||||
}
|
||||
|
||||
private Auth auth;
|
||||
private ApplicationModel realmAdminApp;
|
||||
|
||||
public RealmAuth(Auth auth, ApplicationModel realmAdminApp) {
|
||||
this.auth = auth;
|
||||
this.realmAdminApp = realmAdminApp;
|
||||
}
|
||||
|
||||
public RealmAuth init(Resource resource) {
|
||||
this.resource = resource;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void requireAny() {
|
||||
if (!auth.hasOneOfAppRole(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasView() {
|
||||
return auth.hasOneOfAppRole(realmAdminApp, getViewRole(resource), getManageRole(resource));
|
||||
}
|
||||
|
||||
public boolean hasManage() {
|
||||
return auth.hasOneOfAppRole(realmAdminApp, getManageRole(resource));
|
||||
}
|
||||
|
||||
public void requireView() {
|
||||
if (!hasView()) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public void requireManage() {
|
||||
if (!hasManage()) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
private String getViewRole(Resource resource) {
|
||||
switch (resource) {
|
||||
case APPLICATION:
|
||||
return AdminRoles.VIEW_APPLICATIONS;
|
||||
case CLIENT:
|
||||
return AdminRoles.VIEW_CLIENTS;
|
||||
case USER:
|
||||
return AdminRoles.VIEW_USERS;
|
||||
case REALM:
|
||||
return AdminRoles.VIEW_REALM;
|
||||
case AUDIT:
|
||||
return AdminRoles.VIEW_AUDIT;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
private String getManageRole(Resource resource) {
|
||||
switch (resource) {
|
||||
case APPLICATION:
|
||||
return AdminRoles.MANAGE_APPLICATIONS;
|
||||
case CLIENT:
|
||||
return AdminRoles.MANAGE_CLIENTS;
|
||||
case USER:
|
||||
return AdminRoles.MANAGE_USERS;
|
||||
case REALM:
|
||||
return AdminRoles.MANAGE_REALM;
|
||||
case AUDIT:
|
||||
return AdminRoles.MANAGE_AUDIT;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.keycloak.models.AdminRoles;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.services.ForbiddenException;
|
||||
import org.keycloak.services.managers.Auth;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class RealmAuth {
|
||||
|
||||
private Resource resource;
|
||||
|
||||
public enum Resource {
|
||||
APPLICATION, CLIENT, USER, REALM, AUDIT
|
||||
}
|
||||
|
||||
private AdminAuth auth;
|
||||
private ApplicationModel realmAdminApp;
|
||||
|
||||
public RealmAuth(AdminAuth auth, ApplicationModel realmAdminApp) {
|
||||
this.auth = auth;
|
||||
this.realmAdminApp = realmAdminApp;
|
||||
}
|
||||
|
||||
public RealmAuth init(Resource resource) {
|
||||
this.resource = resource;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void requireAny() {
|
||||
if (!auth.hasOneOfAppRole(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasView() {
|
||||
return auth.hasOneOfAppRole(realmAdminApp, getViewRole(resource), getManageRole(resource));
|
||||
}
|
||||
|
||||
public boolean hasManage() {
|
||||
return auth.hasOneOfAppRole(realmAdminApp, getManageRole(resource));
|
||||
}
|
||||
|
||||
public void requireView() {
|
||||
if (!hasView()) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public void requireManage() {
|
||||
if (!hasManage()) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
private String getViewRole(Resource resource) {
|
||||
switch (resource) {
|
||||
case APPLICATION:
|
||||
return AdminRoles.VIEW_APPLICATIONS;
|
||||
case CLIENT:
|
||||
return AdminRoles.VIEW_CLIENTS;
|
||||
case USER:
|
||||
return AdminRoles.VIEW_USERS;
|
||||
case REALM:
|
||||
return AdminRoles.VIEW_REALM;
|
||||
case AUDIT:
|
||||
return AdminRoles.VIEW_AUDIT;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
private String getManageRole(Resource resource) {
|
||||
switch (resource) {
|
||||
case APPLICATION:
|
||||
return AdminRoles.MANAGE_APPLICATIONS;
|
||||
case CLIENT:
|
||||
return AdminRoles.MANAGE_CLIENTS;
|
||||
case USER:
|
||||
return AdminRoles.MANAGE_USERS;
|
||||
case REALM:
|
||||
return AdminRoles.MANAGE_REALM;
|
||||
case AUDIT:
|
||||
return AdminRoles.MANAGE_AUDIT;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,10 +46,10 @@ import java.util.Map;
|
|||
*/
|
||||
public class RealmsAdminResource {
|
||||
protected static final Logger logger = Logger.getLogger(RealmsAdminResource.class);
|
||||
protected Auth auth;
|
||||
protected AdminAuth auth;
|
||||
protected TokenManager tokenManager;
|
||||
|
||||
public RealmsAdminResource(Auth auth, TokenManager tokenManager) {
|
||||
public RealmsAdminResource(AdminAuth auth, TokenManager tokenManager) {
|
||||
this.auth = auth;
|
||||
this.tokenManager = tokenManager;
|
||||
}
|
||||
|
|
|
@ -158,10 +158,12 @@ public class AccountTest {
|
|||
});
|
||||
}
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void forever() throws Exception{
|
||||
while (true) Thread.sleep(5000);
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void returnToAppFromQueryParam() {
|
||||
|
|
Loading…
Reference in a new issue