From 0b93e7b50db26fbe38abc52893635f8150ee3197 Mon Sep 17 00:00:00 2001 From: Puja Sharma Date: Wed, 4 May 2022 22:12:50 +0530 Subject: [PATCH 1/4] feat(jans-config-api): Added scope DN validation while creating openid client --- .../rest/resource/auth/ClientsResource.java | 69 +++++++++++++++++-- .../java/io/jans/configapi/util/AuthUtil.java | 10 +++ 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java index a02fcf841ea..b62db7020eb 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java @@ -11,13 +11,16 @@ import io.jans.as.common.model.registration.Client; import io.jans.as.common.service.common.EncryptionService; import io.jans.as.common.service.common.InumService; +import io.jans.as.persistence.model.Scope; import io.jans.configapi.core.rest.ProtectedApi; import io.jans.configapi.core.model.SearchRequest; import io.jans.configapi.service.auth.ClientService; import io.jans.configapi.service.auth.ConfigurationService; +import io.jans.configapi.service.auth.ScopeService; import io.jans.configapi.util.ApiAccessConstants; import io.jans.configapi.util.ApiConstants; import io.jans.configapi.util.AttributeNames; +import io.jans.configapi.util.AuthUtil; import io.jans.configapi.core.util.Jackson; import io.jans.orm.PersistenceEntryManager; import io.jans.orm.model.PagedResult; @@ -51,9 +54,6 @@ public class ClientsResource extends ConfigBaseResource { private static final String OPENID_CONNECT_CLIENT = "openid connect client"; - @Inject - Logger logger; - @Inject ClientService clientService; @@ -65,6 +65,12 @@ public class ClientsResource extends ConfigBaseResource { @Inject EncryptionService encryptionService; + + @Inject + AuthUtil authUtil; + + @Inject + ScopeService scopeService; @GET @ProtectedApi(scopes = { ApiAccessConstants.OPENID_CLIENTS_READ_ACCESS }) @@ -112,6 +118,10 @@ public Response createOpenIdConnect(@Valid Client client) throws EncryptionExcep client.setClientId(inum); } checkNotNull(client.getClientName(), AttributeNames.DISPLAY_NAME); + + //scope validation + checkScopeFormat(client); + String clientSecret = client.getClientSecret(); if (StringHelper.isEmpty(clientSecret)) { @@ -121,7 +131,7 @@ public Response createOpenIdConnect(@Valid Client client) throws EncryptionExcep client.setClientSecret(encryptionService.encrypt(clientSecret)); client.setDn(clientService.getDnForClient(inum)); client.setDeletable(client.getClientSecretExpiresAt() != null); - ignoreCustomObjectClassesForNonLDAP(client); + ignoreCustomObjectClassesForNonLDAP(client); logger.debug("Final Client details to be added - client:{}", client); clientService.addClient(client); @@ -142,6 +152,10 @@ public Response updateClient(@Valid Client client) throws EncryptionException { checkNotNull(client.getClientName(), AttributeNames.DISPLAY_NAME); Client existingClient = clientService.getClientByInum(inum); checkResourceNotNull(existingClient, OPENID_CONNECT_CLIENT); + + //scope validation + checkScopeFormat(client); + client.setClientId(existingClient.getClientId()); client.setBaseDn(clientService.getDnForClient(inum)); client.setDeletable(client.getExpirationDate() != null); @@ -233,6 +247,51 @@ private Client ignoreCustomObjectClassesForNonLDAP(Client client) { return client; } - + private Client checkScopeFormat(Client client) { + + if(client==null) { + return client; + } + + //check scope + + logger.debug("Checking client.getScopes():{}",client.getScopes()); + if(client.getScopes()==null || client.getScopes().length==0) { + return client; + } + + + List validScopes = new ArrayList<>(); + List invalidScopes = new ArrayList<>(); + + for(String scope : client.getScopes()) { + logger.debug("Is scope:{} valid:{}", scope, authUtil.isValidDn(scope)); + + if(!authUtil.isValidDn(scope)) { + //Get dn based on name + List scopes = scopeService.searchScopesById(scope); + logger.debug("Scopes from DB - {}'", scopes); + if(scopes!=null && !scopes.isEmpty()) { + validScopes.add(scope); + } + else { + invalidScopes.add(scope); + } + } + else { + validScopes.add(scope); + } + } + logger.debug("Scope validation result - validScopes:{}, invalidScopes:{} ",validScopes, invalidScopes); + + if(!invalidScopes.isEmpty()) { + thorwBadRequestException("Invalid scope in request -> "+invalidScopes.toString()); + } + + //reset scopes + client.setScopes((String[]) validScopes.toArray()); + return client; + } + } diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/util/AuthUtil.java b/jans-config-api/server/src/main/java/io/jans/configapi/util/AuthUtil.java index e32676bee26..3f914b7e797 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/util/AuthUtil.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/util/AuthUtil.java @@ -1,5 +1,6 @@ package io.jans.configapi.util; +import com.unboundid.ldap.sdk.DN; import io.jans.as.client.TokenResponse; import io.jans.as.common.model.registration.Client; import io.jans.as.common.service.common.EncryptionService; @@ -391,6 +392,15 @@ public List getAllFields(List fields, Class type) { log.debug("Final fields:{} of type:{} ", fields, type); return fields; } + + public boolean isValidDn(String dn) { + return isValidDn(dn, false); + } + + + public boolean isValidDn(String dn, boolean strictNameChecking) { + return DN.isValidDN(dn, strictNameChecking); + } From 09f6118aa57dad44761285ced718d97e2af6030d Mon Sep 17 00:00:00 2001 From: Puja Sharma Date: Thu, 5 May 2022 16:35:55 +0530 Subject: [PATCH 2/4] feat(jans-config-api): added scope DN validation while client creation --- .../filters/AuthorizationFilter.java | 9 ++- .../rest/resource/auth/ClientsResource.java | 64 +++++++++---------- .../configapi/service/auth/ScopeService.java | 10 +++ 3 files changed, 43 insertions(+), 40 deletions(-) diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/filters/AuthorizationFilter.java b/jans-config-api/server/src/main/java/io/jans/configapi/filters/AuthorizationFilter.java index b571c118897..8ba9a29f6eb 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/filters/AuthorizationFilter.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/filters/AuthorizationFilter.java @@ -23,7 +23,6 @@ import jakarta.ws.rs.core.UriInfo; import jakarta.ws.rs.ext.Provider; -import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; /** @@ -78,7 +77,7 @@ public void filter(ContainerRequestContext context) { log.info("\n\n\n AuthorizationFilter::filter() - Config Api OAuth Valdation Enabled"); if (!isTokenBasedAuthentication(authorizationHeader)) { - abortWithUnauthorized(context); + abortWithUnauthorized(context, "ONLY TOKEN BASED AUTHORIZATION IS SUPPORTED!"); log.info("======ONLY TOKEN BASED AUTHORIZATION IS SUPPORTED======================"); return; } @@ -93,7 +92,7 @@ public void filter(ContainerRequestContext context) { log.info("======AUTHORIZATION GRANTED==========================================="); } catch (Exception ex) { log.error("======AUTHORIZATION FAILED ===========================================", ex); - abortWithUnauthorized(context); + abortWithUnauthorized(context, ex.getMessage()); } } @@ -103,8 +102,8 @@ private boolean isTokenBasedAuthentication(String authorizationHeader) { && authorizationHeader.toLowerCase().startsWith(AUTHENTICATION_SCHEME.toLowerCase() + " "); } - private void abortWithUnauthorized(ContainerRequestContext requestContext) { - requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED) + private void abortWithUnauthorized(ContainerRequestContext requestContext, String errMsg) { + requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity(errMsg) .header(HttpHeaders.WWW_AUTHENTICATE, AUTHENTICATION_SCHEME).build()); } diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java index b62db7020eb..3f78511511a 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java @@ -39,8 +39,6 @@ import java.util.List; import java.util.UUID; -import org.slf4j.Logger; - /** * @author Mougang T.Gasmyr * @@ -248,50 +246,46 @@ private Client ignoreCustomObjectClassesForNonLDAP(Client client) { } private Client checkScopeFormat(Client client) { - - if(client==null) { + if (client == null) { return client; } - - //check scope - - logger.debug("Checking client.getScopes():{}",client.getScopes()); - if(client.getScopes()==null || client.getScopes().length==0) { + + // check scope + logger.debug("Checking client.getScopes():{}", client.getScopes()); + if (client.getScopes() == null || client.getScopes().length == 0) { return client; } - - + List validScopes = new ArrayList<>(); List invalidScopes = new ArrayList<>(); - - for(String scope : client.getScopes()) { + + for (String scope : client.getScopes()) { logger.debug("Is scope:{} valid:{}", scope, authUtil.isValidDn(scope)); - - if(!authUtil.isValidDn(scope)) { - //Get dn based on name - List scopes = scopeService.searchScopesById(scope); - logger.debug("Scopes from DB - {}'", scopes); - if(scopes!=null && !scopes.isEmpty()) { - validScopes.add(scope); - } - else { - invalidScopes.add(scope); - } + List scopes = null; + if (authUtil.isValidDn(scope)) { + scopes = scopeService.searchScopesByDN(scope); + } else { + scopes = scopeService.searchScopesById(scope); } - else { - validScopes.add(scope); + logger.debug("Scopes from DB - {}'", scopes); + if (scopes != null && !scopes.isEmpty()) { + validScopes.add(scopes.get(0).getDn()); + } else { + invalidScopes.add(scope); } } - logger.debug("Scope validation result - validScopes:{}, invalidScopes:{} ",validScopes, invalidScopes); - - if(!invalidScopes.isEmpty()) { - thorwBadRequestException("Invalid scope in request -> "+invalidScopes.toString()); + logger.debug("Scope validation result - validScopes:{}, invalidScopes:{} ", validScopes, invalidScopes); + + if (!invalidScopes.isEmpty()) { + thorwBadRequestException("Invalid scope in request -> " + invalidScopes.toString()); } - - //reset scopes - client.setScopes((String[]) validScopes.toArray()); - return client; + + // reset scopes + if (!validScopes.isEmpty()) { + String[] scopeArr = validScopes.stream().toArray(String[]::new); + client.setScopes(scopeArr); + } + return client; } - } diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/ScopeService.java b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/ScopeService.java index d75ae0b247c..d875c9ee39a 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/ScopeService.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/ScopeService.java @@ -99,6 +99,16 @@ public List searchScopesById(String jsId) { return new ArrayList<>(); } } + + public List searchScopesByDN(String dn) { + Filter searchFilter = Filter.createEqualityFilter("dn", dn); + try { + return persistenceEntryManager.findEntries(getDnForScope(null), Scope.class, searchFilter); + } catch (Exception e) { + logger.error("No scopes found by DN: " + dn, e); + return new ArrayList<>(); + } + } public List searchScopes(String pattern, int sizeLimit, String scopeType) { String[] targetArray = new String[] { pattern }; From 7e666df779c2172f06c934489ffd843961bb446e Mon Sep 17 00:00:00 2001 From: Puja Sharma Date: Thu, 5 May 2022 17:04:51 +0530 Subject: [PATCH 3/4] feat(jans-config-api): added scope DN validation while client creation --- .../rest/resource/auth/ClientsResource.java | 15 +++++++++------ .../jans/configapi/service/auth/ScopeService.java | 10 ++-------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java index 3f78511511a..2291a50d036 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java @@ -251,7 +251,7 @@ private Client checkScopeFormat(Client client) { } // check scope - logger.debug("Checking client.getScopes():{}", client.getScopes()); + logger.error("Checking client.getScopes():{}", client.getScopes()); if (client.getScopes() == null || client.getScopes().length == 0) { return client; } @@ -260,21 +260,24 @@ private Client checkScopeFormat(Client client) { List invalidScopes = new ArrayList<>(); for (String scope : client.getScopes()) { - logger.debug("Is scope:{} valid:{}", scope, authUtil.isValidDn(scope)); - List scopes = null; + logger.error("Is scope:{} valid:{}", scope, authUtil.isValidDn(scope)); + List scopes = new ArrayList<>(); if (authUtil.isValidDn(scope)) { - scopes = scopeService.searchScopesByDN(scope); + Scope scp = scopeService.getScopeByDn(scope); + if(scp!=null) { + scopes.add(scp); + } } else { scopes = scopeService.searchScopesById(scope); } - logger.debug("Scopes from DB - {}'", scopes); + logger.error("Scopes from DB - {}'", scopes); if (scopes != null && !scopes.isEmpty()) { validScopes.add(scopes.get(0).getDn()); } else { invalidScopes.add(scope); } } - logger.debug("Scope validation result - validScopes:{}, invalidScopes:{} ", validScopes, invalidScopes); + logger.error("Scope validation result - validScopes:{}, invalidScopes:{} ", validScopes, invalidScopes); if (!invalidScopes.isEmpty()) { thorwBadRequestException("Invalid scope in request -> " + invalidScopes.toString()); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/ScopeService.java b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/ScopeService.java index d875c9ee39a..b0183f372ae 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/ScopeService.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/ScopeService.java @@ -100,14 +100,8 @@ public List searchScopesById(String jsId) { } } - public List searchScopesByDN(String dn) { - Filter searchFilter = Filter.createEqualityFilter("dn", dn); - try { - return persistenceEntryManager.findEntries(getDnForScope(null), Scope.class, searchFilter); - } catch (Exception e) { - logger.error("No scopes found by DN: " + dn, e); - return new ArrayList<>(); - } + public Scope getScopeByDn(String dn) { + return persistenceEntryManager.find(Scope.class, dn); } public List searchScopes(String pattern, int sizeLimit, String scopeType) { From 65c353eb65f59476ab11acaf5a8ada62f51bcc34 Mon Sep 17 00:00:00 2001 From: Puja Sharma Date: Thu, 5 May 2022 17:34:54 +0530 Subject: [PATCH 4/4] feat(jans-config-api): added scope DN validation while client creation --- .../rest/resource/auth/ClientsResource.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java index 2291a50d036..3e6dbbc8549 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java @@ -23,6 +23,7 @@ import io.jans.configapi.util.AuthUtil; import io.jans.configapi.core.util.Jackson; import io.jans.orm.PersistenceEntryManager; +import io.jans.orm.exception.EntryPersistenceException; import io.jans.orm.model.PagedResult; import io.jans.util.StringHelper; import io.jans.util.security.StringEncrypter.EncryptionException; @@ -251,7 +252,7 @@ private Client checkScopeFormat(Client client) { } // check scope - logger.error("Checking client.getScopes():{}", client.getScopes()); + logger.debug("Checking client.getScopes():{}", client.getScopes()); if (client.getScopes() == null || client.getScopes().length == 0) { return client; } @@ -260,24 +261,24 @@ private Client checkScopeFormat(Client client) { List invalidScopes = new ArrayList<>(); for (String scope : client.getScopes()) { - logger.error("Is scope:{} valid:{}", scope, authUtil.isValidDn(scope)); + logger.debug("Is scope:{} valid:{}", scope, authUtil.isValidDn(scope)); List scopes = new ArrayList<>(); if (authUtil.isValidDn(scope)) { - Scope scp = scopeService.getScopeByDn(scope); + Scope scp = findScopeByDn(scope); if(scp!=null) { scopes.add(scp); } } else { scopes = scopeService.searchScopesById(scope); } - logger.error("Scopes from DB - {}'", scopes); - if (scopes != null && !scopes.isEmpty()) { + logger.debug("Scopes from DB - {}'", scopes); + if (!scopes.isEmpty()) { validScopes.add(scopes.get(0).getDn()); } else { invalidScopes.add(scope); } } - logger.error("Scope validation result - validScopes:{}, invalidScopes:{} ", validScopes, invalidScopes); + logger.debug("Scope validation result - validScopes:{}, invalidScopes:{} ", validScopes, invalidScopes); if (!invalidScopes.isEmpty()) { thorwBadRequestException("Invalid scope in request -> " + invalidScopes.toString()); @@ -291,4 +292,11 @@ private Client checkScopeFormat(Client client) { return client; } + private Scope findScopeByDn(String scopeDn) { + try { + return scopeService.getScopeByDn(scopeDn); + } catch (EntryPersistenceException e) { + return null; + } + } }