-
Notifications
You must be signed in to change notification settings - Fork 537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: Replace TOTP_NOT_ENABLED_ERROR status and make deviceName optional #729
Changes from 7 commits
06b2cf3
693b70e
b10a23c
1a14e22
14209d8
157d94a
fc9f706
ec6dd7e
98b24ae
646b0b8
430704e
a7d2f27
363492c
5b68216
59373c2
84b1b9d
7ef46d1
29f9643
6be5b8c
0139624
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,6 @@ | |
import io.supertokens.pluginInterface.totp.TOTPDevice; | ||
import io.supertokens.pluginInterface.totp.TOTPUsedCode; | ||
import io.supertokens.pluginInterface.totp.exception.DeviceAlreadyExistsException; | ||
import io.supertokens.pluginInterface.totp.exception.TotpNotEnabledException; | ||
import io.supertokens.pluginInterface.totp.exception.UnknownDeviceException; | ||
import io.supertokens.pluginInterface.totp.exception.UsedCodeAlreadyExistsException; | ||
import io.supertokens.pluginInterface.totp.sqlStorage.TOTPSQLStorage; | ||
|
@@ -107,6 +106,11 @@ public static TOTPDevice registerDevice(AppIdentifierWithStorage appIdentifierWi | |
} | ||
|
||
TOTPSQLStorage totpStorage = appIdentifierWithStorage.getTOTPStorage(); | ||
|
||
if (deviceName == null) { | ||
rishabhpoddar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
TOTPDevice[] devices = totpStorage.getDevices(appIdentifierWithStorage, userId); | ||
deviceName = "TOTP Device " + (devices.length + 1); | ||
rishabhpoddar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
String secret = generateSecret(); | ||
TOTPDevice device = new TOTPDevice(userId, deviceName, secret, period, skew, false); | ||
|
@@ -118,7 +122,7 @@ public static TOTPDevice registerDevice(AppIdentifierWithStorage appIdentifierWi | |
private static void checkAndStoreCode(TenantIdentifierWithStorage tenantIdentifierWithStorage, Main main, | ||
String userId, TOTPDevice[] devices, | ||
String code) | ||
throws InvalidTotpException, TotpNotEnabledException, | ||
throws InvalidTotpException, UnknownDeviceException, | ||
LimitReachedException, StorageQueryException, StorageTransactionLogicException, | ||
TenantOrAppNotFoundException { | ||
// Note that the TOTP cron runs every 1 hour, so all the expired tokens can stay | ||
|
@@ -241,7 +245,7 @@ private static void checkAndStoreCode(TenantIdentifierWithStorage tenantIdentifi | |
try { | ||
totpSQLStorage.insertUsedCode_Transaction(con, tenantIdentifierWithStorage, newCode); | ||
totpSQLStorage.commitTransaction(con); | ||
} catch (UsedCodeAlreadyExistsException | TotpNotEnabledException e) { | ||
} catch (UsedCodeAlreadyExistsException | UnknownDeviceException e) { | ||
rishabhpoddar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
throw new StorageTransactionLogicException(e); | ||
} | ||
|
||
|
@@ -264,8 +268,8 @@ private static void checkAndStoreCode(TenantIdentifierWithStorage tenantIdentifi | |
throw (LimitReachedException) e.actualException; | ||
} else if (e.actualException instanceof InvalidTotpException) { | ||
throw (InvalidTotpException) e.actualException; | ||
} else if (e.actualException instanceof TotpNotEnabledException) { | ||
throw (TotpNotEnabledException) e.actualException; | ||
} else if (e.actualException instanceof UnknownDeviceException) { | ||
throw (UnknownDeviceException) e.actualException; | ||
} else if (e.actualException instanceof UsedCodeAlreadyExistsException) { | ||
rishabhpoddar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// retry the transaction after a small delay: | ||
int delayInMs = (int) (Math.random() * 10 + 1); | ||
|
@@ -284,7 +288,7 @@ private static void checkAndStoreCode(TenantIdentifierWithStorage tenantIdentifi | |
@TestOnly | ||
public static boolean verifyDevice(Main main, | ||
String userId, String deviceName, String code) | ||
throws TotpNotEnabledException, UnknownDeviceException, InvalidTotpException, | ||
throws UnknownDeviceException, InvalidTotpException, | ||
LimitReachedException, StorageQueryException, StorageTransactionLogicException { | ||
try { | ||
return verifyDevice(new TenantIdentifierWithStorage(null, null, null, StorageLayer.getStorage(main)), main, | ||
|
@@ -296,7 +300,7 @@ public static boolean verifyDevice(Main main, | |
|
||
public static boolean verifyDevice(TenantIdentifierWithStorage tenantIdentifierWithStorage, Main main, | ||
String userId, String deviceName, String code) | ||
throws TotpNotEnabledException, UnknownDeviceException, InvalidTotpException, | ||
throws UnknownDeviceException, InvalidTotpException, | ||
LimitReachedException, StorageQueryException, StorageTransactionLogicException, | ||
TenantOrAppNotFoundException { | ||
// Here boolean return value tells whether the device has been | ||
|
@@ -312,7 +316,7 @@ public static boolean verifyDevice(TenantIdentifierWithStorage tenantIdentifierW | |
// Check if the user has any devices: | ||
TOTPDevice[] devices = totpStorage.getDevices(tenantIdentifierWithStorage.toAppIdentifier(), userId); | ||
if (devices.length == 0) { | ||
throw new TotpNotEnabledException(); | ||
throw new UnknownDeviceException(); | ||
} | ||
|
||
// Check if the requested device exists: | ||
|
@@ -337,8 +341,12 @@ public static boolean verifyDevice(TenantIdentifierWithStorage tenantIdentifierW | |
// verified in the devices table (because it was deleted/renamed). So the user | ||
// gets a UnknownDevceException. | ||
// This behaviour is okay so we can ignore it. | ||
checkAndStoreCode(tenantIdentifierWithStorage, main, userId, new TOTPDevice[]{matchingDevice}, | ||
code); | ||
try{ | ||
checkAndStoreCode(tenantIdentifierWithStorage, main, userId, new TOTPDevice[]{matchingDevice}, code); | ||
} catch (UnknownDeviceException e) { | ||
// User must have deleted the device in parallel. | ||
throw new UnknownDeviceException(); | ||
} | ||
// Will reach here only if the code is valid: | ||
totpStorage.markDeviceAsVerified(tenantIdentifierWithStorage.toAppIdentifier(), userId, deviceName); | ||
return true; // Newly verified | ||
|
@@ -347,7 +355,7 @@ public static boolean verifyDevice(TenantIdentifierWithStorage tenantIdentifierW | |
@TestOnly | ||
public static void verifyCode(Main main, String userId, | ||
String code, boolean allowUnverifiedDevices) | ||
throws TotpNotEnabledException, InvalidTotpException, LimitReachedException, | ||
throws InvalidTotpException, LimitReachedException, | ||
StorageQueryException, StorageTransactionLogicException, FeatureNotEnabledException { | ||
try { | ||
verifyCode(new TenantIdentifierWithStorage(null, null, null, StorageLayer.getStorage(main)), main, | ||
|
@@ -359,7 +367,7 @@ public static void verifyCode(Main main, String userId, | |
|
||
public static void verifyCode(TenantIdentifierWithStorage tenantIdentifierWithStorage, Main main, String userId, | ||
String code, boolean allowUnverifiedDevices) | ||
throws TotpNotEnabledException, InvalidTotpException, LimitReachedException, | ||
throws InvalidTotpException, LimitReachedException, | ||
StorageQueryException, StorageTransactionLogicException, FeatureNotEnabledException, | ||
TenantOrAppNotFoundException { | ||
|
||
|
@@ -374,7 +382,8 @@ public static void verifyCode(TenantIdentifierWithStorage tenantIdentifierWithSt | |
// Check if the user has any devices: | ||
TOTPDevice[] devices = totpStorage.getDevices(tenantIdentifierWithStorage.toAppIdentifier(), userId); | ||
if (devices.length == 0) { | ||
throw new TotpNotEnabledException(); | ||
// No devices found. So we can't verify the code anyway. | ||
throw new InvalidTotpException(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe it's better to throw an UnknownUserIdTotpException, since the input to this API is also the userId There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be an additional status code that is sent to the backend sdk There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
} | ||
|
||
// Filter out unverified devices: | ||
|
@@ -386,13 +395,19 @@ public static void verifyCode(TenantIdentifierWithStorage tenantIdentifierWithSt | |
// another API call. We will still check the code against the updated set of | ||
// devices and store it in the used codes table. This behaviour is okay so we | ||
// can ignore it. | ||
checkAndStoreCode(tenantIdentifierWithStorage, main, userId, devices, code); | ||
try{ | ||
checkAndStoreCode(tenantIdentifierWithStorage, main, userId, devices, code); | ||
} catch (UnknownDeviceException e) { | ||
// User must have deleted the device in parallel | ||
// since they cannot un-verify a device (no API exists) | ||
throw new InvalidTotpException(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe it's better to throw an UnknownUserIdTotpException, since the input to this API is also the userId There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
} | ||
} | ||
|
||
@TestOnly | ||
public static void removeDevice(Main main, String userId, | ||
String deviceName) | ||
throws StorageQueryException, UnknownDeviceException, TotpNotEnabledException, | ||
throws StorageQueryException, UnknownDeviceException, | ||
StorageTransactionLogicException { | ||
try { | ||
removeDevice(new AppIdentifierWithStorage(null, null, StorageLayer.getStorage(main)), | ||
|
@@ -407,7 +422,7 @@ public static void removeDevice(Main main, String userId, | |
*/ | ||
public static void removeDevice(AppIdentifierWithStorage appIdentifierWithStorage, String userId, | ||
String deviceName) | ||
throws StorageQueryException, UnknownDeviceException, TotpNotEnabledException, | ||
throws StorageQueryException, UnknownDeviceException, | ||
StorageTransactionLogicException, TenantOrAppNotFoundException { | ||
TOTPSQLStorage storage = appIdentifierWithStorage.getTOTPStorage(); | ||
|
||
|
@@ -432,12 +447,6 @@ public static void removeDevice(AppIdentifierWithStorage appIdentifierWithStorag | |
return; | ||
} catch (StorageTransactionLogicException e) { | ||
if (e.actualException instanceof UnknownDeviceException) { | ||
// Check if any device exists for the user: | ||
TOTPDevice[] devices = storage.getDevices(appIdentifierWithStorage, userId); | ||
if (devices.length == 0) { | ||
throw new TotpNotEnabledException(); | ||
} | ||
|
||
throw (UnknownDeviceException) e.actualException; | ||
} | ||
|
||
|
@@ -448,8 +457,7 @@ public static void removeDevice(AppIdentifierWithStorage appIdentifierWithStorag | |
@TestOnly | ||
public static void updateDeviceName(Main main, String userId, | ||
String oldDeviceName, String newDeviceName) | ||
throws StorageQueryException, DeviceAlreadyExistsException, UnknownDeviceException, | ||
TotpNotEnabledException { | ||
throws StorageQueryException, DeviceAlreadyExistsException, UnknownDeviceException { | ||
try { | ||
updateDeviceName(new AppIdentifierWithStorage(null, null, StorageLayer.getStorage(main)), | ||
userId, oldDeviceName, newDeviceName); | ||
|
@@ -460,25 +468,14 @@ public static void updateDeviceName(Main main, String userId, | |
|
||
public static void updateDeviceName(AppIdentifierWithStorage appIdentifierWithStorage, String userId, | ||
String oldDeviceName, String newDeviceName) | ||
throws StorageQueryException, DeviceAlreadyExistsException, UnknownDeviceException, | ||
TotpNotEnabledException, TenantOrAppNotFoundException { | ||
throws StorageQueryException, DeviceAlreadyExistsException, UnknownDeviceException, TenantOrAppNotFoundException { | ||
TOTPSQLStorage totpStorage = appIdentifierWithStorage.getTOTPStorage(); | ||
try { | ||
totpStorage.updateDeviceName(appIdentifierWithStorage, userId, oldDeviceName, newDeviceName); | ||
} catch (UnknownDeviceException e) { | ||
// Check if any device exists for the user: | ||
TOTPDevice[] devices = totpStorage.getDevices(appIdentifierWithStorage, userId); | ||
if (devices.length == 0) { | ||
throw new TotpNotEnabledException(); | ||
} else { | ||
throw e; | ||
} | ||
} | ||
totpStorage.updateDeviceName(appIdentifierWithStorage, userId, oldDeviceName, newDeviceName); | ||
} | ||
|
||
@TestOnly | ||
public static TOTPDevice[] getDevices(Main main, String userId) | ||
throws StorageQueryException, TotpNotEnabledException { | ||
throws StorageQueryException { | ||
try { | ||
return getDevices(new AppIdentifierWithStorage(null, null, StorageLayer.getStorage(main)), | ||
userId); | ||
|
@@ -488,13 +485,10 @@ public static TOTPDevice[] getDevices(Main main, String userId) | |
} | ||
|
||
public static TOTPDevice[] getDevices(AppIdentifierWithStorage appIdentifierWithStorage, String userId) | ||
throws StorageQueryException, TotpNotEnabledException, TenantOrAppNotFoundException { | ||
throws StorageQueryException, TenantOrAppNotFoundException { | ||
TOTPSQLStorage totpStorage = appIdentifierWithStorage.getTOTPStorage(); | ||
|
||
TOTPDevice[] devices = totpStorage.getDevices(appIdentifierWithStorage, userId); | ||
if (devices.length == 0) { | ||
throw new TotpNotEnabledException(); | ||
} | ||
return devices; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see my comment in plugin interface PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you're talking about replacing
TotpNotEnabledError
with newUnknownUserIdError
. If yes, done.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check and confirm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done