Skip to content

Commit

Permalink
fix: firstFactors and requiredSecondaryFactors validation
Browse files Browse the repository at this point in the history
  • Loading branch information
sattvikc committed Dec 20, 2023
1 parent 10636dc commit fdc9dfa
Show file tree
Hide file tree
Showing 2 changed files with 307 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/main/java/io/supertokens/multitenancy/Multitenancy.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,51 @@ private static void validateTenantConfig(Main main, TenantConfig targetTenantCon
// Verify that the keys in the coreConfig is valid
validateConfigJsonForInvalidKeys(main, targetTenantConfig.coreConfig);

// Validate firstFactors and requiredSecondaryFactors
{
Set<String> disallowedFactors = new HashSet<>();
Map<String, String> factorIdToRecipeName = new HashMap<>();
if (!targetTenantConfig.emailPasswordConfig.enabled) {
disallowedFactors.add("emailpassword");

factorIdToRecipeName.put("emailpassword", "emailPassword");
}
if (!targetTenantConfig.passwordlessConfig.enabled) {
disallowedFactors.add("otp-email");
disallowedFactors.add("otp-phone");
disallowedFactors.add("link-email");
disallowedFactors.add("link-phone");

factorIdToRecipeName.put("otp-email", "passwordless");
factorIdToRecipeName.put("otp-phone", "passwordless");
factorIdToRecipeName.put("link-email", "passwordless");
factorIdToRecipeName.put("link-phone", "passwordless");
}
if (!targetTenantConfig.thirdPartyConfig.enabled) {
disallowedFactors.add("thirdparty");

factorIdToRecipeName.put("thirdparty", "thirdParty");
}

if (targetTenantConfig.firstFactors != null) {
for (String factor : targetTenantConfig.firstFactors) {
if (disallowedFactors.contains(factor)) {
throw new InvalidConfigException("firstFactors should not contain '" + factor
+ "' because " + factorIdToRecipeName.get(factor) + " is disabled for the tenant.");
}
}
}

if (targetTenantConfig.requiredSecondaryFactors != null) {
for (String factor : targetTenantConfig.requiredSecondaryFactors) {
if (disallowedFactors.contains(factor)) {
throw new InvalidConfigException("requiredSecondaryFactors should not contain '" + factor
+ "' because " + factorIdToRecipeName.get(factor) + " is disabled for the tenant.");
}
}
}
}

// we check if the core config provided is correct
{
if (shouldPreventProtecterdConfigUpdate) {
Expand Down
262 changes: 262 additions & 0 deletions src/test/java/io/supertokens/test/multitenant/api/TestApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,269 @@ public void testDuplicateValuesInFirstFactorsAndRequiredSecondaryFactors() throw
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: requiredSecondaryFactors input should not contain duplicate values", e.getMessage());
}
}

@Test
public void testFirstFactorArrayValueValidationBasedOnDisabledRecipe() throws Exception {
if (StorageLayer.getStorage(process.getProcess()).getType() != STORAGE_TYPE.SQL) {
return;
}

JsonObject config = new JsonObject();
StorageLayer.getBaseStorage(process.getProcess()).modifyConfigToAddANewUserPoolForTesting(config, 1);

TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", true, true, true,
null, false, null, false, null,
config, SemVer.v5_0);

{
String[] factors = new String[]{"emailpassword", "custom"};
try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", false, null, null,
null, true, factors, false, null,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: firstFactors should not contain 'emailpassword' because emailPassword is disabled for the tenant.", e.getMessage());
}

{
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", false, null, null,
null, false, null, false, null,
config, SemVer.v5_0);
}

try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, null, null,
null, true, factors, false, null,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: firstFactors should not contain 'emailpassword' because emailPassword is disabled for the tenant.", e.getMessage());
}
}

{
String[] factors = new String[]{"otp-email", "custom"};
try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, null, false,
null, true, factors, false, null,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: firstFactors should not contain 'otp-email' because passwordless is disabled for the tenant.", e.getMessage());
}

{
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, null, false,
null, false, null, false, null,
config, SemVer.v5_0);
}

try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, null, null,
null, true, factors, false, null,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: firstFactors should not contain 'otp-email' because passwordless is disabled for the tenant.", e.getMessage());
}
}

{
String[] factors = new String[]{"thirdparty", "custom"};
try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, false, null,
null, true, factors, false, null,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: firstFactors should not contain 'thirdparty' because thirdParty is disabled for the tenant.", e.getMessage());
}

{
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, false, null,
null, false, null, false, null,
config, SemVer.v5_0);
}

try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, null, null,
null, true, factors, false, null,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: firstFactors should not contain 'thirdparty' because thirdParty is disabled for the tenant.", e.getMessage());
}
}

}

@Test
public void testRequiredSecondaryFactorArrayValueValidationBasedOnDisabledRecipe() throws Exception {
if (StorageLayer.getStorage(process.getProcess()).getType() != STORAGE_TYPE.SQL) {
return;
}

JsonObject config = new JsonObject();
StorageLayer.getBaseStorage(process.getProcess()).modifyConfigToAddANewUserPoolForTesting(config, 1);

TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", true, true, true,
null, false, null, false, null,
config, SemVer.v5_0);

{
String[] factors = new String[]{"emailpassword", "custom"};
try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", false, null, null,
null, false, null, true, factors,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: requiredSecondaryFactors should not contain 'emailpassword' because emailPassword is disabled for the tenant.", e.getMessage());
}

{
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", false, null, null,
null, false, null, false, null,
config, SemVer.v5_0);
}

try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, null, null,
null, false, null, true, factors,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: requiredSecondaryFactors should not contain 'emailpassword' because emailPassword is disabled for the tenant.", e.getMessage());
}
}

{
String[] factors = new String[]{"otp-email", "custom"};
try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, null, false,
null, false, null, true, factors,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: requiredSecondaryFactors should not contain 'otp-email' because passwordless is disabled for the tenant.", e.getMessage());
}

{
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, null, false,
null, false, null, false, null,
config, SemVer.v5_0);
}

try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, null, null,
null, false, null, true, factors,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: requiredSecondaryFactors should not contain 'otp-email' because passwordless is disabled for the tenant.", e.getMessage());
}
}

{
String[] factors = new String[]{"thirdparty", "custom"};
try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, false, null,
null, false, null, true, factors,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: requiredSecondaryFactors should not contain 'thirdparty' because thirdParty is disabled for the tenant.", e.getMessage());
}

{
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, false, null,
null, false, null, false, null,
config, SemVer.v5_0);
}

try {
TestMultitenancyAPIHelper.createApp(
process.getProcess(),
new TenantIdentifier(null, null, null),
"a1", null, null, null,
null, false, null, true, factors,
config, SemVer.v5_0);
fail();
} catch (HttpResponseException e) {
assertEquals(400, e.statusCode);
assertEquals("Http error. Status Code: 400. Message: Invalid core config: requiredSecondaryFactors should not contain 'thirdparty' because thirdParty is disabled for the tenant.", e.getMessage());
}
}

}
}

0 comments on commit fdc9dfa

Please sign in to comment.