From 0fdd619c9ba59df679ceb6775167f7414c9f352f Mon Sep 17 00:00:00 2001 From: gkc Date: Fri, 24 May 2024 15:06:56 +0100 Subject: [PATCH] test: add a unit test to verify that the ttl is set to -1 (do not expire) if a ttl is not supplied to otp:put refactor: rename isOTPValid to isPasscodeValid --- .../verb/handler/abstract_verb_handler.dart | 12 ++-- .../src/verb/handler/enroll_verb_handler.dart | 2 +- .../test/abstract_verb_handler_test.dart | 2 +- .../test/enroll_verb_test.dart | 2 +- .../test/otp_verb_test.dart | 55 +++++++++++++------ 5 files changed, 46 insertions(+), 27 deletions(-) diff --git a/packages/at_secondary_server/lib/src/verb/handler/abstract_verb_handler.dart b/packages/at_secondary_server/lib/src/verb/handler/abstract_verb_handler.dart index e687c949e..33b71e6cb 100644 --- a/packages/at_secondary_server/lib/src/verb/handler/abstract_verb_handler.dart +++ b/packages/at_secondary_server/lib/src/verb/handler/abstract_verb_handler.dart @@ -270,14 +270,14 @@ abstract class AbstractVerbHandler implements VerbHandler { /// /// Additionally, this function removes the OTP from the keystore to prevent /// its reuse. - Future isOTPValid(String? otp) async { - if (otp == null) { + Future isPasscodeValid(String? passcode) async { + if (passcode == null) { return false; } // 1. Check if user has configured an SPP(Semi-Permanent Pass-code). // If SPP key is available, check if the otp sent is a valid pass code. // If yes, return true, else check it is a valid OTP. - String passcodeKey = OtpVerbHandler.passcodeKey(otp, isSpp: true); + String passcodeKey = OtpVerbHandler.passcodeKey(passcode, isSpp: true); if (!keyStore.isKeyExists(passcodeKey)) { // if new SPPKey does not exist in keystore, check for SPP data against legacy SPP key // New SPP key has __otp namespace, legacy key does NOT have any namespace @@ -290,7 +290,7 @@ abstract class AbstractVerbHandler implements VerbHandler { // (which is the actual SPP) // By comparison, OTPs are stored with the key being ${OTP}.__otp@alice // i.e. the OTP is part of the key, and the stored data is irrelevant - if (sppAtData?.data?.toLowerCase() == otp.toLowerCase()) { + if (sppAtData?.data?.toLowerCase() == passcode.toLowerCase()) { if (SecondaryUtil.isActiveKey(sppAtData)) { return true; } else { @@ -303,12 +303,12 @@ abstract class AbstractVerbHandler implements VerbHandler { } // 2. If not a valid SPP, then check against OTP keys - String otpKey = OtpVerbHandler.passcodeKey(otp, isSpp: false); + String otpKey = OtpVerbHandler.passcodeKey(passcode, isSpp: false); if (!keyStore.isKeyExists(otpKey)) { // if new OTPKey does not exist in keystore, check for OTP data against legacy OTPKey // New OTP key has __otp namespace, legacy key does not have namespace otpKey = - 'private:${otp.toLowerCase()}${AtSecondaryServerImpl.getInstance().currentAtSign}'; + 'private:${passcode.toLowerCase()}${AtSecondaryServerImpl.getInstance().currentAtSign}'; } AtData? otpAtData; diff --git a/packages/at_secondary_server/lib/src/verb/handler/enroll_verb_handler.dart b/packages/at_secondary_server/lib/src/verb/handler/enroll_verb_handler.dart index 1a13fc9d8..2a7542a18 100644 --- a/packages/at_secondary_server/lib/src/verb/handler/enroll_verb_handler.dart +++ b/packages/at_secondary_server/lib/src/verb/handler/enroll_verb_handler.dart @@ -191,7 +191,7 @@ class EnrollVerbHandler extends AbstractVerbHandler { // OTP is sent only in enrollment request which is submitted on // unauthenticated connection. if (atConnection.metaData.isAuthenticated == false) { - var isValid = await isOTPValid(enrollParams.otp); + var isValid = await isPasscodeValid(enrollParams.otp); if (!isValid) { _lastInvalidOtpReceivedInMills = DateTime.now().toUtc().millisecondsSinceEpoch; diff --git a/packages/at_secondary_server/test/abstract_verb_handler_test.dart b/packages/at_secondary_server/test/abstract_verb_handler_test.dart index d3d1110c5..9a3bc0c9f 100644 --- a/packages/at_secondary_server/test/abstract_verb_handler_test.dart +++ b/packages/at_secondary_server/test/abstract_verb_handler_test.dart @@ -97,7 +97,7 @@ class TestUpdateVerbHandler extends AbstractVerbHandler { } @override - Future isOTPValid(String? otp) { + Future isPasscodeValid(String? otp) { // TODO: implement isOTPValid throw UnimplementedError(); } diff --git a/packages/at_secondary_server/test/enroll_verb_test.dart b/packages/at_secondary_server/test/enroll_verb_test.dart index 458ab7a46..cfb10c0ba 100644 --- a/packages/at_secondary_server/test/enroll_verb_test.dart +++ b/packages/at_secondary_server/test/enroll_verb_test.dart @@ -108,7 +108,7 @@ void main() { response, enrollmentRequestVerbParams, inboundConnection); String enrollmentId = jsonDecode(response.data!)['enrollmentId']; expect(enrollmentId, isNotNull); - expect(await enrollVerbHandler.isOTPValid(otp), false); + expect(await enrollVerbHandler.isPasscodeValid(otp), false); }); tearDown(() async => await verbTestsTearDown()); }); diff --git a/packages/at_secondary_server/test/otp_verb_test.dart b/packages/at_secondary_server/test/otp_verb_test.dart index c22b18c08..ac2903dbe 100644 --- a/packages/at_secondary_server/test/otp_verb_test.dart +++ b/packages/at_secondary_server/test/otp_verb_test.dart @@ -90,7 +90,7 @@ void main() { OtpVerbHandler otpVerbHandler = OtpVerbHandler(secondaryKeyStore); await otpVerbHandler.processVerb(response, verbParams, inboundConnection); String? otp = response.data; - expect(await otpVerbHandler.isOTPValid(otp), true); + expect(await otpVerbHandler.isPasscodeValid(otp), true); }); test('A test to verify otp:get with TTL set expires after the TTL is met', @@ -103,7 +103,7 @@ void main() { await otpVerbHandler.processVerb(response, verbParams, inboundConnection); String? otp = response.data; await Future.delayed(Duration(seconds: 1)); - expect(await otpVerbHandler.isOTPValid(otp), false); + expect(await otpVerbHandler.isPasscodeValid(otp), false); }); tearDown(() async => await verbTestsTearDown()); }); @@ -142,7 +142,7 @@ void main() { inboundConnection.metaData.isAuthenticated = true; OtpVerbHandler otpVerbHandler = OtpVerbHandler(secondaryKeyStore); await otpVerbHandler.processVerb(response, verbParams, inboundConnection); - expect(await otpVerbHandler.isOTPValid(response.data), true); + expect(await otpVerbHandler.isPasscodeValid(response.data), true); }); test('A test to verify otp:validate returns invalid when OTP is expired', @@ -155,7 +155,7 @@ void main() { await otpVerbHandler.processVerb(response, verbParams, inboundConnection); String? otp = response.data; await Future.delayed(Duration(milliseconds: 2)); - expect(await otpVerbHandler.isOTPValid(otp), false); + expect(await otpVerbHandler.isPasscodeValid(otp), false); }); test('A test to verify default otp expiry not overwritten', () async { @@ -183,7 +183,7 @@ void main() { () async { String otp = 'ABC123'; OtpVerbHandler otpVerbHandler = OtpVerbHandler(secondaryKeyStore); - expect(await otpVerbHandler.isOTPValid(otp), false); + expect(await otpVerbHandler.isPasscodeValid(otp), false); }); test('A test to verify otp is removed from the keystore after use', @@ -195,8 +195,8 @@ void main() { OtpVerbHandler otpVerbHandler = OtpVerbHandler(secondaryKeyStore); await otpVerbHandler.processVerb(response, verbParams, inboundConnection); String? otp = response.data; - expect(await otpVerbHandler.isOTPValid(otp), true); - expect(await otpVerbHandler.isOTPValid(otp), false); + expect(await otpVerbHandler.isPasscodeValid(otp), true); + expect(await otpVerbHandler.isPasscodeValid(otp), false); }); test('validate backwards compatability with legacy otp key', () async { @@ -210,7 +210,7 @@ void main() { await secondaryKeyStore.put(otpLegacyKey, value); OtpVerbHandler otpVerbHandler = OtpVerbHandler(secondaryKeyStore); - expect(await otpVerbHandler.isOTPValid(testOtp), true); + expect(await otpVerbHandler.isPasscodeValid(testOtp), true); }); tearDown(() async => await verbTestsTearDown()); }); @@ -240,10 +240,10 @@ void main() { enrollmentId; OtpVerbHandler otpVerbHandler = OtpVerbHandler(secondaryKeyStore); await otpVerbHandler.processVerb(response, verbParams, inboundConnection); - expect(await otpVerbHandler.isOTPValid(passcode), true); + expect(await otpVerbHandler.isPasscodeValid(passcode), true); // Adding expect again to ensure the Semi-permanent passcodes are not deleted // after one time use. - expect(await otpVerbHandler.isOTPValid(passcode), true); + expect(await otpVerbHandler.isPasscodeValid(passcode), true); }); test('set spp with a ttl, check isOTPValid before ttl expires', () async { @@ -256,10 +256,11 @@ void main() { enrollmentId; OtpVerbHandler otpVerbHandler = OtpVerbHandler(secondaryKeyStore); await otpVerbHandler.processVerb(response, verbParams, inboundConnection); - expect(await otpVerbHandler.isOTPValid(passcode), true); + expect(await otpVerbHandler.isPasscodeValid(passcode), true); // Adding expect again to ensure the Semi-permanent passcodes are not deleted // after one time use. - expect(await otpVerbHandler.isOTPValid(passcode), true); + await Future.delayed(Duration(milliseconds: 10)); + expect(await otpVerbHandler.isPasscodeValid(passcode), true); }); test('set spp with a ttl, check isOTPValid before and after ttl expires', @@ -273,13 +274,31 @@ void main() { enrollmentId; OtpVerbHandler otpVerbHandler = OtpVerbHandler(secondaryKeyStore); await otpVerbHandler.processVerb(response, verbParams, inboundConnection); - expect(await otpVerbHandler.isOTPValid(passcode), true); + expect(await otpVerbHandler.isPasscodeValid(passcode), true); // Adding expect again to ensure the Semi-permanent passcodes are not deleted // after one time use. - expect(await otpVerbHandler.isOTPValid(passcode), true); + expect(await otpVerbHandler.isPasscodeValid(passcode), true); await Future.delayed(Duration(milliseconds: 51)); - expect(await otpVerbHandler.isOTPValid(passcode), false); + expect(await otpVerbHandler.isPasscodeValid(passcode), false); + }); + + test('set spp without a ttl, verify its ttl has been set to -1', () async { + String passcode = 'SppWithoutTtl'; + Response response = Response(); + HashMap verbParams = + getVerbParam(VerbSyntax.otp, 'otp:put:$passcode'); + inboundConnection.metaData.isAuthenticated = true; + (inboundConnection.metaData as InboundConnectionMetadata).enrollmentId = + enrollmentId; + OtpVerbHandler otpVerbHandler = OtpVerbHandler(secondaryKeyStore); + await otpVerbHandler.processVerb(response, verbParams, inboundConnection); + await Future.delayed(Duration(milliseconds: 2)); + expect(await otpVerbHandler.isPasscodeValid(passcode), true); + + String sppKey = OtpVerbHandler.passcodeKey(passcode, isSpp: true); + var atData = await secondaryKeyStore.get(sppKey); + expect(atData?.metaData?.ttl, -1); }); test('A test to verify pass code can be updated', () async { @@ -292,14 +311,14 @@ void main() { enrollmentId; OtpVerbHandler otpVerbHandler = OtpVerbHandler(secondaryKeyStore); await otpVerbHandler.processVerb(response, verbParams, inboundConnection); - expect(await otpVerbHandler.isOTPValid(passcode), true); + expect(await otpVerbHandler.isPasscodeValid(passcode), true); // Update the pass-code passcode = 'xyz987'; response = Response(); verbParams = getVerbParam(VerbSyntax.otp, 'otp:put:$passcode'); otpVerbHandler = OtpVerbHandler(secondaryKeyStore); await otpVerbHandler.processVerb(response, verbParams, inboundConnection); - expect(await otpVerbHandler.isOTPValid(passcode), true); + expect(await otpVerbHandler.isPasscodeValid(passcode), true); }); test('validate backwards compatability with legacy ssp key', () async { @@ -310,7 +329,7 @@ void main() { await secondaryKeyStore.put(otpLegacyKey, value); OtpVerbHandler otpVerbHandler = OtpVerbHandler(secondaryKeyStore); - expect(await otpVerbHandler.isOTPValid(testOtp), true); + expect(await otpVerbHandler.isPasscodeValid(testOtp), true); }); tearDown(() async => await verbTestsTearDown()); });