use secrets
This commit is contained in:
parent
f66060e1be
commit
0cdd5e857e
43 changed files with 435 additions and 398 deletions
|
@ -329,9 +329,6 @@ module.config([ '$routeProvider', function($routeProvider) {
|
|||
},
|
||||
application : function(ApplicationLoader) {
|
||||
return ApplicationLoader();
|
||||
},
|
||||
installation : function(ApplicationInstallationLoader) {
|
||||
return ApplicationInstallationLoader();
|
||||
}
|
||||
},
|
||||
controller : 'ApplicationInstallationCtrl'
|
||||
|
@ -399,9 +396,6 @@ module.config([ '$routeProvider', function($routeProvider) {
|
|||
realm : function(RealmLoader) {
|
||||
return RealmLoader();
|
||||
},
|
||||
application : function(OAuthClientLoader) {
|
||||
return OAuthClientLoader();
|
||||
},
|
||||
oauth : function(OAuthClientLoader) {
|
||||
return OAuthClientLoader();
|
||||
}
|
||||
|
|
|
@ -13,80 +13,25 @@ module.controller('ApplicationRoleListCtrl', function($scope, $location, realm,
|
|||
module.controller('ApplicationCredentialsCtrl', function($scope, $location, realm, application, ApplicationCredentials, Notifications) {
|
||||
$scope.realm = realm;
|
||||
$scope.application = application;
|
||||
|
||||
var required = realm.requiredApplicationCredentials;
|
||||
|
||||
for (var i = 0; i < required.length; i++) {
|
||||
if (required[i] == 'password') {
|
||||
$scope.passwordRequired = true;
|
||||
} else if (required[i] == 'totp') {
|
||||
$scope.totpRequired = true;
|
||||
} else if (required[i] == 'cert') {
|
||||
$scope.certRequired = true;
|
||||
var secret = ApplicationCredentials.get({ realm : realm.realm, application : application.name },
|
||||
function() {
|
||||
$scope.secret = secret.value;
|
||||
}
|
||||
}
|
||||
|
||||
function randomString(len) {
|
||||
var charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
var randomString = '';
|
||||
for (var i = 0; i < len; i++) {
|
||||
var randomPoz = Math.floor(Math.random() * charSet.length);
|
||||
randomString += charSet.substring(randomPoz,randomPoz+1);
|
||||
}
|
||||
return randomString;
|
||||
}
|
||||
|
||||
$scope.generateTotp = function() {
|
||||
$scope.totp = randomString(5) + '-' + randomString(5) + '-' + randomString(5);
|
||||
}
|
||||
);
|
||||
|
||||
$scope.changePassword = function() {
|
||||
if ($scope.password != $scope.confirmPassword) {
|
||||
Notifications.error("Password and confirmation does not match.");
|
||||
$scope.password = "";
|
||||
$scope.confirmPassword = "";
|
||||
return;
|
||||
}
|
||||
var creds = [
|
||||
{
|
||||
type : "password",
|
||||
value : $scope.password
|
||||
}
|
||||
];
|
||||
|
||||
ApplicationCredentials.update({ realm : realm.realm, application : application.name }, creds,
|
||||
var secret = ApplicationCredentials.update({ realm : realm.realm, application : application.name },
|
||||
function() {
|
||||
Notifications.success('The password has been changed.');
|
||||
$scope.password = null;
|
||||
$scope.confirmPassword = null;
|
||||
Notifications.success('The secret has been changed.');
|
||||
$scope.secret = secret.value;
|
||||
},
|
||||
function() {
|
||||
Notifications.error("The password was not changed due to a problem.");
|
||||
$scope.password = null;
|
||||
$scope.confirmPassword = null;
|
||||
Notifications.error("The secret was not changed due to a problem.");
|
||||
$scope.secret = "error";
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
$scope.changeTotp = function() {
|
||||
var creds = [
|
||||
{
|
||||
type : "totp",
|
||||
value : $scope.totp
|
||||
}
|
||||
];
|
||||
|
||||
ApplicationCredentials.update({ realm : realm.realm, application : application.name }, creds,
|
||||
function() {
|
||||
Notifications.success('The totp was changed.');
|
||||
$scope.totp = null;
|
||||
},
|
||||
function() {
|
||||
Notifications.error("The totp was not changed due to a problem.");
|
||||
$scope.totp = null;
|
||||
}
|
||||
);
|
||||
};
|
||||
$scope.$watch(function() {
|
||||
return $location.path();
|
||||
}, function() {
|
||||
|
@ -163,12 +108,37 @@ module.controller('ApplicationListCtrl', function($scope, realm, applications, A
|
|||
});
|
||||
});
|
||||
|
||||
module.controller('ApplicationInstallationCtrl', function($scope, realm, installation, application, ApplicationInstallation, $routeParams) {
|
||||
module.controller('ApplicationInstallationCtrl', function($scope, realm, application, ApplicationInstallation,ApplicationInstallationJBoss, $http, $routeParams) {
|
||||
console.log('ApplicationInstallationCtrl');
|
||||
$scope.realm = realm;
|
||||
$scope.application = application;
|
||||
$scope.installation = installation;
|
||||
$scope.download = ApplicationInstallation.url({ realm: $routeParams.realm, application: $routeParams.application });
|
||||
$scope.installation = null;
|
||||
$scope.download = null;
|
||||
$scope.configFormat = null;
|
||||
|
||||
$scope.configFormats = [
|
||||
"keycloak.json",
|
||||
"Wildfly/JBoss Subsystem XML"
|
||||
];
|
||||
|
||||
$scope.changeFormat = function() {
|
||||
if ($scope.configFormat == "keycloak.json") {
|
||||
var url = ApplicationInstallation.url({ realm: $routeParams.realm, application: $routeParams.application });
|
||||
var installation = $http.get(url).success(function(data) {
|
||||
var tmp = angular.fromJson(data);
|
||||
$scope.installation = angular.toJson(tmp, true);
|
||||
})
|
||||
$scope.download = url;
|
||||
} else if ($scope.configFormat == "Wildfly/JBoss Subsystem XML") {
|
||||
var url = ApplicationInstallationJBoss.url({ realm: $routeParams.realm, application: $routeParams.application });
|
||||
var installation = $http.get(url).success(function(data) {
|
||||
$scope.installation = data;
|
||||
})
|
||||
$scope.download = url;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
module.controller('ApplicationDetailCtrl', function($scope, realm, application, Application, $location, Dialog, Notifications) {
|
||||
|
|
|
@ -2,84 +2,31 @@ module.controller('OAuthClientCredentialsCtrl', function($scope, $location, real
|
|||
$scope.realm = realm;
|
||||
$scope.oauth = oauth;
|
||||
|
||||
var required = realm.requiredOAuthClientCredentials;
|
||||
|
||||
for (var i = 0; i < required.length; i++) {
|
||||
if (required[i] == 'password') {
|
||||
$scope.passwordRequired = true;
|
||||
} else if (required[i] == 'totp') {
|
||||
$scope.totpRequired = true;
|
||||
} else if (required[i] == 'cert') {
|
||||
$scope.certRequired = true;
|
||||
var secret = OAuthClientCredentials.get({ realm : realm.realm, oauth : oauth.id },
|
||||
function() {
|
||||
$scope.secret = secret.value;
|
||||
}
|
||||
}
|
||||
|
||||
function randomString(len) {
|
||||
var charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
var randomString = '';
|
||||
for (var i = 0; i < len; i++) {
|
||||
var randomPoz = Math.floor(Math.random() * charSet.length);
|
||||
randomString += charSet.substring(randomPoz,randomPoz+1);
|
||||
}
|
||||
return randomString;
|
||||
}
|
||||
|
||||
$scope.generateTotp = function() {
|
||||
$scope.totp = randomString(5) + '-' + randomString(5) + '-' + randomString(5);
|
||||
}
|
||||
);
|
||||
|
||||
$scope.changePassword = function() {
|
||||
if ($scope.password != $scope.confirmPassword) {
|
||||
Notifications.error("Password and confirmation does not match.");
|
||||
$scope.password = "";
|
||||
$scope.confirmPassword = "";
|
||||
return;
|
||||
}
|
||||
var creds = [
|
||||
{
|
||||
type : "password",
|
||||
value : $scope.password
|
||||
}
|
||||
];
|
||||
|
||||
OAuthClientCredentials.update({ realm : realm.realm, oauth : oauth.id }, creds,
|
||||
var secret = OAuthClientCredentials.update({ realm : realm.realm, oauth : oauth.id },
|
||||
function() {
|
||||
Notifications.success('The password has been changed.');
|
||||
$scope.password = null;
|
||||
$scope.confirmPassword = null;
|
||||
Notifications.success('The secret has been changed.');
|
||||
$scope.secret = secret.value;
|
||||
},
|
||||
function() {
|
||||
Notifications.error("The password was not changed due to a problem.");
|
||||
$scope.password = null;
|
||||
$scope.confirmPassword = null;
|
||||
Notifications.error("The secret was not changed due to a problem.");
|
||||
$scope.secret = "error";
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
$scope.changeTotp = function() {
|
||||
var creds = [
|
||||
{
|
||||
type : "totp",
|
||||
value : $scope.totp
|
||||
}
|
||||
];
|
||||
|
||||
OAuthClientCredentials.update({ realm : realm.realm, oauth : oauth.id }, creds,
|
||||
function() {
|
||||
Notifications.success('The totp was changed.');
|
||||
$scope.totp = null;
|
||||
},
|
||||
function() {
|
||||
Notifications.error("The totp was not changed due to a problem.");
|
||||
$scope.totp = null;
|
||||
}
|
||||
);
|
||||
};
|
||||
$scope.$watch(function() {
|
||||
return $location.path();
|
||||
}, function() {
|
||||
$scope.path = $location.path().substring(1).split("/");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
module.controller('OAuthClientListCtrl', function($scope, realm, oauthClients, OAuthClient, $location) {
|
||||
|
|
|
@ -464,29 +464,31 @@ module.factory('Application', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('ApplicationInstallation', function($resource) {
|
||||
var url = '/auth/rest/admin/realms/:realm/applications/:application/installation';
|
||||
var resource = $resource('/auth/rest/admin/realms/:realm/applications/:application/installation', {
|
||||
realm : '@realm',
|
||||
application : '@application'
|
||||
}, {
|
||||
update : {
|
||||
method : 'PUT'
|
||||
var url = '/auth/rest/admin/realms/:realm/applications/:application/installation/json';
|
||||
return {
|
||||
url : function(parameters)
|
||||
{
|
||||
return url.replace(':realm', parameters.realm).replace(':application', parameters.application);
|
||||
}
|
||||
});
|
||||
resource.url = function(parameters) {
|
||||
}
|
||||
});
|
||||
module.factory('ApplicationInstallationJBoss', function($resource) {
|
||||
var url = '/auth/rest/admin/realms/:realm/applications/:application/installation/jboss';
|
||||
return {
|
||||
url : function(parameters)
|
||||
{
|
||||
return url.replace(':realm', parameters.realm).replace(':application', parameters.application);
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
});
|
||||
|
||||
module.factory('ApplicationCredentials', function($resource) {
|
||||
return $resource('/auth/rest/admin/realms/:realm/applications/:application/credentials', {
|
||||
return $resource('/auth/rest/admin/realms/:realm/applications/:application/client-secret', {
|
||||
realm : '@realm',
|
||||
application : '@application'
|
||||
}, {
|
||||
update : {
|
||||
method : 'PUT',
|
||||
isArray : true
|
||||
method : 'POST'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -515,15 +517,15 @@ module.factory('OAuthClient', function($resource) {
|
|||
});
|
||||
|
||||
module.factory('OAuthClientCredentials', function($resource) {
|
||||
return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/credentials', {
|
||||
return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/client-secret', {
|
||||
realm : '@realm',
|
||||
oauth : '@oauth'
|
||||
}, {
|
||||
update : {
|
||||
method : 'PUT',
|
||||
isArray : true
|
||||
method : 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
module.factory('OAuthClientRealmScopeMapping', function($resource) {
|
||||
|
|
|
@ -17,42 +17,20 @@
|
|||
</ol>
|
||||
<h2 data-ng-hide="create"><span>{{application.name}}</span> Credentials</h2>
|
||||
<form class="form-horizontal" name="credentialForm" novalidate>
|
||||
<fieldset data-ng-show="passwordRequired">
|
||||
<legend><span class="text">Change Password</span></legend>
|
||||
<fieldset >
|
||||
<legend><span class="text">Client Secret</span></legend>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="password">New Password</label>
|
||||
<label class="col-sm-2 control-label" for="secret">Secret</label>
|
||||
<div class="col-sm-4">
|
||||
<input class="form-control" type="password" id="password" name="password" data-ng-model="password" autofocus
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="password">New Password Confirmation</label>
|
||||
<div class="col-sm-4">
|
||||
<input class="form-control" type="password" id="confirmPassword" name="confirmPassword" data-ng-model="confirmPassword"
|
||||
<input ng-disabled="true" class="form-control" type="text" id="secret" name="secret" data-ng-model="secret" autofocus
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="pull-right form-actions" ng-show="password != null">
|
||||
<button type="submit" data-ng-click="changePassword()" class="btn btn-primary btn-lg">Change Password
|
||||
<div class="pull-right form-actions">
|
||||
<button type="submit" data-ng-click="changePassword()" class="btn btn-primary btn-lg">Regenerate Secret
|
||||
</button>
|
||||
</div>
|
||||
<fieldset data-ng-show="totpRequired">
|
||||
<legend uncollapsed><span class="text">Change TOTP Key</span></legend>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="totp">New Key</label>
|
||||
<div class="col-sm-4">
|
||||
<input class="form-control" type="text" id="totp" name="totp" data-ng-model="totp" autofocus
|
||||
required>
|
||||
<button class="btn btn-primary" type="submit" data-ng-click="generateTotp()">Generate
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="pull-right form-actions" ng-show="totp != null">
|
||||
<button type="submit" data-ng-click="changeTotp()" class="btn btn-primary btn-lg">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -19,15 +19,27 @@
|
|||
<h2>Application Installation</h2>
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
<div class="form-group input-select">
|
||||
<label class="col-sm-2 control-label" for="configFormats">Format Option</label>
|
||||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<div class="select-kc">
|
||||
<select id="configFormats" name="configFormats" ng-change="changeFormat()" ng-model="configFormat" ng-options="a for a in configFormats">
|
||||
<option value="" selected> Select a Format </option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-show="installation">
|
||||
<div class="col-sm-12">
|
||||
<textarea class="form-control" rows="20" kc-select-action="click">{{installation | json}}</textarea>
|
||||
<textarea class="form-control" rows="20" kc-select-action="click">{{installation}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<div class="pull-right form-actions">
|
||||
<div class="pull-right form-actions" ng-show="installation">
|
||||
<a class="btn btn-primary btn-lg" href="{{download}}" download="keycloak.json" type="submit">Download</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -16,43 +16,19 @@
|
|||
</ol>
|
||||
<h2 data-ng-hide="create"><span>{{oauth.name}}</span> Credentials</h2>
|
||||
<form class="form-horizontal" name="credentialForm" novalidate>
|
||||
<fieldset data-ng-show="passwordRequired">
|
||||
<legend><span class="text">Change Password</span></legend>
|
||||
<fieldset >
|
||||
<legend><span class="text">Client Secret</span></legend>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="password">New Password</label>
|
||||
<label class="col-sm-2 control-label" for="secret">Secret</label>
|
||||
<div class="col-sm-4">
|
||||
<input class="form-control" type="password" id="password" name="password" data-ng-model="password" autofocus
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label two-lines" for="password">New Password Confirmation</label>
|
||||
<div class="col-sm-4">
|
||||
<input class="form-control" type="password" id="confirmPassword" name="confirmPassword" data-ng-model="confirmPassword"
|
||||
<input ng-disabled="true" class="form-control" type="text" id="secret" name="secret" data-ng-model="secret" autofocus
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="pull-right form-actions" ng-show="password != null">
|
||||
<button class="btn btn-primary btn-lg" type="submit" data-ng-click="changePassword()" ng-show="password != null">Change Password</button>
|
||||
</div>
|
||||
|
||||
<fieldset data-ng-show="totpRequired">
|
||||
<legend uncollapsed><span class="text">Change TOTP Key</span></legend>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="totp">New Key</label>
|
||||
<div class="col-sm-4">
|
||||
<input class="form-control" type="text" id="totp" name="totp" data-ng-model="totp" autofocus
|
||||
required>
|
||||
<button class="btn btn-primary" type="submit" data-ng-click="generateTotp()">Generate
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="pull-right form-actions" ng-show="totp != null">
|
||||
<button class="btn btn-primary btn-lg" type="submit" data-ng-click="changeTotp()" ng-show="totp != null">Save</button>
|
||||
<div class="pull-right form-actions">
|
||||
<button type="submit" data-ng-click="changePassword()" class="btn btn-primary btn-lg">Regenerate Secret
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -19,20 +19,6 @@
|
|||
<input id="user" type="text" ui-select2="userCredentialOptions" ng-model="realm.requiredCredentials" placeholder="Type a role and enter">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="application" class="control-label two-lines">Required Application Credentials</label>
|
||||
|
||||
<div class="col-sm-4">
|
||||
<input id="application" type="text" ui-select2="userCredentialOptions" ng-model="realm.requiredApplicationCredentials" placeholder="Type a role and enter">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="oauth" class="control-label two-lines">Required OAuth Credentials</label>
|
||||
|
||||
<div class="col-sm-4">
|
||||
<input id="oauth" type="text" ui-select2="userCredentialOptions" ng-model="realm.requiredOAuthClientCredentials" placeholder="Type a role and enter">
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="border-top">
|
||||
<legend uncollapsed><span class="text">Realm Password Policy</span></legend>
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.keycloak;
|
|||
import org.keycloak.util.KeycloakUriBuilder;
|
||||
|
||||
import java.security.KeyStore;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
|
@ -13,7 +14,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
public class AbstractOAuthClient {
|
||||
public static final String OAUTH_TOKEN_REQUEST_STATE = "OAuth_Token_Request_State";
|
||||
protected String clientId;
|
||||
protected String password;
|
||||
protected Map<String, String> credentials;
|
||||
protected KeyStore truststore;
|
||||
protected String authUrl;
|
||||
protected String codeUrl;
|
||||
|
@ -35,12 +36,12 @@ public class AbstractOAuthClient {
|
|||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
public Map<String, String> getCredentials() {
|
||||
return credentials;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
public void setCredentials(Map<String, String> credentials) {
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
public KeyStore getTruststore() {
|
||||
|
|
|
@ -5,6 +5,7 @@ package org.keycloak.representations.idm;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CredentialRepresentation {
|
||||
public static final String SECRET = "secret";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String TOTP = "totp";
|
||||
public static final String CLIENT_CERT = "cert";
|
||||
|
|
|
@ -28,8 +28,6 @@ public class RealmRepresentation {
|
|||
protected RolesRepresentation roles;
|
||||
protected List<String> defaultRoles;
|
||||
protected Set<String> requiredCredentials;
|
||||
protected Set<String> requiredApplicationCredentials;
|
||||
protected Set<String> requiredOAuthClientCredentials;
|
||||
protected String passwordPolicy;
|
||||
protected List<UserRepresentation> users;
|
||||
protected List<UserRoleMappingRepresentation> roleMappings;
|
||||
|
@ -168,22 +166,6 @@ public class RealmRepresentation {
|
|||
this.requiredCredentials = requiredCredentials;
|
||||
}
|
||||
|
||||
public Set<String> getRequiredApplicationCredentials() {
|
||||
return requiredApplicationCredentials;
|
||||
}
|
||||
|
||||
public void setRequiredApplicationCredentials(Set<String> requiredApplicationCredentials) {
|
||||
this.requiredApplicationCredentials = requiredApplicationCredentials;
|
||||
}
|
||||
|
||||
public Set<String> getRequiredOAuthClientCredentials() {
|
||||
return requiredOAuthClientCredentials;
|
||||
}
|
||||
|
||||
public void setRequiredOAuthClientCredentials(Set<String> requiredOAuthClientCredentials) {
|
||||
this.requiredOAuthClientCredentials = requiredOAuthClientCredentials;
|
||||
}
|
||||
|
||||
public String getPasswordPolicy() {
|
||||
return passwordPolicy;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,6 @@
|
|||
"ssl-not-required": true,
|
||||
"expose-token": true,
|
||||
"credentials": {
|
||||
"password": "password"
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
"auth-server-url" : "http://localhost:8080/auth",
|
||||
"ssl-not-required" : true,
|
||||
"credentials" : {
|
||||
"password" : "password"
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
<secure-deployment name="customer-portal.war">
|
||||
<realm>demo</realm>
|
||||
<resource>customer-portal</resource>
|
||||
<credential name="password">password</credential>
|
||||
<credential name="secret">password</credential>
|
||||
</secure-deployment>
|
||||
<secure-deployment name="product-portal.war">
|
||||
<realm>demo</realm>
|
||||
<resource>product-portal</resource>
|
||||
<credential name="password">password</credential>
|
||||
<credential name="secret">password</credential>
|
||||
</secure-deployment>
|
||||
<secure-deployment name="database.war">
|
||||
<realm>demo</realm>
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
"privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
|
||||
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"requiredCredentials": [ "password" ],
|
||||
"requiredApplicationCredentials": [ "password" ],
|
||||
"requiredOAuthClientCredentials": [ "password" ],
|
||||
"users" : [
|
||||
{
|
||||
"username" : "bburke@redhat.com",
|
||||
|
@ -66,7 +64,7 @@
|
|||
"adminUrl": "http://localhost:8080/customer-portal",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
@ -77,7 +75,7 @@
|
|||
"adminUrl": "http://localhost:8080/product-portal",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
@ -89,7 +87,7 @@
|
|||
"enabled": true,
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"auth-server-url" : "http://localhost:8080/auth",
|
||||
"ssl-not-required" : true,
|
||||
"credentials" : {
|
||||
"password" : "password"
|
||||
"secret": "password"
|
||||
},
|
||||
"scope": {
|
||||
"realm": [ "user" ]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"auth-server-url" : "http://localhost:8080/auth",
|
||||
"ssl-not-required" : true,
|
||||
"credentials" : {
|
||||
"password" : "password"
|
||||
"secret": "password"
|
||||
},
|
||||
"scope": {
|
||||
"realm": [ "user" ]
|
||||
|
|
|
@ -57,11 +57,12 @@ public class TokenGrantRequest {
|
|||
public static AccessTokenResponse invoke(HttpClient client, String code, String codeUrl, String redirectUri, String client_id, Map<String, String> credentials) throws IOException, HttpFailure {
|
||||
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
||||
redirectUri = stripOauthParametersFromRedirect(redirectUri);
|
||||
String password = credentials.get("password");
|
||||
for (Map.Entry<String, String> entry : credentials.entrySet()) {
|
||||
formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
formparams.add(new BasicNameValuePair("grant_type", "authorization_code"));
|
||||
formparams.add(new BasicNameValuePair("code", code));
|
||||
formparams.add(new BasicNameValuePair("client_id", client_id));
|
||||
formparams.add(new BasicNameValuePair(CredentialRepresentation.PASSWORD, password));
|
||||
formparams.add(new BasicNameValuePair("redirect_uri", redirectUri));
|
||||
HttpResponse response = null;
|
||||
UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
|
||||
|
|
|
@ -28,7 +28,7 @@ public abstract class OAuthClientConfigLoader extends RealmConfigurationLoader {
|
|||
|
||||
public void configureOAuthClient(AbstractOAuthClient oauthClient) {
|
||||
oauthClient.setClientId(adapterConfig.getResource());
|
||||
oauthClient.setPassword(adapterConfig.getCredentials().get("password"));
|
||||
oauthClient.setCredentials(adapterConfig.getCredentials());
|
||||
if (adapterConfig.getAuthServerUrl() == null) {
|
||||
throw new RuntimeException("You must specify auth-url");
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.jboss.resteasy.logging.Logger;
|
|||
import org.jboss.resteasy.util.BasicAuthHelper;
|
||||
import org.keycloak.AbstractOAuthClient;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
|
||||
import javax.ws.rs.BadRequestException;
|
||||
import javax.ws.rs.InternalServerErrorException;
|
||||
|
@ -19,6 +20,7 @@ import javax.ws.rs.core.UriBuilder;
|
|||
import javax.ws.rs.core.UriInfo;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Helper code to obtain oauth access tokens via browser redirects
|
||||
|
@ -58,14 +60,15 @@ public class JaxrsOAuthClient extends AbstractOAuthClient {
|
|||
|
||||
public String resolveBearerToken(String redirectUri, String code) {
|
||||
redirectUri = stripOauthParametersFromRedirect(redirectUri);
|
||||
String authHeader = BasicAuthHelper.createHeader(clientId, password);
|
||||
Form codeForm = new Form()
|
||||
.param("grant_type", "authorization_code")
|
||||
.param("code", code)
|
||||
.param("client_id", clientId)
|
||||
.param("password", password)
|
||||
.param("redirect_uri", redirectUri);
|
||||
Response res = client.target(codeUrl).request().header(HttpHeaders.AUTHORIZATION, authHeader).post(Entity.form(codeForm));
|
||||
for (Map.Entry<String, String> entry : credentials.entrySet()) {
|
||||
codeForm.param(entry.getKey(), entry.getValue());
|
||||
}
|
||||
Response res = client.target(codeUrl).request().post(Entity.form(codeForm));
|
||||
try {
|
||||
if (res.getStatus() == 400) {
|
||||
throw new BadRequestException();
|
||||
|
|
|
@ -48,8 +48,6 @@ public class ServletOAuthClient extends AbstractOAuthClient {
|
|||
}
|
||||
|
||||
public String resolveBearerToken(String redirectUri, String code) throws IOException, TokenGrantRequest.HttpFailure {
|
||||
Map<String, String> credentials = new HashMap<String, String>();
|
||||
credentials.put("password", password);
|
||||
return TokenGrantRequest.invoke(client, code, codeUrl, redirectUri, clientId, credentials).getToken();
|
||||
}
|
||||
|
||||
|
|
|
@ -170,4 +170,13 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
|
|||
|
||||
void setAccountTheme(String name);
|
||||
|
||||
boolean validateSecret(UserModel user, String secret);
|
||||
|
||||
/**
|
||||
* Secrets can be viewed. They are used by confidential Applications and OAuth clients
|
||||
*
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
UserCredentialModel getSecret(UserModel user);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ public class RequiredCredentialModel {
|
|||
public static final RequiredCredentialModel PASSWORD;
|
||||
public static final RequiredCredentialModel TOTP;
|
||||
public static final RequiredCredentialModel CLIENT_CERT;
|
||||
public static final RequiredCredentialModel SECRET;
|
||||
|
||||
static {
|
||||
Map<String, RequiredCredentialModel> map = new HashMap<String, RequiredCredentialModel>();
|
||||
|
@ -62,6 +63,12 @@ public class RequiredCredentialModel {
|
|||
PASSWORD.setSecret(true);
|
||||
PASSWORD.setFormLabel("password");
|
||||
map.put(PASSWORD.getType(), PASSWORD);
|
||||
SECRET = new RequiredCredentialModel();
|
||||
SECRET.setType(UserCredentialModel.SECRET);
|
||||
SECRET.setInput(false);
|
||||
SECRET.setSecret(true);
|
||||
SECRET.setFormLabel("secret");
|
||||
map.put(SECRET.getType(), SECRET);
|
||||
TOTP = new RequiredCredentialModel();
|
||||
TOTP.setType(UserCredentialModel.TOTP);
|
||||
TOTP.setInput(true);
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UserCredentialModel {
|
||||
public static final String PASSWORD = "password";
|
||||
|
||||
// Secret is same as password but it is not hashed
|
||||
public static final String SECRET = "secret";
|
||||
public static final String TOTP = "totp";
|
||||
public static final String CLIENT_CERT = "cert";
|
||||
|
||||
|
@ -23,6 +28,20 @@ public class UserCredentialModel {
|
|||
return model;
|
||||
}
|
||||
|
||||
public static UserCredentialModel secret(String password) {
|
||||
UserCredentialModel model = new UserCredentialModel();
|
||||
model.setType(SECRET);
|
||||
model.setValue(password);
|
||||
return model;
|
||||
}
|
||||
|
||||
public static UserCredentialModel generateSecret() {
|
||||
UserCredentialModel model = new UserCredentialModel();
|
||||
model.setType(SECRET);
|
||||
model.setValue(UUID.randomUUID().toString());
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
|
|
|
@ -996,6 +996,17 @@ public class RealmAdapter implements RealmModel {
|
|||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserCredentialModel getSecret(UserModel user) {
|
||||
for (CredentialEntity cred : ((UserAdapter)user).getUser().getCredentials()) {
|
||||
if (cred.getType().equals(UserCredentialModel.SECRET)) {
|
||||
return UserCredentialModel.secret(cred.getValue());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validatePassword(UserModel user, String password) {
|
||||
for (CredentialEntity cred : ((UserAdapter)user).getUser().getCredentials()) {
|
||||
|
@ -1006,6 +1017,18 @@ public class RealmAdapter implements RealmModel {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateSecret(UserModel user, String secret) {
|
||||
for (CredentialEntity cred : ((UserAdapter)user).getUser().getCredentials()) {
|
||||
if (cred.getType().equals(UserCredentialModel.SECRET)) {
|
||||
return secret.equals(cred.getValue());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean validateTOTP(UserModel user, String password, String token) {
|
||||
if (!validatePassword(user, password)) return false;
|
||||
|
|
|
@ -769,6 +769,29 @@ public class RealmAdapter extends AbstractAdapter implements RealmModel {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateSecret(UserModel user, String secret) {
|
||||
for (CredentialEntity cred : ((UserAdapter)user).getUser().getCredentials()) {
|
||||
if (cred.getType().equals(UserCredentialModel.SECRET)) {
|
||||
return secret.equals(cred.getValue());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserCredentialModel getSecret(UserModel user) {
|
||||
for (CredentialEntity cred : ((UserAdapter)user).getUser().getCredentials()) {
|
||||
if (cred.getType().equals(UserCredentialModel.SECRET)) {
|
||||
return UserCredentialModel.secret(cred.getValue());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void updateCredential(UserModel user, UserCredentialModel cred) {
|
||||
CredentialEntity credentialEntity = null;
|
||||
|
|
|
@ -151,8 +151,8 @@ public class ImportTest extends AbstractModelTest {
|
|||
Assert.assertFalse(realm.isUpdateProfileOnInitialSocialLogin());
|
||||
Assert.assertEquals(600, realm.getAccessCodeLifespanUserAction());
|
||||
verifyRequiredCredentials(realm.getRequiredCredentials(), "password");
|
||||
verifyRequiredCredentials(realm.getRequiredApplicationCredentials(), "totp");
|
||||
verifyRequiredCredentials(realm.getRequiredOAuthClientCredentials(), "cert");
|
||||
verifyRequiredCredentials(realm.getRequiredApplicationCredentials(), "secret");
|
||||
verifyRequiredCredentials(realm.getRequiredOAuthClientCredentials(), "secret");
|
||||
}
|
||||
|
||||
private void verifyRequiredCredentials(List<RequiredCredentialModel> requiredCreds, String expectedType) {
|
||||
|
|
12
model/tests/src/test/resources/testcomposites.json
Normal file → Executable file
12
model/tests/src/test/resources/testcomposites.json
Normal file → Executable file
|
@ -9,8 +9,6 @@
|
|||
"registrationAllowed": true,
|
||||
"resetPasswordAllowed": true,
|
||||
"requiredCredentials": [ "password" ],
|
||||
"requiredApplicationCredentials": [ "password" ],
|
||||
"requiredOAuthClientCredentials": [ "password" ],
|
||||
"smtpServer": {
|
||||
"from": "auto@keycloak.org",
|
||||
"host": "localhost",
|
||||
|
@ -68,7 +66,7 @@
|
|||
"name" : "third-party",
|
||||
"enabled": true,
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
{ "type" : "secret",
|
||||
"value" : "password" }
|
||||
]
|
||||
}
|
||||
|
@ -109,7 +107,7 @@
|
|||
"adminUrl": "http://localhost:8081/app/logout",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
@ -121,7 +119,7 @@
|
|||
"adminUrl": "http://localhost:8081/app/logout",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
@ -133,7 +131,7 @@
|
|||
"adminUrl": "http://localhost:8081/app/logout",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
@ -145,7 +143,7 @@
|
|||
"adminUrl": "http://localhost:8081/app/logout",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
"privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
|
||||
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"requiredCredentials": [ "password" ],
|
||||
"requiredApplicationCredentials": [ "totp" ],
|
||||
"requiredOAuthClientCredentials": [ "cert" ],
|
||||
"users" : [
|
||||
{
|
||||
"username" : "bburke@redhat.com",
|
||||
|
@ -29,7 +27,7 @@
|
|||
"name" : "third-party",
|
||||
"enabled": true,
|
||||
"credentials" : [
|
||||
{ "type" : "Password",
|
||||
{ "type" : "secret",
|
||||
"value" : "password" }
|
||||
]
|
||||
}
|
||||
|
@ -66,9 +64,8 @@
|
|||
"adminUrl": "http://localhost:8080/customer-portal/j_admin_request",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "totp",
|
||||
"value": "12345",
|
||||
"device": "67890"
|
||||
"type": "secret",
|
||||
"value": "12345"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -78,9 +75,8 @@
|
|||
"adminUrl": "http://localhost:8080/product-portal/j_admin_request",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "totp",
|
||||
"value": "12345",
|
||||
"device": "67890"
|
||||
"type": "secret",
|
||||
"value": "12345"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
"accessCodeLifespan": 30,
|
||||
"accessCodeLifespanUserAction": 600,
|
||||
"requiredCredentials": [ "password" ],
|
||||
"requiredApplicationCredentials": [ "password" ],
|
||||
"requiredOAuthClientCredentials": [ "password" ],
|
||||
"defaultRoles": [ "foo", "bar" ],
|
||||
"verifyEmail" : "true",
|
||||
"users": [
|
||||
|
@ -83,7 +81,7 @@
|
|||
"name" : "oauthclient",
|
||||
"enabled": true,
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
{ "type" : "secret",
|
||||
"value" : "clientpassword" }
|
||||
]
|
||||
}
|
||||
|
|
|
@ -58,16 +58,10 @@ public class ApplianceBootstrap {
|
|||
realm.setLoginTheme("keycloak");
|
||||
realm.setAccountTheme("keycloak");
|
||||
|
||||
ApplicationModel adminConsole = realm.addApplication(Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
ApplicationModel adminConsole = new ApplicationManager(manager).createApplication(realm, Constants.ADMIN_CONSOLE_APPLICATION);
|
||||
adminConsole.setBaseUrl("/auth/admin/index.html");
|
||||
adminConsole.setEnabled(true);
|
||||
UserCredentialModel adminConsolePassword = new UserCredentialModel();
|
||||
adminConsolePassword.setType(UserCredentialModel.PASSWORD);
|
||||
adminConsolePassword.setValue(UUID.randomUUID().toString()); // just a random password as we'll never access it
|
||||
realm.updateCredential(adminConsole.getApplicationUser(), adminConsolePassword);
|
||||
|
||||
RoleModel applicationRole = realm.getRole(Constants.APPLICATION_ROLE);
|
||||
realm.grantRole(adminConsole.getApplicationUser(), applicationRole);
|
||||
RoleModel adminRole = adminConsole.addRole(Constants.ADMIN_CONSOLE_ADMIN_ROLE);
|
||||
|
||||
UserModel adminUser = realm.addUser("admin");
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.keycloak.services.managers;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
import org.codehaus.jackson.annotate.JsonPropertyOrder;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Constants;
|
||||
|
@ -7,7 +9,9 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.SkeletonKeyScope;
|
||||
import org.keycloak.representations.adapters.config.BaseAdapterConfig;
|
||||
import org.keycloak.representations.adapters.config.BaseRealmConfig;
|
||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
|
@ -22,6 +26,7 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -36,6 +41,10 @@ public class ApplicationManager {
|
|||
this.realmManager = realmManager;
|
||||
}
|
||||
|
||||
public ApplicationManager() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Does not create scope or role mappings!
|
||||
*
|
||||
|
@ -54,14 +63,18 @@ public class ApplicationManager {
|
|||
applicationModel.updateApplication();
|
||||
|
||||
UserModel resourceUser = applicationModel.getApplicationUser();
|
||||
if (resourceRep.getCredentials() != null) {
|
||||
if (resourceRep.getCredentials() != null && resourceRep.getCredentials().size() > 0) {
|
||||
for (CredentialRepresentation cred : resourceRep.getCredentials()) {
|
||||
UserCredentialModel credential = new UserCredentialModel();
|
||||
credential.setType(cred.getType());
|
||||
credential.setValue(cred.getValue());
|
||||
realm.updateCredential(resourceUser, credential);
|
||||
}
|
||||
} else {
|
||||
generateSecret(realm, applicationModel);
|
||||
}
|
||||
|
||||
|
||||
if (resourceRep.getRedirectUris() != null) {
|
||||
for (String redirectUri : resourceRep.getRedirectUris()) {
|
||||
resourceUser.addRedirectUri(redirectUri);
|
||||
|
@ -122,9 +135,17 @@ public class ApplicationManager {
|
|||
RoleModel loginRole = realm.getRole(Constants.APPLICATION_ROLE);
|
||||
ApplicationModel app = realm.addApplication(name);
|
||||
realm.grantRole(app.getApplicationUser(), loginRole);
|
||||
generateSecret(realm, app);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
public UserCredentialModel generateSecret(RealmModel realm, ApplicationModel app) {
|
||||
UserCredentialModel secret = UserCredentialModel.generateSecret();
|
||||
realm.updateCredential(app.getApplicationUser(), secret);
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void updateApplication(ApplicationRepresentation rep, ApplicationModel resource) {
|
||||
resource.setName(rep.getName());
|
||||
resource.setEnabled(rep.isEnabled());
|
||||
|
@ -175,8 +196,45 @@ public class ApplicationManager {
|
|||
|
||||
}
|
||||
|
||||
public BaseAdapterConfig toInstallationRepresentation(RealmModel realmModel, ApplicationModel applicationModel, URI baseUri) {
|
||||
BaseAdapterConfig rep = new BaseAdapterConfig();
|
||||
@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required",
|
||||
"resource", "credentials",
|
||||
"use-resource-role-mappings"})
|
||||
public static class InstallationAdapterConfig extends BaseRealmConfig {
|
||||
@JsonProperty("resource")
|
||||
protected String resource;
|
||||
@JsonProperty("use-resource-role-mappings")
|
||||
protected boolean useResourceRoleMappings;
|
||||
@JsonProperty("credentials")
|
||||
protected Map<String, String> credentials = new HashMap<String, String>();
|
||||
|
||||
public boolean isUseResourceRoleMappings() {
|
||||
return useResourceRoleMappings;
|
||||
}
|
||||
|
||||
public void setUseResourceRoleMappings(boolean useResourceRoleMappings) {
|
||||
this.useResourceRoleMappings = useResourceRoleMappings;
|
||||
}
|
||||
|
||||
public String getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void setResource(String resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
public Map<String, String> getCredentials() {
|
||||
return credentials;
|
||||
}
|
||||
|
||||
public void setCredentials(Map<String, String> credentials) {
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public InstallationAdapterConfig toInstallationRepresentation(RealmModel realmModel, ApplicationModel applicationModel, URI baseUri) {
|
||||
InstallationAdapterConfig rep = new InstallationAdapterConfig();
|
||||
rep.setRealm(realmModel.getName());
|
||||
rep.setRealmKey(realmModel.getPublicKeyPem());
|
||||
rep.setSslNotRequired(realmModel.isSslNotRequired());
|
||||
|
@ -187,12 +245,25 @@ public class ApplicationManager {
|
|||
rep.setResource(applicationModel.getName());
|
||||
|
||||
Map<String, String> creds = new HashMap<String, String>();
|
||||
creds.put(CredentialRepresentation.PASSWORD, "INSERT APPLICATION PASSWORD");
|
||||
if (applicationModel.getApplicationUser().isTotp()) {
|
||||
creds.put(CredentialRepresentation.TOTP, "INSERT APPLICATION TOTP");
|
||||
}
|
||||
String cred = realmModel.getSecret(applicationModel.getApplicationUser()).getValue();
|
||||
creds.put(CredentialRepresentation.SECRET, cred);
|
||||
rep.setCredentials(creds);
|
||||
|
||||
return rep;
|
||||
}
|
||||
|
||||
public String toJBossSubsystemConfig(RealmModel realmModel, ApplicationModel applicationModel, URI baseUri) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("<secure-deployment name=\"WAR MODULE NAME.war\">\n");
|
||||
buffer.append(" <realm>").append(realmModel.getName()).append("</realm>\n");
|
||||
buffer.append(" <realm-public-key>").append(realmModel.getPublicKeyPem()).append("</realm-public-key>\n");
|
||||
buffer.append(" <auth-server-url>").append(baseUri.toString()).append("</auth-server-url>\n");
|
||||
buffer.append(" <ssl-not-required>").append(realmModel.isSslNotRequired()).append("</ssl-not-required>\n");
|
||||
buffer.append(" <resource>").append(applicationModel.getName()).append("</resource>\n");
|
||||
String cred = realmModel.getSecret(applicationModel.getApplicationUser()).getValue();
|
||||
buffer.append(" <credential name=\"secret\">").append(cred).append("</credential>\n");
|
||||
buffer.append("</secure-deployment>\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -298,6 +298,21 @@ public class AuthenticationManager {
|
|||
}
|
||||
}
|
||||
|
||||
if (!user.getRequiredActions().isEmpty()) {
|
||||
return AuthenticationStatus.ACTIONS_REQUIRED;
|
||||
} else {
|
||||
return AuthenticationStatus.SUCCESS;
|
||||
}
|
||||
} else if (types.contains(CredentialRepresentation.SECRET)) {
|
||||
String secret = formData.getFirst(CredentialRepresentation.SECRET);
|
||||
if (secret == null) {
|
||||
logger.warn("Secret not provided");
|
||||
return AuthenticationStatus.MISSING_PASSWORD;
|
||||
}
|
||||
if (!realm.validateSecret(user, secret)) {
|
||||
logger.debug("invalid secret for user: " + user.getLoginName());
|
||||
return AuthenticationStatus.INVALID_CREDENTIALS;
|
||||
}
|
||||
if (!user.getRequiredActions().isEmpty()) {
|
||||
return AuthenticationStatus.ACTIONS_REQUIRED;
|
||||
} else {
|
||||
|
|
|
@ -5,7 +5,9 @@ import org.keycloak.models.Constants;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredCredentialModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
|
@ -95,20 +97,13 @@ public class ModelToRepresentation {
|
|||
rep.getRequiredCredentials().add(cred.getType());
|
||||
}
|
||||
}
|
||||
List<RequiredCredentialModel> requiredResourceCredentialModels = realm.getRequiredApplicationCredentials();
|
||||
if (requiredResourceCredentialModels.size() > 0) {
|
||||
rep.setRequiredApplicationCredentials(new HashSet<String>());
|
||||
for (RequiredCredentialModel cred : requiredResourceCredentialModels) {
|
||||
rep.getRequiredApplicationCredentials().add(cred.getType());
|
||||
}
|
||||
}
|
||||
List<RequiredCredentialModel> requiredOAuthCredentialModels = realm.getRequiredOAuthClientCredentials();
|
||||
if (requiredOAuthCredentialModels.size() > 0) {
|
||||
rep.setRequiredOAuthClientCredentials(new HashSet<String>());
|
||||
for (RequiredCredentialModel cred : requiredOAuthCredentialModels) {
|
||||
rep.getRequiredOAuthClientCredentials().add(cred.getType());
|
||||
}
|
||||
}
|
||||
return rep;
|
||||
}
|
||||
|
||||
public static CredentialRepresentation toRepresentation(UserCredentialModel cred) {
|
||||
CredentialRepresentation rep = new CredentialRepresentation();
|
||||
rep.setType(CredentialRepresentation.SECRET);
|
||||
rep.setValue(cred.getValue());
|
||||
return rep;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.keycloak.services.managers;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
import org.codehaus.jackson.annotate.JsonPropertyOrder;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.OAuthClientModel;
|
||||
|
@ -8,6 +10,7 @@ import org.keycloak.models.RoleModel;
|
|||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.adapters.config.BaseAdapterConfig;
|
||||
import org.keycloak.representations.adapters.config.BaseRealmConfig;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.OAuthClientRepresentation;
|
||||
import org.keycloak.services.resources.flows.Urls;
|
||||
|
@ -83,21 +86,43 @@ public class OAuthClientManager {
|
|||
return rep;
|
||||
}
|
||||
|
||||
public BaseAdapterConfig toInstallationRepresentation(RealmModel realmModel, OAuthClientModel model, URI baseUri) {
|
||||
BaseAdapterConfig rep = new BaseAdapterConfig();
|
||||
@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required",
|
||||
"resource", "credentials"})
|
||||
public static class InstallationAdapterConfig extends BaseRealmConfig {
|
||||
@JsonProperty("resource")
|
||||
protected String resource;
|
||||
@JsonProperty("credentials")
|
||||
protected Map<String, String> credentials = new HashMap<String, String>();
|
||||
|
||||
public String getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void setResource(String resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
public Map<String, String> getCredentials() {
|
||||
return credentials;
|
||||
}
|
||||
|
||||
public void setCredentials(Map<String, String> credentials) {
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public InstallationAdapterConfig toInstallationRepresentation(RealmModel realmModel, OAuthClientModel model, URI baseUri) {
|
||||
InstallationAdapterConfig rep = new InstallationAdapterConfig();
|
||||
rep.setRealm(realmModel.getName());
|
||||
rep.setRealmKey(realmModel.getPublicKeyPem());
|
||||
rep.setSslNotRequired(realmModel.isSslNotRequired());
|
||||
rep.setAuthServerUrl(baseUri.toString());
|
||||
rep.setUseResourceRoleMappings(false);
|
||||
|
||||
rep.setResource(model.getOAuthAgent().getLoginName());
|
||||
|
||||
Map<String, String> creds = new HashMap<String, String>();
|
||||
creds.put(CredentialRepresentation.PASSWORD, "INSERT CLIENT PASSWORD");
|
||||
if (model.getOAuthAgent().isTotp()) {
|
||||
creds.put(CredentialRepresentation.TOTP, "INSERT CLIENT TOTP");
|
||||
}
|
||||
creds.put(CredentialRepresentation.SECRET, realmModel.getSecret(model.getOAuthAgent()).getValue());
|
||||
rep.setCredentials(creds);
|
||||
|
||||
return rep;
|
||||
|
|
|
@ -64,6 +64,7 @@ public class RealmManager {
|
|||
return identitySession.getRealmByName(name);
|
||||
}
|
||||
|
||||
|
||||
public RealmModel createRealm(String name) {
|
||||
return createRealm(name, name);
|
||||
}
|
||||
|
@ -76,6 +77,8 @@ public class RealmManager {
|
|||
realm.addRole(Constants.IDENTITY_REQUESTER_ROLE);
|
||||
|
||||
setupAccountManagement(realm);
|
||||
realm.addRequiredOAuthClientCredential(UserCredentialModel.SECRET);
|
||||
realm.addRequiredResourceCredential(UserCredentialModel.SECRET);
|
||||
|
||||
return realm;
|
||||
}
|
||||
|
@ -108,15 +111,9 @@ public class RealmManager {
|
|||
if (rep.getAccessCodeLifespanUserAction() != null)
|
||||
realm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction());
|
||||
if (rep.getTokenLifespan() != null) realm.setTokenLifespan(rep.getTokenLifespan());
|
||||
if (rep.getRequiredOAuthClientCredentials() != null) {
|
||||
realm.updateRequiredOAuthClientCredentials(rep.getRequiredOAuthClientCredentials());
|
||||
}
|
||||
if (rep.getRequiredCredentials() != null) {
|
||||
realm.updateRequiredCredentials(rep.getRequiredCredentials());
|
||||
}
|
||||
if (rep.getRequiredApplicationCredentials() != null) {
|
||||
realm.updateRequiredApplicationCredentials(rep.getRequiredApplicationCredentials());
|
||||
}
|
||||
realm.setLoginTheme(rep.getLoginTheme());
|
||||
realm.setAccountTheme(rep.getAccountTheme());
|
||||
|
||||
|
@ -142,20 +139,12 @@ public class RealmManager {
|
|||
private void setupAccountManagement(RealmModel realm) {
|
||||
ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
|
||||
if (application == null) {
|
||||
application = realm.addApplication(Constants.ACCOUNT_APPLICATION);
|
||||
application = new ApplicationManager(this).createApplication(realm, Constants.ACCOUNT_APPLICATION);
|
||||
application.setEnabled(true);
|
||||
|
||||
application.addDefaultRole(Constants.ACCOUNT_PROFILE_ROLE);
|
||||
application.addDefaultRole(Constants.ACCOUNT_MANAGE_ROLE);
|
||||
|
||||
UserCredentialModel password = new UserCredentialModel();
|
||||
password.setType(UserCredentialModel.PASSWORD);
|
||||
password.setValue(UUID.randomUUID().toString()); // just a random password as we'll never access it
|
||||
|
||||
realm.updateCredential(application.getApplicationUser(), password);
|
||||
|
||||
RoleModel applicationRole = realm.getRole(Constants.APPLICATION_ROLE);
|
||||
realm.grantRole(application.getApplicationUser(), applicationRole);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,22 +198,6 @@ public class RealmManager {
|
|||
addRequiredCredential(newRealm, CredentialRepresentation.PASSWORD);
|
||||
}
|
||||
|
||||
if (rep.getRequiredApplicationCredentials() != null) {
|
||||
for (String requiredCred : rep.getRequiredApplicationCredentials()) {
|
||||
addResourceRequiredCredential(newRealm, requiredCred);
|
||||
}
|
||||
} else {
|
||||
addResourceRequiredCredential(newRealm, CredentialRepresentation.PASSWORD);
|
||||
}
|
||||
|
||||
if (rep.getRequiredOAuthClientCredentials() != null) {
|
||||
for (String requiredCred : rep.getRequiredOAuthClientCredentials()) {
|
||||
addOAuthClientRequiredCredential(newRealm, requiredCred);
|
||||
}
|
||||
} else {
|
||||
addOAuthClientRequiredCredential(newRealm, CredentialRepresentation.PASSWORD);
|
||||
}
|
||||
|
||||
newRealm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
|
||||
|
||||
if (rep.getUsers() != null) {
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.keycloak.representations.adapters.config.BaseAdapterConfig;
|
|||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.managers.ApplicationManager;
|
||||
import org.keycloak.services.managers.ModelToRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
@ -17,6 +18,8 @@ import org.keycloak.util.JsonSerialization;
|
|||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
|
@ -25,7 +28,6 @@ import javax.ws.rs.core.Context;
|
|||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -73,35 +75,53 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
|
||||
@GET
|
||||
@NoCache
|
||||
@Path("installation")
|
||||
@Path("installation/json")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public String getInstallation() throws IOException {
|
||||
ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session));
|
||||
BaseAdapterConfig rep = applicationManager.toInstallationRepresentation(realm, application, getKeycloakApplication().getBaseUri(uriInfo));
|
||||
Object rep = applicationManager.toInstallationRepresentation(realm, application, getKeycloakApplication().getBaseUri(uriInfo));
|
||||
|
||||
// TODO Temporary solution to pretty-print
|
||||
return JsonSerialization.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rep);
|
||||
}
|
||||
|
||||
@GET
|
||||
@NoCache
|
||||
@Path("installation/jboss")
|
||||
@Produces(MediaType.TEXT_PLAIN)
|
||||
public String getJBossInstallation() throws IOException {
|
||||
ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session));
|
||||
return applicationManager.toJBossSubsystemConfig(realm, application, getKeycloakApplication().getBaseUri(uriInfo));
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@NoCache
|
||||
public void deleteApplication() {
|
||||
realm.removeApplication(application.getId());
|
||||
}
|
||||
|
||||
@Path("credentials")
|
||||
@PUT
|
||||
@Path("client-secret")
|
||||
@POST
|
||||
@Produces("application/json")
|
||||
@Consumes("application/json")
|
||||
public void updateCredentials(List<CredentialRepresentation> credentials) {
|
||||
logger.debug("updateCredentials");
|
||||
if (credentials == null) return;
|
||||
|
||||
for (CredentialRepresentation rep : credentials) {
|
||||
UserCredentialModel cred = RealmManager.fromRepresentation(rep);
|
||||
realm.updateCredential(application.getApplicationUser(), cred);
|
||||
}
|
||||
public CredentialRepresentation regenerateSecret() {
|
||||
logger.debug("regenerateSecret");
|
||||
UserCredentialModel cred = new ApplicationManager().generateSecret(realm, application);
|
||||
CredentialRepresentation rep = ModelToRepresentation.toRepresentation(cred);
|
||||
return rep;
|
||||
}
|
||||
|
||||
@Path("client-secret")
|
||||
@GET
|
||||
@Produces("application/json")
|
||||
public CredentialRepresentation getClientSecret() {
|
||||
logger.debug("getClientSecret");
|
||||
UserCredentialModel model = realm.getSecret(application.getApplicationUser());
|
||||
if (model == null) throw new NotFoundException("Application does not have a secret");
|
||||
return ModelToRepresentation.toRepresentation(model);
|
||||
}
|
||||
|
||||
|
||||
@Path("scope-mappings")
|
||||
public ScopeMappedResource getScopeMappedResource() {
|
||||
return new ScopeMappedResource(realm, application.getApplicationUser(), session);
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.keycloak.representations.adapters.config.BaseAdapterConfig;
|
|||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.OAuthClientRepresentation;
|
||||
import org.keycloak.services.managers.ApplicationManager;
|
||||
import org.keycloak.services.managers.ModelToRepresentation;
|
||||
import org.keycloak.services.managers.OAuthClientManager;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
|
@ -18,6 +19,8 @@ import org.keycloak.util.JsonSerialization;
|
|||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
|
@ -74,7 +77,7 @@ public class OAuthClientResource {
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public String getInstallation() throws IOException {
|
||||
OAuthClientManager manager = new OAuthClientManager(realm);
|
||||
BaseAdapterConfig rep = manager.toInstallationRepresentation(realm, oauthClient, getApplication().getBaseUri(uriInfo));
|
||||
Object rep = manager.toInstallationRepresentation(realm, oauthClient, getApplication().getBaseUri(uriInfo));
|
||||
|
||||
// TODO Temporary solution to pretty-print
|
||||
return JsonSerialization.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rep);
|
||||
|
@ -86,17 +89,26 @@ public class OAuthClientResource {
|
|||
realm.removeOAuthClient(oauthClient.getId());
|
||||
}
|
||||
|
||||
@Path("credentials")
|
||||
@PUT
|
||||
@Path("client-secret")
|
||||
@POST
|
||||
@Produces("application/json")
|
||||
@Consumes("application/json")
|
||||
public void updateCredentials(List<CredentialRepresentation> credentials) {
|
||||
logger.debug("updateCredentials");
|
||||
if (credentials == null) return;
|
||||
public CredentialRepresentation regenerateSecret() {
|
||||
logger.debug("regenerateSecret");
|
||||
UserCredentialModel cred = UserCredentialModel.generateSecret();
|
||||
realm.updateCredential(oauthClient.getOAuthAgent(), cred);
|
||||
CredentialRepresentation rep = ModelToRepresentation.toRepresentation(cred);
|
||||
return rep;
|
||||
}
|
||||
|
||||
for (CredentialRepresentation rep : credentials) {
|
||||
UserCredentialModel cred = RealmManager.fromRepresentation(rep);
|
||||
realm.updateCredential(oauthClient.getOAuthAgent(), cred);
|
||||
}
|
||||
@Path("client-secret")
|
||||
@GET
|
||||
@Produces("application/json")
|
||||
public CredentialRepresentation getClientSecret() {
|
||||
logger.debug("getClientSecret");
|
||||
UserCredentialModel model = realm.getSecret(oauthClient.getOAuthAgent());
|
||||
if (model == null) throw new NotFoundException("Application does not have a secret");
|
||||
return ModelToRepresentation.toRepresentation(model);
|
||||
}
|
||||
|
||||
@Path("scope-mappings")
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.junit.After;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.internet.AddressException;
|
||||
|
@ -14,12 +15,27 @@ import java.io.IOException;
|
|||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.net.SocketException;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public class EmailSenderTest {
|
||||
|
||||
private GreenMail greenMail;
|
||||
private EmailSender emailSender;
|
||||
|
||||
@Test
|
||||
public void testUUID() throws Exception{
|
||||
System.out.println(UUID.randomUUID());
|
||||
|
||||
HashMap<String,String> config = new HashMap<String, String>();
|
||||
config.put("from", "auto@keycloak.org");
|
||||
config.put("host", "localhost");
|
||||
config.put("port", "3025");
|
||||
|
||||
System.out.println(JsonSerialization.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(config));
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ServerSetup setup = new ServerSetup(3025, "localhost", "smtp");
|
||||
|
|
|
@ -125,7 +125,7 @@ public class OAuthClient {
|
|||
parameters.add(new BasicNameValuePair("client_id", clientId));
|
||||
}
|
||||
if (password != null) {
|
||||
parameters.add(new BasicNameValuePair("password", password));
|
||||
parameters.add(new BasicNameValuePair("secret", password));
|
||||
}
|
||||
|
||||
UrlEncodedFormEntity formEntity = null;
|
||||
|
|
|
@ -62,8 +62,6 @@ public class CompositeRoleTest {
|
|||
realm.setAccessCodeLifespan(1000);
|
||||
realm.setSslNotRequired(true);
|
||||
realm.setEnabled(true);
|
||||
realm.addRequiredResourceCredential(UserCredentialModel.PASSWORD);
|
||||
realm.addRequiredOAuthClientCredential(UserCredentialModel.PASSWORD);
|
||||
realm.addRequiredCredential(UserCredentialModel.PASSWORD);
|
||||
final RoleModel realmRole1 = realm.addRole("REALM_ROLE_1");
|
||||
final RoleModel realmRole2 = realm.addRole("REALM_ROLE_2");
|
||||
|
@ -86,21 +84,21 @@ public class CompositeRoleTest {
|
|||
realmComposite1Application.addScope(realmComposite1);
|
||||
realmComposite1Application.setBaseUrl("http://localhost:8081/app");
|
||||
realmComposite1Application.setManagementUrl("http://localhost:8081/app/logout");
|
||||
realm.updateCredential(realmComposite1Application.getApplicationUser(), UserCredentialModel.password("password"));
|
||||
realm.updateCredential(realmComposite1Application.getApplicationUser(), UserCredentialModel.secret("password"));
|
||||
|
||||
final ApplicationModel realmRole1Application = new ApplicationManager(manager).createApplication(realm, "REALM_ROLE_1_APPLICATION");
|
||||
realmRole1Application.setEnabled(true);
|
||||
realmRole1Application.addScope(realmRole1);
|
||||
realmRole1Application.setBaseUrl("http://localhost:8081/app");
|
||||
realmRole1Application.setManagementUrl("http://localhost:8081/app/logout");
|
||||
realm.updateCredential(realmRole1Application.getApplicationUser(), UserCredentialModel.password("password"));
|
||||
realm.updateCredential(realmRole1Application.getApplicationUser(), UserCredentialModel.secret("password"));
|
||||
|
||||
|
||||
final ApplicationModel appRoleApplication = new ApplicationManager(manager).createApplication(realm, "APP_ROLE_APPLICATION");
|
||||
appRoleApplication.setEnabled(true);
|
||||
appRoleApplication.setBaseUrl("http://localhost:8081/app");
|
||||
appRoleApplication.setManagementUrl("http://localhost:8081/app/logout");
|
||||
realm.updateCredential(appRoleApplication.getApplicationUser(), UserCredentialModel.password("password"));
|
||||
realm.updateCredential(appRoleApplication.getApplicationUser(), UserCredentialModel.secret("password"));
|
||||
final RoleModel appRole1 = appRoleApplication.addRole("APP_ROLE_1");
|
||||
final RoleModel appRole2 = appRoleApplication.addRole("APP_ROLE_2");
|
||||
|
||||
|
@ -121,7 +119,7 @@ public class CompositeRoleTest {
|
|||
appCompositeApplication.setEnabled(true);
|
||||
appCompositeApplication.setBaseUrl("http://localhost:8081/app");
|
||||
appCompositeApplication.setManagementUrl("http://localhost:8081/app/logout");
|
||||
realm.updateCredential(appCompositeApplication.getApplicationUser(), UserCredentialModel.password("password"));
|
||||
realm.updateCredential(appCompositeApplication.getApplicationUser(), UserCredentialModel.secret("password"));
|
||||
final RoleModel appCompositeRole = appCompositeApplication.addRole("APP_COMPOSITE_ROLE");
|
||||
appCompositeApplication.addScope(appRole2);
|
||||
appCompositeRole.addCompositeRole(realmRole1);
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
"registrationAllowed": true,
|
||||
"resetPasswordAllowed": true,
|
||||
"requiredCredentials": [ "password" ],
|
||||
"requiredApplicationCredentials": [ "password" ],
|
||||
"requiredOAuthClientCredentials": [ "password" ],
|
||||
"smtpServer": {
|
||||
"from": "auto@keycloak.org",
|
||||
"host": "localhost",
|
||||
|
@ -68,7 +66,7 @@
|
|||
"name" : "third-party",
|
||||
"enabled": true,
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
{ "type" : "secret",
|
||||
"value" : "password" }
|
||||
]
|
||||
}
|
||||
|
@ -109,7 +107,7 @@
|
|||
"adminUrl": "http://localhost:8081/app/logout",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
@ -121,7 +119,7 @@
|
|||
"adminUrl": "http://localhost:8081/app/logout",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
@ -133,7 +131,7 @@
|
|||
"adminUrl": "http://localhost:8081/app/logout",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
@ -145,7 +143,7 @@
|
|||
"adminUrl": "http://localhost:8081/app/logout",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
"privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
|
||||
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"requiredCredentials": [ "password" ],
|
||||
"requiredApplicationCredentials": [ "password" ],
|
||||
"requiredOAuthClientCredentials": [ "password" ],
|
||||
"defaultRoles": [ "user" ],
|
||||
"smtpServer": {
|
||||
"from": "auto@keycloak.org",
|
||||
|
@ -35,7 +33,7 @@
|
|||
"name" : "third-party",
|
||||
"enabled": true,
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
{ "type" : "secret",
|
||||
"value" : "password" }
|
||||
]
|
||||
}
|
||||
|
@ -64,7 +62,7 @@
|
|||
"adminUrl": "http://localhost:8081/app/logout",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"type": "secret",
|
||||
"value": "password"
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue