Merge pull request #31 from gresham-computing/DWN-39926_inputValidation

Dwn 39926 input validation
pull/1601/head
Harry Smith 2023-02-01 08:35:23 +00:00 committed by GitHub
commit d9d1df35e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 103 additions and 7 deletions

View File

@ -21,9 +21,11 @@
package org.mitre.oauth2.web;
import java.util.Set;
import java.util.regex.Pattern;
import org.mitre.oauth2.model.SystemScope;
import org.mitre.oauth2.service.SystemScopeService;
import org.mitre.openid.connect.exception.ScopeException;
import org.mitre.openid.connect.view.HttpCodeView;
import org.mitre.openid.connect.view.JsonEntityView;
import org.mitre.openid.connect.view.JsonErrorView;
@ -33,6 +35,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.method.P;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
@ -54,6 +57,8 @@ public class ScopeAPI {
public static final String URL = RootController.API_URL + "/scopes";
private static final String characterMatcher = "[a-zA-Z]+";
private static final Pattern pattern = Pattern.compile(characterMatcher);
@Autowired
private SystemScopeService scopeService;
@ -101,7 +106,14 @@ public class ScopeAPI {
SystemScope existing = scopeService.getById(id);
SystemScope scope = gson.fromJson(json, SystemScope.class);
try {
validateScope(scope);
} catch (ScopeException e) {
logger.error("updateScope failed due to ScopeException", e);
m.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
m.put(JsonErrorView.ERROR_MESSAGE, "Could not update scope. The server encountered a scope exception. Contact a system administrator for assistance.");
return JsonErrorView.VIEWNAME;
}
if (existing != null && scope != null) {
if (existing.getId().equals(scope.getId())) {
@ -138,6 +150,14 @@ public class ScopeAPI {
SystemScope scope = gson.fromJson(json, SystemScope.class);
SystemScope alreadyExists = scopeService.getByValue(scope.getValue());
try {
validateScope(scope);
} catch (ScopeException e) {
logger.error("createScope failed due to ScopeException", e);
m.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
m.put(JsonErrorView.ERROR_MESSAGE, "Could not create scope. The server encountered a scope exception. Contact a system administrator for assistance.");
return JsonErrorView.VIEWNAME;
}
if (alreadyExists != null) {
//Error, cannot save a scope with the same value as an existing one
logger.error("Error: attempting to save a scope with a value that already exists: " + scope.getValue());
@ -163,6 +183,12 @@ public class ScopeAPI {
}
}
private void validateScope(SystemScope scope) throws ScopeException {
if (!pattern.matcher(scope.getValue()).matches()) {
throw new ScopeException(scope.getValue());
}
}
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public String deleteScope(@PathVariable("id") Long id, ModelMap m) {

View File

@ -0,0 +1,25 @@
/**
* <copyright>
* <p>
* Copyright (c) 2010-2023 Gresham Technologies plc. All rights reserved.
*
* </copyright>
*/
package org.mitre.openid.connect.exception;
/**
* @author hwsmith
*/
public class ScopeException extends Exception {
private final String invalidScope;
public ScopeException(String invalidScope) {
this.invalidScope = invalidScope;
}
public String getMessage() {
return "The scope " + invalidScope + " is invalid as it contains non-alphabet characters";
}
}

View File

@ -21,6 +21,8 @@ import java.lang.reflect.Type;
import java.sql.SQLIntegrityConstraintViolationException;
import java.text.ParseException;
import java.util.Collection;
import java.util.Set;
import java.util.regex.Pattern;
import javax.persistence.PersistenceException;
@ -33,9 +35,8 @@ import org.mitre.oauth2.model.ClientDetailsEntity.SubjectType;
import org.mitre.oauth2.model.PKCEAlgorithm;
import org.mitre.oauth2.service.ClientDetailsEntityService;
import org.mitre.oauth2.web.AuthenticationUtilities;
import org.mitre.openid.connect.exception.ScopeException;
import org.mitre.openid.connect.exception.ValidationException;
import org.mitre.openid.connect.model.CachedImage;
import org.mitre.openid.connect.service.ClientLogoLoadingService;
import org.mitre.openid.connect.view.ClientEntityViewForAdmins;
import org.mitre.openid.connect.view.ClientEntityViewForUsers;
import org.mitre.openid.connect.view.HttpCodeView;
@ -45,10 +46,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
@ -130,6 +129,9 @@ public class ClientAPI {
public static final String URL = RootController.API_URL + "/clients";
private static final String characterMatcher = "[a-zA-Z]+";
private static final Pattern pattern = Pattern.compile(characterMatcher);
@Autowired
private ClientDetailsEntityService clientService;
@ -256,6 +258,12 @@ public class ClientAPI {
json = parser.parse(jsonString).getAsJsonObject();
client = gson.fromJson(json, ClientDetailsEntity.class);
client = validateSoftwareStatement(client);
validateScopes(client.getScope());
} catch (ScopeException e) {
logger.error("apiAddClient failed due to ScopeException", e);
m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
m.addAttribute(JsonErrorView.ERROR_MESSAGE, "Could not save new client. The server encountered a scope exception. Contact a system administrator for assistance.");
return JsonErrorView.VIEWNAME;
} catch (JsonSyntaxException e) {
logger.error("apiAddClient failed due to JsonSyntaxException", e);
m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
@ -369,6 +377,12 @@ public class ClientAPI {
json = parser.parse(jsonString).getAsJsonObject();
client = gson.fromJson(json, ClientDetailsEntity.class);
client = validateSoftwareStatement(client);
validateScopes(client.getScope());
} catch (ScopeException e) {
logger.error("apiUpdateClient failed due to ScopeException", e);
m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
m.addAttribute(JsonErrorView.ERROR_MESSAGE, "Could not update client. The server encountered a scope exception. Contact a system administrator for assistance.");
return JsonErrorView.VIEWNAME;
} catch (JsonSyntaxException e) {
logger.error("apiUpdateClient failed due to JsonSyntaxException", e);
m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
@ -460,6 +474,14 @@ public class ClientAPI {
}
}
private void validateScopes(Set<String> scopes) throws ScopeException {
for (String s : scopes) {
if (!pattern.matcher(s).matches()) {
throw new ScopeException(s);
}
}
}
/**
* Delete a client
* @param id

View File

@ -22,7 +22,10 @@ package org.mitre.openid.connect.web;
import java.security.Principal;
import java.util.Collection;
import java.util.Set;
import java.util.regex.Pattern;
import org.mitre.openid.connect.exception.ScopeException;
import org.mitre.openid.connect.model.WhitelistedSite;
import org.mitre.openid.connect.service.WhitelistedSiteService;
import org.mitre.openid.connect.view.HttpCodeView;
@ -56,6 +59,8 @@ import com.google.gson.JsonParser;
public class WhitelistAPI {
public static final String URL = RootController.API_URL + "/whitelist";
private static final String characterMatcher = "[a-zA-Z]+";
private static final Pattern pattern = Pattern.compile(characterMatcher);
@Autowired
private WhitelistedSiteService whitelistService;
@ -100,7 +105,12 @@ public class WhitelistAPI {
try {
json = parser.parse(jsonString).getAsJsonObject();
whitelist = gson.fromJson(json, WhitelistedSite.class);
validateWhitelistScopes(whitelist.getAllowedScopes());
} catch (ScopeException e) {
logger.error("addNewWhitelistedSite failed due to ScopeException", e);
m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
m.addAttribute(JsonErrorView.ERROR_MESSAGE, "Could not save new whitelisted site. The server encountered a scopes exception. Contact a system administrator for assistance.");
return JsonErrorView.VIEWNAME;
} catch (JsonParseException e) {
logger.error("addNewWhitelistedSite failed due to JsonParseException", e);
m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
@ -137,7 +147,12 @@ public class WhitelistAPI {
try {
json = parser.parse(jsonString).getAsJsonObject();
whitelist = gson.fromJson(json, WhitelistedSite.class);
validateWhitelistScopes(whitelist.getAllowedScopes());
} catch (ScopeException e) {
logger.error("updateWhitelistedSite failed due to ScopeException", e);
m.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
m.put(JsonErrorView.ERROR_MESSAGE, "Could not update whitelisted site. The server encountered a scope exception. Contact a system administrator for assistance.");
return JsonErrorView.VIEWNAME;
} catch (JsonParseException e) {
logger.error("updateWhitelistedSite failed due to JsonParseException", e);
m.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
@ -167,6 +182,14 @@ public class WhitelistAPI {
}
}
private void validateWhitelistScopes(Set<String> scopes) throws ScopeException {
for (String s : scopes) {
if (!pattern.matcher(s).matches()) {
throw new ScopeException(s);
}
}
}
/**
* Delete a whitelisted site
*