Skip to content

Commit

Permalink
fixes #354 update UnifiedSecurityConfig to support JSON string pathPr…
Browse files Browse the repository at this point in the history
…efixAuth (#355)
  • Loading branch information
stevehu authored Feb 14, 2024
1 parent afccde7 commit 231fc95
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
import java.util.List;

public class UnifiedPathPrefixAuth {
String pathPrefix;
String prefix;
boolean basic;
boolean jwt;
boolean swt;
boolean apikey;
List<String> jwkServiceIds;
List<String> swtServiceIds;

public String getPathPrefix() {
return pathPrefix;
public String getPrefix() {
return prefix;
}

public void setPathPrefix(String pathPrefix) {
this.pathPrefix = pathPrefix;
public void setPrefix(String prefix) {
this.prefix = prefix;
}

public boolean isBasic() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ private void setConfigList() {
try {
anonymousPrefixes = Config.getInstance().getMapper().readValue(s, new TypeReference<List<String>>() {});
} catch (Exception e) {
logger.error("could not parse the anonymousPrefixes json with a list of strings.", e);
throw new ConfigException("could not parse the anonymousPrefixes json with a list of strings.");
}
} else {
Expand Down Expand Up @@ -138,66 +139,73 @@ private void setConfigList() {
if(s.startsWith("[")) {
// json format
try {
pathPrefixAuths = Config.getInstance().getMapper().readValue(s, new TypeReference<List<UnifiedPathPrefixAuth>>() {});
List<Map<String, Object>> values = Config.getInstance().getMapper().readValue(s, new TypeReference<>() {});
pathPrefixAuths = populatePathPrefixAuths(values);
} catch (Exception e) {
logger.error("could not parse the pathPrefixAuths json with a list of string and object.", e);
throw new ConfigException("could not parse the pathPrefixAuths json with a list of string and object.");
}
} else {
throw new ConfigException("pathPrefixAuths must be a list of string object map.");
}
} else if (object instanceof List) {
// the object is a list of map, we need convert it to PathPrefixAuth object.
List<Map<String, Object>> values = (List<Map<String, Object>>)object;
for(Map<String, Object> value: values) {
UnifiedPathPrefixAuth unifiedPathPrefixAuth = new UnifiedPathPrefixAuth();

unifiedPathPrefixAuth.setPathPrefix((String)value.get(PREFIX));
unifiedPathPrefixAuth.setBasic(value.get(BASIC) == null ? false : (Boolean)value.get(BASIC));
unifiedPathPrefixAuth.setJwt(value.get(JWT) == null ? false : (Boolean)value.get(JWT));
unifiedPathPrefixAuth.setSwt(value.get(SWT) == null ? false : (Boolean)value.get(SWT));
unifiedPathPrefixAuth.setApikey(value.get(APIKEY) == null ? false : (Boolean)value.get(APIKEY));
Object jwkIds = value.get(JWK_SERVICE_IDS);
if(jwkIds instanceof String) {
String s = (String)value.get(JWK_SERVICE_IDS);
if(s.startsWith("[")) {
// json format
try {
unifiedPathPrefixAuth.setJwkServiceIds(Config.getInstance().getMapper().readValue(s, new TypeReference<List<String>>() {}));
} catch (Exception e) {
throw new ConfigException("could not parse the jwkServiceIds json with a list of strings.");
}
} else {
// comma separated
unifiedPathPrefixAuth.setJwkServiceIds(Arrays.asList(s.split("\\s*,\\s*")));
}
} else if(jwkIds instanceof List ) {
// it must be a json array.
unifiedPathPrefixAuth.setJwkServiceIds((List)jwkIds);
}
Object swtIds = value.get(SWT_SERVICE_IDS);
if(swtIds instanceof String) {
String s = (String)value.get(SWT_SERVICE_IDS);
if(s.startsWith("[")) {
// json format
try {
unifiedPathPrefixAuth.setSwtServiceIds(Config.getInstance().getMapper().readValue(s, new TypeReference<List<String>>() {}));
} catch (Exception e) {
throw new ConfigException("could not parse the swtServiceIds json with a list of strings.");
}
} else {
// comma separated
unifiedPathPrefixAuth.setSwtServiceIds(Arrays.asList(s.split("\\s*,\\s*")));
}
} else if(swtIds instanceof List ) {
// it must be a json array.
unifiedPathPrefixAuth.setSwtServiceIds((List)swtIds);
}
pathPrefixAuths.add(unifiedPathPrefixAuth);
}
pathPrefixAuths = populatePathPrefixAuths((List<Map<String, Object>>)object);
} else {
throw new ConfigException("pathPrefixAuth must be a list of string object map.");
}
}
}

public static List<UnifiedPathPrefixAuth> populatePathPrefixAuths(List<Map<String, Object>> values) {
List<UnifiedPathPrefixAuth> pathPrefixAuths = new ArrayList<>();
for(Map<String, Object> value: values) {
UnifiedPathPrefixAuth unifiedPathPrefixAuth = new UnifiedPathPrefixAuth();
unifiedPathPrefixAuth.setPrefix((String)value.get(PREFIX));
unifiedPathPrefixAuth.setBasic(value.get(BASIC) == null ? false : (Boolean)value.get(BASIC));
unifiedPathPrefixAuth.setJwt(value.get(JWT) == null ? false : (Boolean)value.get(JWT));
unifiedPathPrefixAuth.setSwt(value.get(SWT) == null ? false : (Boolean)value.get(SWT));
unifiedPathPrefixAuth.setApikey(value.get(APIKEY) == null ? false : (Boolean)value.get(APIKEY));
Object jwkIds = value.get(JWK_SERVICE_IDS);
if(jwkIds instanceof String) {
String s = (String)value.get(JWK_SERVICE_IDS);
if(s.startsWith("[")) {
// json format
try {
unifiedPathPrefixAuth.setJwkServiceIds(Config.getInstance().getMapper().readValue(s, new TypeReference<List<String>>() {}));
} catch (Exception e) {
logger.error("could not parse the jwkServiceIds json with a list of strings.", e);
throw new ConfigException("could not parse the jwkServiceIds json with a list of strings.");
}
} else {
// comma separated
unifiedPathPrefixAuth.setJwkServiceIds(Arrays.asList(s.split("\\s*,\\s*")));
}
} else if(jwkIds instanceof List ) {
// it must be a json array.
unifiedPathPrefixAuth.setJwkServiceIds((List)jwkIds);
}
Object swtIds = value.get(SWT_SERVICE_IDS);
if(swtIds instanceof String) {
String s = (String)value.get(SWT_SERVICE_IDS);
if(s.startsWith("[")) {
// json format
try {
unifiedPathPrefixAuth.setSwtServiceIds(Config.getInstance().getMapper().readValue(s, new TypeReference<List<String>>() {}));
} catch (Exception e) {
logger.error("could not parse the swtServiceIds json with a list of strings.", e);
throw new ConfigException("could not parse the swtServiceIds json with a list of strings.");
}
} else {
// comma separated
unifiedPathPrefixAuth.setSwtServiceIds(Arrays.asList(s.split("\\s*,\\s*")));
}
} else if(swtIds instanceof List ) {
// it must be a json array.
unifiedPathPrefixAuth.setSwtServiceIds((List)swtIds);
}
pathPrefixAuths.add(unifiedPathPrefixAuth);
}
return pathPrefixAuths;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ public void handleRequest(HttpServerExchange exchange) throws Exception {
boolean found = false;
// iterate each entry to check enabled security methods.
for(UnifiedPathPrefixAuth pathPrefixAuth: config.getPathPrefixAuths()) {
if(logger.isTraceEnabled()) logger.trace("Check with requestPath = " + reqPath + " prefix = " + pathPrefixAuth.getPathPrefix());
if(reqPath.startsWith(pathPrefixAuth.getPathPrefix())) {
if(logger.isTraceEnabled()) logger.trace("Check with requestPath = " + reqPath + " prefix = " + pathPrefixAuth.getPrefix());
if(reqPath.startsWith(pathPrefixAuth.getPrefix())) {
found = true;
if(logger.isTraceEnabled()) logger.trace("Found with requestPath = " + reqPath + " prefix = " + pathPrefixAuth.getPathPrefix());
if(logger.isTraceEnabled()) logger.trace("Found with requestPath = " + reqPath + " prefix = " + pathPrefixAuth.getPrefix());
// check jwt and basic first with authorization header, then check the apikey if it is enabled.
if(pathPrefixAuth.isBasic() || pathPrefixAuth.isJwt() || pathPrefixAuth.isSwt()) {
String authorization = exchange.getRequestHeaders().getFirst(Headers.AUTHORIZATION);
Expand Down Expand Up @@ -130,7 +130,7 @@ public void handleRequest(HttpServerExchange exchange) throws Exception {
break;
}
// get the jwkServiceIds list.
if (handler.handleJwt(exchange, pathPrefixAuth.getPathPrefix(), reqPath, pathPrefixAuth.getJwkServiceIds())) {
if (handler.handleJwt(exchange, pathPrefixAuth.getPrefix(), reqPath, pathPrefixAuth.getJwkServiceIds())) {
// verification is passed, go to the next handler in the chain.
break;
} else {
Expand Down Expand Up @@ -174,7 +174,7 @@ public void handleRequest(HttpServerExchange exchange) throws Exception {
break;
}
// get the jwkServiceIds list.
if (handler.handleJwt(exchange, pathPrefixAuth.getPathPrefix(), reqPath, pathPrefixAuth.getJwkServiceIds())) {
if (handler.handleJwt(exchange, pathPrefixAuth.getPrefix(), reqPath, pathPrefixAuth.getJwkServiceIds())) {
// verification is passed, go to the next handler in the chain.
break;
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.networknt.openapi;

import com.fasterxml.jackson.core.type.TypeReference;
import com.networknt.config.Config;
import com.networknt.config.ConfigException;
import org.junit.Assert;
import org.junit.Test;

import java.util.List;
import java.util.Map;

public class UnifiedSecurityConfigTest {
@Test
Expand Down Expand Up @@ -67,4 +71,22 @@ public void testLoadNoListConfig() {
Assert.assertNull(config.getPathPrefixAuths());
}

@Test
public void testPathPrefixAuth() {
String s = "[{\"prefix\":\"/adm/modules\",\"basic\":true},{\"prefix\":\"/adm/server\",\"basic\":true},{\"prefix\":\"/adm/logger\",\"basic\":true},{\"prefix\":\"/adm/health\",\"basic\":true},{\"prefix\":\"/gateway/NavigationTP\",\"jwt\":true,\"jwkServiceIds\":\"Navigation, NavigationJWT\"}]";
if(s.startsWith("[")) {
// json format
try {
List<Map<String, Object>> values = Config.getInstance().getMapper().readValue(s, new TypeReference<>() {});
Assert.assertEquals(5, values.size());
List<UnifiedPathPrefixAuth> pathPrefixAuths = UnifiedSecurityConfig.populatePathPrefixAuths(values);
Assert.assertEquals(5, pathPrefixAuths.size());
} catch (Exception e) {
e.printStackTrace();
throw new ConfigException("could not parse the pathPrefixAuths json with a list of string and object.");
}
} else {
throw new ConfigException("pathPrefixAuths must be a list of string object map.");
}
}
}

0 comments on commit 231fc95

Please sign in to comment.