commit
ea0ceeb65d
26 changed files with 183 additions and 30 deletions
|
@ -21,6 +21,7 @@ public class ApplicationRepresentation {
|
||||||
protected Integer notBefore;
|
protected Integer notBefore;
|
||||||
protected Boolean bearerOnly;
|
protected Boolean bearerOnly;
|
||||||
protected Boolean publicClient;
|
protected Boolean publicClient;
|
||||||
|
protected Boolean fullScopeAllowed;
|
||||||
|
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
@ -134,4 +135,12 @@ public class ApplicationRepresentation {
|
||||||
public void setPublicClient(Boolean publicClient) {
|
public void setPublicClient(Boolean publicClient) {
|
||||||
this.publicClient = publicClient;
|
this.publicClient = publicClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean isFullScopeAllowed() {
|
||||||
|
return fullScopeAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullScopeAllowed(Boolean fullScopeAllowed) {
|
||||||
|
this.fullScopeAllowed = fullScopeAllowed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ public class OAuthClientRepresentation {
|
||||||
protected Integer notBefore;
|
protected Integer notBefore;
|
||||||
protected Boolean publicClient;
|
protected Boolean publicClient;
|
||||||
protected Boolean directGrantsOnly;
|
protected Boolean directGrantsOnly;
|
||||||
|
protected Boolean fullScopeAllowed;
|
||||||
|
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
@ -98,4 +99,13 @@ public class OAuthClientRepresentation {
|
||||||
public void setDirectGrantsOnly(Boolean directGrantsOnly) {
|
public void setDirectGrantsOnly(Boolean directGrantsOnly) {
|
||||||
this.directGrantsOnly = directGrantsOnly;
|
this.directGrantsOnly = directGrantsOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean isFullScopeAllowed() {
|
||||||
|
return fullScopeAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullScopeAllowed(Boolean fullScopeAllowed) {
|
||||||
|
this.fullScopeAllowed = fullScopeAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
7
dependencies/server-all/pom.xml
vendored
7
dependencies/server-all/pom.xml
vendored
|
@ -88,7 +88,12 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- authentication api -->
|
<!-- ldap federation api -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-ldap-federation</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.picketlink</groupId>
|
<groupId>org.picketlink</groupId>
|
||||||
<artifactId>picketlink-common</artifactId>
|
<artifactId>picketlink-common</artifactId>
|
||||||
|
|
|
@ -11,14 +11,18 @@
|
||||||
Authentication SPI has been removed and rewritten. The new SPI is UserFederationProvider and is
|
Authentication SPI has been removed and rewritten. The new SPI is UserFederationProvider and is
|
||||||
more flexible.
|
more flexible.
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
|
||||||
DB Schema has changed again.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<literal>ssl-not-required</literal> property in adapter config has been removed. Replaced with
|
<literal>ssl-not-required</literal> property in adapter config has been removed. Replaced with
|
||||||
<literal>ssl-required</literal>, valid values are <literal>all</literal> (require SSL for all requests), <literal>external</literal>
|
<literal>ssl-required</literal>, valid values are <literal>all</literal> (require SSL for all requests), <literal>external</literal>
|
||||||
(require SSL only for external request) and <literal>none</literal> (SSL not required).
|
(require SSL only for external request) and <literal>none</literal> (SSL not required).
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
DB Schema has changed again.
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
Created applications now have a full scope by default. This means that you don't have to configure
|
||||||
|
the scope of an application if you don't want to.
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</sect1>
|
</sect1>
|
||||||
<sect1>
|
<sect1>
|
||||||
|
|
|
@ -92,28 +92,7 @@
|
||||||
{
|
{
|
||||||
"client": "third-party",
|
"client": "third-party",
|
||||||
"roles": ["user"]
|
"roles": ["user"]
|
||||||
},
|
|
||||||
{
|
|
||||||
"client": "customer-portal",
|
|
||||||
"roles": ["user", "admin" ]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"client": "customer-portal-js",
|
|
||||||
"roles": ["user"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"client": "customer-portal-cli",
|
|
||||||
"roles": ["user"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"client": "angular-product",
|
|
||||||
"roles": ["user"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"client": "product-portal",
|
|
||||||
"roles": ["user", "admin" ]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
"applications": [
|
"applications": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -348,11 +348,12 @@ module.controller('ApplicationDetailCtrl', function($scope, realm, application,
|
||||||
});
|
});
|
||||||
|
|
||||||
module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm, application, applications,
|
module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm, application, applications,
|
||||||
|
Application,
|
||||||
ApplicationRealmScopeMapping, ApplicationApplicationScopeMapping, ApplicationRole,
|
ApplicationRealmScopeMapping, ApplicationApplicationScopeMapping, ApplicationRole,
|
||||||
ApplicationAvailableRealmScopeMapping, ApplicationAvailableApplicationScopeMapping,
|
ApplicationAvailableRealmScopeMapping, ApplicationAvailableApplicationScopeMapping,
|
||||||
ApplicationCompositeRealmScopeMapping, ApplicationCompositeApplicationScopeMapping) {
|
ApplicationCompositeRealmScopeMapping, ApplicationCompositeApplicationScopeMapping) {
|
||||||
$scope.realm = realm;
|
$scope.realm = realm;
|
||||||
$scope.application = application;
|
$scope.application = angular.copy(application);
|
||||||
$scope.selectedRealmRoles = [];
|
$scope.selectedRealmRoles = [];
|
||||||
$scope.selectedRealmMappings = [];
|
$scope.selectedRealmMappings = [];
|
||||||
$scope.realmMappings = [];
|
$scope.realmMappings = [];
|
||||||
|
@ -364,6 +365,21 @@ module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm,
|
||||||
$scope.applicationMappings = [];
|
$scope.applicationMappings = [];
|
||||||
$scope.dummymodel = [];
|
$scope.dummymodel = [];
|
||||||
|
|
||||||
|
|
||||||
|
$scope.changeFullScopeAllowed = function() {
|
||||||
|
console.log('change full scope');
|
||||||
|
Application.update({
|
||||||
|
realm : realm.realm,
|
||||||
|
application : application.name
|
||||||
|
}, $scope.application, function() {
|
||||||
|
$scope.changed = false;
|
||||||
|
application = angular.copy($scope.application);
|
||||||
|
updateRealmRoles();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function updateRealmRoles() {
|
function updateRealmRoles() {
|
||||||
$scope.realmRoles = ApplicationAvailableRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
$scope.realmRoles = ApplicationAvailableRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||||
$scope.realmMappings = ApplicationRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
$scope.realmMappings = ApplicationRealmScopeMapping.query({realm : realm.realm, application : application.name});
|
||||||
|
|
|
@ -183,11 +183,12 @@ module.controller('OAuthClientDetailCtrl', function($scope, realm, oauth, OAuthC
|
||||||
});
|
});
|
||||||
|
|
||||||
module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm, oauth, applications,
|
module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm, oauth, applications,
|
||||||
|
OAuthClient,
|
||||||
OAuthClientRealmScopeMapping, OAuthClientApplicationScopeMapping, ApplicationRole,
|
OAuthClientRealmScopeMapping, OAuthClientApplicationScopeMapping, ApplicationRole,
|
||||||
OAuthClientAvailableRealmScopeMapping, OAuthClientAvailableApplicationScopeMapping,
|
OAuthClientAvailableRealmScopeMapping, OAuthClientAvailableApplicationScopeMapping,
|
||||||
OAuthClientCompositeRealmScopeMapping, OAuthClientCompositeApplicationScopeMapping) {
|
OAuthClientCompositeRealmScopeMapping, OAuthClientCompositeApplicationScopeMapping) {
|
||||||
$scope.realm = realm;
|
$scope.realm = realm;
|
||||||
$scope.oauth = oauth;
|
$scope.oauth = angular.copy(oauth);
|
||||||
$scope.selectedRealmRoles = [];
|
$scope.selectedRealmRoles = [];
|
||||||
$scope.selectedRealmMappings = [];
|
$scope.selectedRealmMappings = [];
|
||||||
$scope.realmMappings = [];
|
$scope.realmMappings = [];
|
||||||
|
@ -199,6 +200,19 @@ module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm,
|
||||||
$scope.applicationMappings = [];
|
$scope.applicationMappings = [];
|
||||||
$scope.dummymodel = [];
|
$scope.dummymodel = [];
|
||||||
|
|
||||||
|
$scope.changeFullScopeAllowed = function() {
|
||||||
|
console.log('change full scope');
|
||||||
|
OAuthClient.update({
|
||||||
|
realm : realm.realm,
|
||||||
|
oauth : oauth.name
|
||||||
|
}, $scope.oauth, function() {
|
||||||
|
$scope.changed = false;
|
||||||
|
oauth = angular.copy($scope.oauth);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function updateRealmRoles() {
|
function updateRealmRoles() {
|
||||||
$scope.realmRoles = OAuthClientAvailableRealmScopeMapping.query({realm : realm.realm, oauth : oauth.name});
|
$scope.realmRoles = OAuthClientAvailableRealmScopeMapping.query({realm : realm.realm, oauth : oauth.name});
|
||||||
$scope.realmMappings = OAuthClientRealmScopeMapping.query({realm : realm.realm, oauth : oauth.name});
|
$scope.realmMappings = OAuthClientRealmScopeMapping.query({realm : realm.realm, oauth : oauth.name});
|
||||||
|
|
|
@ -21,7 +21,18 @@
|
||||||
</ol>
|
</ol>
|
||||||
<h2><span>{{application.name}}</span> Scope Mappings</h2>
|
<h2><span>{{application.name}}</span> Scope Mappings</h2>
|
||||||
<p class="subtitle"></p>
|
<p class="subtitle"></p>
|
||||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageApplications">
|
<form class="form-horizontal" name="allowScope" novalidate kc-read-only="!access.manageApplications">
|
||||||
|
<fieldset class="border-top">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label" for="fullScopeAllowed">Full Scope Allowed</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input ng-model="application.fullScopeAllowed" ng-click="changeFullScopeAllowed()" name="fullScopeAllowed" id="fullScopeAllowed" onoffswitch />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageApplications" data-ng-show="!application.fullScopeAllowed">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend><span class="text">Realm Roles</span></legend>
|
<legend><span class="text">Realm Roles</span></legend>
|
||||||
<div class="form-group col-sm-10">
|
<div class="form-group col-sm-10">
|
||||||
|
|
|
@ -19,7 +19,17 @@
|
||||||
</ol>
|
</ol>
|
||||||
<h2><span>{{oauth.name}}</span> Scope Mappings</h2>
|
<h2><span>{{oauth.name}}</span> Scope Mappings</h2>
|
||||||
<p class="subtitle"></p>
|
<p class="subtitle"></p>
|
||||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients">
|
<form class="form-horizontal" name="allowScope" novalidate kc-read-only="!access.manageClients">
|
||||||
|
<fieldset class="border-top">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label" for="fullScopeAllowed">Full Scope Allowed</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input ng-model="oauth.fullScopeAllowed" ng-click="changeFullScopeAllowed()" name="fullScopeAllowed" id="fullScopeAllowed" onoffswitch />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients" data-ng-show="!oauth.fullScopeAllowed">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend><span class="text">Realm Roles</span></legend>
|
<legend><span class="text">Realm Roles</span></legend>
|
||||||
<div class="form-group col-sm-10">
|
<div class="form-group col-sm-10">
|
||||||
|
|
|
@ -50,6 +50,9 @@ public interface ClientModel {
|
||||||
String getSecret();
|
String getSecret();
|
||||||
public void setSecret(String secret);
|
public void setSecret(String secret);
|
||||||
|
|
||||||
|
boolean isFullScopeAllowed();
|
||||||
|
void setFullScopeAllowed(boolean value);
|
||||||
|
|
||||||
boolean isPublicClient();
|
boolean isPublicClient();
|
||||||
void setPublicClient(boolean flag);
|
void setPublicClient(boolean flag);
|
||||||
|
|
||||||
|
|
9
model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
Normal file → Executable file
9
model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
Normal file → Executable file
|
@ -14,6 +14,7 @@ public class ClientEntity extends AbstractIdentifiableEntity {
|
||||||
private long allowedClaimsMask;
|
private long allowedClaimsMask;
|
||||||
private int notBefore;
|
private int notBefore;
|
||||||
private boolean publicClient;
|
private boolean publicClient;
|
||||||
|
private boolean fullScopeAllowed;
|
||||||
|
|
||||||
private String realmId;
|
private String realmId;
|
||||||
|
|
||||||
|
@ -100,4 +101,12 @@ public class ClientEntity extends AbstractIdentifiableEntity {
|
||||||
public void setScopeIds(List<String> scopeIds) {
|
public void setScopeIds(List<String> scopeIds) {
|
||||||
this.scopeIds = scopeIds;
|
this.scopeIds = scopeIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isFullScopeAllowed() {
|
||||||
|
return fullScopeAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullScopeAllowed(boolean fullScopeAllowed) {
|
||||||
|
this.fullScopeAllowed = fullScopeAllowed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,7 @@ public final class KeycloakModelUtils {
|
||||||
public static ApplicationModel createApplication(RealmModel realm, String name) {
|
public static ApplicationModel createApplication(RealmModel realm, String name) {
|
||||||
ApplicationModel app = realm.addApplication(name);
|
ApplicationModel app = realm.addApplication(name);
|
||||||
generateSecret(app);
|
generateSecret(app);
|
||||||
|
app.setFullScopeAllowed(true);
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,7 @@ public class ModelToRepresentation {
|
||||||
rep.setEnabled(applicationModel.isEnabled());
|
rep.setEnabled(applicationModel.isEnabled());
|
||||||
rep.setAdminUrl(applicationModel.getManagementUrl());
|
rep.setAdminUrl(applicationModel.getManagementUrl());
|
||||||
rep.setPublicClient(applicationModel.isPublicClient());
|
rep.setPublicClient(applicationModel.isPublicClient());
|
||||||
|
rep.setFullScopeAllowed(applicationModel.isFullScopeAllowed());
|
||||||
rep.setBearerOnly(applicationModel.isBearerOnly());
|
rep.setBearerOnly(applicationModel.isBearerOnly());
|
||||||
rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired());
|
rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired());
|
||||||
rep.setBaseUrl(applicationModel.getBaseUrl());
|
rep.setBaseUrl(applicationModel.getBaseUrl());
|
||||||
|
@ -242,6 +243,7 @@ public class ModelToRepresentation {
|
||||||
rep.setName(model.getClientId());
|
rep.setName(model.getClientId());
|
||||||
rep.setEnabled(model.isEnabled());
|
rep.setEnabled(model.isEnabled());
|
||||||
rep.setPublicClient(model.isPublicClient());
|
rep.setPublicClient(model.isPublicClient());
|
||||||
|
rep.setFullScopeAllowed(model.isFullScopeAllowed());
|
||||||
rep.setDirectGrantsOnly(model.isDirectGrantsOnly());
|
rep.setDirectGrantsOnly(model.isDirectGrantsOnly());
|
||||||
Set<String> redirectUris = model.getRedirectUris();
|
Set<String> redirectUris = model.getRedirectUris();
|
||||||
if (redirectUris != null) {
|
if (redirectUris != null) {
|
||||||
|
|
|
@ -353,6 +353,8 @@ public class RepresentationToModel {
|
||||||
applicationModel.setBaseUrl(resourceRep.getBaseUrl());
|
applicationModel.setBaseUrl(resourceRep.getBaseUrl());
|
||||||
if (resourceRep.isBearerOnly() != null) applicationModel.setBearerOnly(resourceRep.isBearerOnly());
|
if (resourceRep.isBearerOnly() != null) applicationModel.setBearerOnly(resourceRep.isBearerOnly());
|
||||||
if (resourceRep.isPublicClient() != null) applicationModel.setPublicClient(resourceRep.isPublicClient());
|
if (resourceRep.isPublicClient() != null) applicationModel.setPublicClient(resourceRep.isPublicClient());
|
||||||
|
if (resourceRep.isFullScopeAllowed() != null) applicationModel.setFullScopeAllowed(resourceRep.isFullScopeAllowed());
|
||||||
|
else applicationModel.setFullScopeAllowed(true);
|
||||||
applicationModel.updateApplication();
|
applicationModel.updateApplication();
|
||||||
|
|
||||||
if (resourceRep.getNotBefore() != null) {
|
if (resourceRep.getNotBefore() != null) {
|
||||||
|
@ -415,6 +417,7 @@ public class RepresentationToModel {
|
||||||
if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled());
|
if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled());
|
||||||
if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
|
if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
|
||||||
if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient());
|
if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient());
|
||||||
|
if (rep.isFullScopeAllowed() != null) resource.setFullScopeAllowed(rep.isFullScopeAllowed());
|
||||||
if (rep.getAdminUrl() != null) resource.setManagementUrl(rep.getAdminUrl());
|
if (rep.getAdminUrl() != null) resource.setManagementUrl(rep.getAdminUrl());
|
||||||
if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl());
|
if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl());
|
||||||
if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
|
if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
|
||||||
|
@ -521,6 +524,7 @@ public class RepresentationToModel {
|
||||||
if (rep.getName() != null) model.setClientId(rep.getName());
|
if (rep.getName() != null) model.setClientId(rep.getName());
|
||||||
if (rep.isEnabled() != null) model.setEnabled(rep.isEnabled());
|
if (rep.isEnabled() != null) model.setEnabled(rep.isEnabled());
|
||||||
if (rep.isPublicClient() != null) model.setPublicClient(rep.isPublicClient());
|
if (rep.isPublicClient() != null) model.setPublicClient(rep.isPublicClient());
|
||||||
|
if (rep.isFullScopeAllowed() != null) model.setFullScopeAllowed(rep.isFullScopeAllowed());
|
||||||
if (rep.isDirectGrantsOnly() != null) model.setDirectGrantsOnly(rep.isDirectGrantsOnly());
|
if (rep.isDirectGrantsOnly() != null) model.setDirectGrantsOnly(rep.isDirectGrantsOnly());
|
||||||
if (rep.getClaims() != null) {
|
if (rep.getClaims() != null) {
|
||||||
setClaims(model, rep.getClaims());
|
setClaims(model, rep.getClaims());
|
||||||
|
|
|
@ -123,6 +123,19 @@ public abstract class ClientAdapter implements ClientModel {
|
||||||
updatedClient.setPublicClient(flag);
|
updatedClient.setPublicClient(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFullScopeAllowed() {
|
||||||
|
if (updatedClient != null) return updatedClient.isFullScopeAllowed();
|
||||||
|
return cachedClient.isFullScopeAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFullScopeAllowed(boolean value) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updatedClient.setFullScopeAllowed(value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isDirectGrantsOnly() {
|
public boolean isDirectGrantsOnly() {
|
||||||
if (updatedClient != null) return updatedClient.isDirectGrantsOnly();
|
if (updatedClient != null) return updatedClient.isDirectGrantsOnly();
|
||||||
return cachedClient.isDirectGrantsOnly();
|
return cachedClient.isDirectGrantsOnly();
|
||||||
|
@ -171,7 +184,7 @@ public abstract class ClientAdapter implements ClientModel {
|
||||||
|
|
||||||
public boolean hasScope(RoleModel role) {
|
public boolean hasScope(RoleModel role) {
|
||||||
if (updatedClient != null) return updatedClient.hasScope(role);
|
if (updatedClient != null) return updatedClient.hasScope(role);
|
||||||
if (cachedClient.getScope().contains(role.getId())) return true;
|
if (cachedClient.isFullScopeAllowed() || cachedClient.getScope().contains(role.getId())) return true;
|
||||||
|
|
||||||
Set<RoleModel> roles = getScopeMappings();
|
Set<RoleModel> roles = getScopeMappings();
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ public class CachedClient {
|
||||||
protected boolean enabled;
|
protected boolean enabled;
|
||||||
protected String secret;
|
protected String secret;
|
||||||
protected boolean publicClient;
|
protected boolean publicClient;
|
||||||
|
protected boolean fullScopeAllowed;
|
||||||
protected boolean directGrantsOnly;
|
protected boolean directGrantsOnly;
|
||||||
protected int notBefore;
|
protected int notBefore;
|
||||||
protected Set<String> scope = new HashSet<String>();
|
protected Set<String> scope = new HashSet<String>();
|
||||||
|
@ -37,6 +38,7 @@ public class CachedClient {
|
||||||
directGrantsOnly = model.isDirectGrantsOnly();
|
directGrantsOnly = model.isDirectGrantsOnly();
|
||||||
publicClient = model.isPublicClient();
|
publicClient = model.isPublicClient();
|
||||||
allowedClaimsMask = model.getAllowedClaimsMask();
|
allowedClaimsMask = model.getAllowedClaimsMask();
|
||||||
|
fullScopeAllowed = model.isFullScopeAllowed();
|
||||||
redirectUris.addAll(model.getRedirectUris());
|
redirectUris.addAll(model.getRedirectUris());
|
||||||
webOrigins.addAll(model.getWebOrigins());
|
webOrigins.addAll(model.getWebOrigins());
|
||||||
for (RoleModel role : model.getScopeMappings()) {
|
for (RoleModel role : model.getScopeMappings()) {
|
||||||
|
@ -92,4 +94,8 @@ public class CachedClient {
|
||||||
public Set<String> getWebOrigins() {
|
public Set<String> getWebOrigins() {
|
||||||
return webOrigins;
|
return webOrigins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isFullScopeAllowed() {
|
||||||
|
return fullScopeAllowed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,16 @@ public abstract class ClientAdapter implements ClientModel {
|
||||||
entity.setPublicClient(flag);
|
entity.setPublicClient(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFullScopeAllowed() {
|
||||||
|
return entity.isFullScopeAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFullScopeAllowed(boolean value) {
|
||||||
|
entity.setFullScopeAllowed(value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getWebOrigins() {
|
public Set<String> getWebOrigins() {
|
||||||
Set<String> result = new HashSet<String>();
|
Set<String> result = new HashSet<String>();
|
||||||
|
@ -214,6 +224,7 @@ public abstract class ClientAdapter implements ClientModel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasScope(RoleModel role) {
|
public boolean hasScope(RoleModel role) {
|
||||||
|
if (isFullScopeAllowed()) return true;
|
||||||
Set<RoleModel> roles = getScopeMappings();
|
Set<RoleModel> roles = getScopeMappings();
|
||||||
if (roles.contains(role)) return true;
|
if (roles.contains(role)) return true;
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ public abstract class ClientEntity {
|
||||||
private int notBefore;
|
private int notBefore;
|
||||||
@Column(name="PUBLIC_CLIENT")
|
@Column(name="PUBLIC_CLIENT")
|
||||||
private boolean publicClient;
|
private boolean publicClient;
|
||||||
|
@Column(name="FULL_SCOPE_ALLOWED")
|
||||||
|
private boolean fullScopeAllowed;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "REALM_ID")
|
@JoinColumn(name = "REALM_ID")
|
||||||
|
@ -132,4 +134,12 @@ public abstract class ClientEntity {
|
||||||
public void setPublicClient(boolean publicClient) {
|
public void setPublicClient(boolean publicClient) {
|
||||||
this.publicClient = publicClient;
|
this.publicClient = publicClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isFullScopeAllowed() {
|
||||||
|
return fullScopeAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFullScopeAllowed(boolean fullScopeAllowed) {
|
||||||
|
this.fullScopeAllowed = fullScopeAllowed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,18 @@ public abstract class ClientAdapter<T extends MongoIdentifiableEntity> extends A
|
||||||
updateMongoEntity();
|
updateMongoEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFullScopeAllowed() {
|
||||||
|
return getMongoEntityAsClient().isFullScopeAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFullScopeAllowed(boolean value) {
|
||||||
|
getMongoEntityAsClient().setFullScopeAllowed(value);
|
||||||
|
updateMongoEntity();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RealmModel getRealm() {
|
public RealmModel getRealm() {
|
||||||
return realm;
|
return realm;
|
||||||
|
@ -207,6 +219,7 @@ public abstract class ClientAdapter<T extends MongoIdentifiableEntity> extends A
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasScope(RoleModel role) {
|
public boolean hasScope(RoleModel role) {
|
||||||
|
if (isFullScopeAllowed()) return true;
|
||||||
Set<RoleModel> roles = getScopeMappings();
|
Set<RoleModel> roles = getScopeMappings();
|
||||||
if (roles.contains(role)) return true;
|
if (roles.contains(role)) return true;
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ public class RealmManager {
|
||||||
adminConsole.setEnabled(true);
|
adminConsole.setEnabled(true);
|
||||||
adminConsole.setPublicClient(true);
|
adminConsole.setPublicClient(true);
|
||||||
adminConsole.addRedirectUri(baseUrl + "/*");
|
adminConsole.addRedirectUri(baseUrl + "/*");
|
||||||
|
adminConsole.setFullScopeAllowed(false);
|
||||||
|
|
||||||
RoleModel adminRole;
|
RoleModel adminRole;
|
||||||
if (realm.getName().equals(Config.getAdminRealm())) {
|
if (realm.getName().equals(Config.getAdminRealm())) {
|
||||||
|
@ -163,6 +164,7 @@ public class RealmManager {
|
||||||
}
|
}
|
||||||
RoleModel adminRole = realmAdminApp.addRole(AdminRoles.REALM_ADMIN);
|
RoleModel adminRole = realmAdminApp.addRole(AdminRoles.REALM_ADMIN);
|
||||||
realmAdminApp.setBearerOnly(true);
|
realmAdminApp.setBearerOnly(true);
|
||||||
|
realmAdminApp.setFullScopeAllowed(false);
|
||||||
|
|
||||||
for (String r : AdminRoles.ALL_REALM_ROLES) {
|
for (String r : AdminRoles.ALL_REALM_ROLES) {
|
||||||
RoleModel role = realmAdminApp.addRole(r);
|
RoleModel role = realmAdminApp.addRole(r);
|
||||||
|
@ -176,6 +178,7 @@ public class RealmManager {
|
||||||
if (application == null) {
|
if (application == null) {
|
||||||
application = new ApplicationManager(this).createApplication(realm, Constants.ACCOUNT_MANAGEMENT_APP);
|
application = new ApplicationManager(this).createApplication(realm, Constants.ACCOUNT_MANAGEMENT_APP);
|
||||||
application.setEnabled(true);
|
application.setEnabled(true);
|
||||||
|
application.setFullScopeAllowed(false);
|
||||||
String base = contextPath + "/realms/" + realm.getName() + "/account";
|
String base = contextPath + "/realms/" + realm.getName() + "/account";
|
||||||
String redirectUri = base + "/*";
|
String redirectUri = base + "/*";
|
||||||
application.addRedirectUri(redirectUri);
|
application.addRedirectUri(redirectUri);
|
||||||
|
|
|
@ -135,6 +135,8 @@ public class TokenManager {
|
||||||
Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
|
Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
|
||||||
|
|
||||||
Set<RoleModel> roleMappings = user.getRoleMappings();
|
Set<RoleModel> roleMappings = user.getRoleMappings();
|
||||||
|
if (client.isFullScopeAllowed()) return roleMappings;
|
||||||
|
|
||||||
Set<RoleModel> scopeMappings = client.getScopeMappings();
|
Set<RoleModel> scopeMappings = client.getScopeMappings();
|
||||||
if (client instanceof ApplicationModel) {
|
if (client instanceof ApplicationModel) {
|
||||||
scopeMappings.addAll(((ApplicationModel) client).getRoles());
|
scopeMappings.addAll(((ApplicationModel) client).getRoles());
|
||||||
|
|
|
@ -1069,6 +1069,11 @@ public class TokenService {
|
||||||
|
|
||||||
if (redirectUri != null) {
|
if (redirectUri != null) {
|
||||||
// todo manage legal redirects
|
// todo manage legal redirects
|
||||||
|
if (redirectUri.startsWith("/")) { // handle relative uri
|
||||||
|
UriBuilder builder = uriInfo.getAbsolutePathBuilder();
|
||||||
|
builder.replacePath(redirectUri);
|
||||||
|
return Response.status(302).location(builder.build()).build();
|
||||||
|
}
|
||||||
return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build();
|
return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build();
|
||||||
} else {
|
} else {
|
||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
|
|
|
@ -166,6 +166,7 @@ public class AdminAPITest {
|
||||||
if (appRep.isEnabled() != null) Assert.assertEquals(appRep.isEnabled(), storedApp.isEnabled());
|
if (appRep.isEnabled() != null) Assert.assertEquals(appRep.isEnabled(), storedApp.isEnabled());
|
||||||
if (appRep.isBearerOnly() != null) Assert.assertEquals(appRep.isBearerOnly(), storedApp.isBearerOnly());
|
if (appRep.isBearerOnly() != null) Assert.assertEquals(appRep.isBearerOnly(), storedApp.isBearerOnly());
|
||||||
if (appRep.isPublicClient() != null) Assert.assertEquals(appRep.isPublicClient(), storedApp.isPublicClient());
|
if (appRep.isPublicClient() != null) Assert.assertEquals(appRep.isPublicClient(), storedApp.isPublicClient());
|
||||||
|
if (appRep.isFullScopeAllowed() != null) Assert.assertEquals(appRep.isFullScopeAllowed(), storedApp.isFullScopeAllowed());
|
||||||
if (appRep.getAdminUrl() != null) Assert.assertEquals(appRep.getAdminUrl(), storedApp.getAdminUrl());
|
if (appRep.getAdminUrl() != null) Assert.assertEquals(appRep.getAdminUrl(), storedApp.getAdminUrl());
|
||||||
if (appRep.getBaseUrl() != null) Assert.assertEquals(appRep.getBaseUrl(), storedApp.getBaseUrl());
|
if (appRep.getBaseUrl() != null) Assert.assertEquals(appRep.getBaseUrl(), storedApp.getBaseUrl());
|
||||||
if (appRep.isSurrogateAuthRequired() != null) Assert.assertEquals(appRep.isSurrogateAuthRequired(), storedApp.isSurrogateAuthRequired());
|
if (appRep.isSurrogateAuthRequired() != null) Assert.assertEquals(appRep.isSurrogateAuthRequired(), storedApp.isSurrogateAuthRequired());
|
||||||
|
|
|
@ -86,6 +86,7 @@ public class CompositeRoleTest {
|
||||||
realmRole1User.grantRole(realmRole1);
|
realmRole1User.grantRole(realmRole1);
|
||||||
|
|
||||||
final ApplicationModel realmComposite1Application = new ApplicationManager(manager).createApplication(realm, "REALM_COMPOSITE_1_APPLICATION");
|
final ApplicationModel realmComposite1Application = new ApplicationManager(manager).createApplication(realm, "REALM_COMPOSITE_1_APPLICATION");
|
||||||
|
realmComposite1Application.setFullScopeAllowed(false);
|
||||||
realmComposite1Application.setEnabled(true);
|
realmComposite1Application.setEnabled(true);
|
||||||
realmComposite1Application.addScopeMapping(realmComposite1);
|
realmComposite1Application.addScopeMapping(realmComposite1);
|
||||||
realmComposite1Application.addRedirectUri("http://localhost:8081/app/*");
|
realmComposite1Application.addRedirectUri("http://localhost:8081/app/*");
|
||||||
|
@ -94,6 +95,7 @@ public class CompositeRoleTest {
|
||||||
realmComposite1Application.setSecret("password");
|
realmComposite1Application.setSecret("password");
|
||||||
|
|
||||||
final ApplicationModel realmRole1Application = new ApplicationManager(manager).createApplication(realm, "REALM_ROLE_1_APPLICATION");
|
final ApplicationModel realmRole1Application = new ApplicationManager(manager).createApplication(realm, "REALM_ROLE_1_APPLICATION");
|
||||||
|
realmRole1Application.setFullScopeAllowed(false);
|
||||||
realmRole1Application.setEnabled(true);
|
realmRole1Application.setEnabled(true);
|
||||||
realmRole1Application.addScopeMapping(realmRole1);
|
realmRole1Application.addScopeMapping(realmRole1);
|
||||||
realmRole1Application.addRedirectUri("http://localhost:8081/app/*");
|
realmRole1Application.addRedirectUri("http://localhost:8081/app/*");
|
||||||
|
@ -103,6 +105,7 @@ public class CompositeRoleTest {
|
||||||
|
|
||||||
|
|
||||||
final ApplicationModel appRoleApplication = new ApplicationManager(manager).createApplication(realm, "APP_ROLE_APPLICATION");
|
final ApplicationModel appRoleApplication = new ApplicationManager(manager).createApplication(realm, "APP_ROLE_APPLICATION");
|
||||||
|
appRoleApplication.setFullScopeAllowed(false);
|
||||||
appRoleApplication.setEnabled(true);
|
appRoleApplication.setEnabled(true);
|
||||||
appRoleApplication.addRedirectUri("http://localhost:8081/app/*");
|
appRoleApplication.addRedirectUri("http://localhost:8081/app/*");
|
||||||
appRoleApplication.setBaseUrl("http://localhost:8081/app");
|
appRoleApplication.setBaseUrl("http://localhost:8081/app");
|
||||||
|
@ -125,6 +128,7 @@ public class CompositeRoleTest {
|
||||||
realmAppRoleUser.grantRole(appRole2);
|
realmAppRoleUser.grantRole(appRole2);
|
||||||
|
|
||||||
final ApplicationModel appCompositeApplication = new ApplicationManager(manager).createApplication(realm, "APP_COMPOSITE_APPLICATION");
|
final ApplicationModel appCompositeApplication = new ApplicationManager(manager).createApplication(realm, "APP_COMPOSITE_APPLICATION");
|
||||||
|
appCompositeApplication.setFullScopeAllowed(false);
|
||||||
appCompositeApplication.setEnabled(true);
|
appCompositeApplication.setEnabled(true);
|
||||||
appCompositeApplication.addRedirectUri("http://localhost:8081/app/*");
|
appCompositeApplication.addRedirectUri("http://localhost:8081/app/*");
|
||||||
appCompositeApplication.setBaseUrl("http://localhost:8081/app");
|
appCompositeApplication.setBaseUrl("http://localhost:8081/app");
|
||||||
|
|
|
@ -88,6 +88,7 @@
|
||||||
"applications": [
|
"applications": [
|
||||||
{
|
{
|
||||||
"name": "REALM_COMPOSITE_1_APPLICATION",
|
"name": "REALM_COMPOSITE_1_APPLICATION",
|
||||||
|
"fullScopeAllowed": false,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"baseUrl": "http://localhost:8081/app",
|
"baseUrl": "http://localhost:8081/app",
|
||||||
"adminUrl": "http://localhost:8081/app/logout",
|
"adminUrl": "http://localhost:8081/app/logout",
|
||||||
|
@ -95,6 +96,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "REALM_ROLE_1_APPLICATION",
|
"name": "REALM_ROLE_1_APPLICATION",
|
||||||
|
"fullScopeAllowed": false,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"baseUrl": "http://localhost:8081/app",
|
"baseUrl": "http://localhost:8081/app",
|
||||||
"adminUrl": "http://localhost:8081/app/logout",
|
"adminUrl": "http://localhost:8081/app/logout",
|
||||||
|
@ -102,6 +104,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "APP_ROLE_APPLICATION",
|
"name": "APP_ROLE_APPLICATION",
|
||||||
|
"fullScopeAllowed": false,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"baseUrl": "http://localhost:8081/app",
|
"baseUrl": "http://localhost:8081/app",
|
||||||
"adminUrl": "http://localhost:8081/app/logout",
|
"adminUrl": "http://localhost:8081/app/logout",
|
||||||
|
@ -109,6 +112,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "APP_COMPOSITE_APPLICATION",
|
"name": "APP_COMPOSITE_APPLICATION",
|
||||||
|
"fullScopeAllowed": false,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"baseUrl": "http://localhost:8081/app",
|
"baseUrl": "http://localhost:8081/app",
|
||||||
"adminUrl": "http://localhost:8081/app/logout",
|
"adminUrl": "http://localhost:8081/app/logout",
|
||||||
|
|
|
@ -89,6 +89,7 @@
|
||||||
{
|
{
|
||||||
"name": "REALM_COMPOSITE_1_APPLICATION",
|
"name": "REALM_COMPOSITE_1_APPLICATION",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
"fullScopeAllowed": false,
|
||||||
"baseUrl": "http://localhost:8081/app",
|
"baseUrl": "http://localhost:8081/app",
|
||||||
"adminUrl": "http://localhost:8081/app/logout",
|
"adminUrl": "http://localhost:8081/app/logout",
|
||||||
"redirectUris": [
|
"redirectUris": [
|
||||||
|
@ -98,6 +99,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "REALM_ROLE_1_APPLICATION",
|
"name": "REALM_ROLE_1_APPLICATION",
|
||||||
|
"fullScopeAllowed": false,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"baseUrl": "http://localhost:8081/app",
|
"baseUrl": "http://localhost:8081/app",
|
||||||
"adminUrl": "http://localhost:8081/app/logout",
|
"adminUrl": "http://localhost:8081/app/logout",
|
||||||
|
@ -108,6 +110,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "APP_ROLE_APPLICATION",
|
"name": "APP_ROLE_APPLICATION",
|
||||||
|
"fullScopeAllowed": false,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"baseUrl": "http://localhost:8081/app",
|
"baseUrl": "http://localhost:8081/app",
|
||||||
"adminUrl": "http://localhost:8081/app/logout",
|
"adminUrl": "http://localhost:8081/app/logout",
|
||||||
|
@ -118,6 +121,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "APP_COMPOSITE_APPLICATION",
|
"name": "APP_COMPOSITE_APPLICATION",
|
||||||
|
"fullScopeAllowed": false,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"baseUrl": "http://localhost:8081/app",
|
"baseUrl": "http://localhost:8081/app",
|
||||||
"adminUrl": "http://localhost:8081/app/logout",
|
"adminUrl": "http://localhost:8081/app/logout",
|
||||||
|
|
Loading…
Reference in a new issue