diff --git a/packages/at_auth/lib/src/enroll/at_enrollment_impl.dart b/packages/at_auth/lib/src/enroll/at_enrollment_impl.dart index a0b79ccf..13252aa7 100644 --- a/packages/at_auth/lib/src/enroll/at_enrollment_impl.dart +++ b/packages/at_auth/lib/src/enroll/at_enrollment_impl.dart @@ -25,10 +25,10 @@ class AtEnrollmentImpl implements AtEnrollmentBase { AtEnrollmentRequest atEnrollmentRequest, AtLookUp atLookUp) async { switch (atEnrollmentRequest.runtimeType) { case AtInitialEnrollmentRequest: - return await initialClientEnrollment( + return await _initialClientEnrollment( atEnrollmentRequest as AtInitialEnrollmentRequest, atLookUp); case AtNewEnrollmentRequest: - return await newClientEnrollment( + return await _newClientEnrollment( atEnrollmentRequest as AtNewEnrollmentRequest, atLookUp); default: throw AtEnrollmentException( @@ -36,8 +36,7 @@ class AtEnrollmentImpl implements AtEnrollmentBase { } } - @visibleForTesting - Future initialClientEnrollment( + Future _initialClientEnrollment( AtInitialEnrollmentRequest atInitialEnrollmentRequest, AtLookUp atLookUp) async { _logger.finer('inside initialClientEnrollment'); @@ -53,8 +52,7 @@ class AtEnrollmentImpl implements AtEnrollmentBase { ..atAuthKeys = atAuthKeys; } - @visibleForTesting - Future newClientEnrollment( + Future _newClientEnrollment( AtNewEnrollmentRequest atNewEnrollmentRequest, AtLookUp atLookUp) async { _logger.info('Generating APKAM encryption keypair and APKAM symmetric key'); AtPkamKeyPair atPkamKeyPair = AtChopsUtil.generateAtPkamKeyPair(); @@ -112,8 +110,11 @@ class AtEnrollmentImpl implements AtEnrollmentBase { AtEnrollmentRequest atEnrollmentRequest, AtLookUp atLookUp) { switch (atEnrollmentRequest.enrollOperationEnum) { case EnrollOperationEnum.approve: - return _handleApproveOperation( - atEnrollmentRequest as AtEnrollmentNotificationRequest, atLookUp); + if (atEnrollmentRequest is! AtEnrollmentNotificationRequest) { + throw AtEnrollmentException( + 'Invalid atEnrollmentRequest type: $atEnrollmentRequest. Please pass AtEnrollmentNotificationRequest'); + } + return _handleApproveOperation(atEnrollmentRequest, atLookUp); case EnrollOperationEnum.deny: return _handleDenyOperation(atEnrollmentRequest, atLookUp); default: @@ -192,6 +193,8 @@ class AtEnrollmentImpl implements AtEnrollmentBase { } @visibleForTesting + + /// Creates a verb builder instance based on the [request] type EnrollVerbBuilder createEnrollVerbBuilder( AtEnrollmentRequest request, { AtPkamKeyPair? atPkamKeyPair, diff --git a/packages/at_auth/lib/src/enroll/at_enrollment_notification_request.dart b/packages/at_auth/lib/src/enroll/at_enrollment_notification_request.dart index 68a3aa7c..00ac8fa5 100644 --- a/packages/at_auth/lib/src/enroll/at_enrollment_notification_request.dart +++ b/packages/at_auth/lib/src/enroll/at_enrollment_notification_request.dart @@ -1,5 +1,8 @@ import 'package:at_auth/src/enroll/at_enrollment_request.dart'; +/// In APKAM approval flow, use this class from a privileged client to set attributes required for enrollment approval. +/// Once a notification is received on the privileged client which can approve enrollment notifications from new devices, +/// use [AtEnrollmentNotificationRequestBuilder] to create [AtEnrollmentNotificationRequest] class AtEnrollmentNotificationRequest extends AtEnrollmentRequest { String _encryptedApkamSymmetricKey; diff --git a/packages/at_auth/lib/src/enroll/at_enrollment_request.dart b/packages/at_auth/lib/src/enroll/at_enrollment_request.dart index 63bf28a9..2424858e 100644 --- a/packages/at_auth/lib/src/enroll/at_enrollment_request.dart +++ b/packages/at_auth/lib/src/enroll/at_enrollment_request.dart @@ -1,7 +1,8 @@ import 'package:at_auth/at_auth.dart'; import 'package:at_commons/at_commons.dart'; -/// Represents an enrollment request for APKAM. +/// Base class containing common attributes for enrollment requests either from first onboarding client with enrollment enabled +/// or a new client requesting enrollment. class AtEnrollmentRequest { final String? _appName; final String? _deviceName; diff --git a/packages/at_auth/lib/src/enroll/at_initial_enrollment_request.dart b/packages/at_auth/lib/src/enroll/at_initial_enrollment_request.dart index d5b26b56..49584e5e 100644 --- a/packages/at_auth/lib/src/enroll/at_initial_enrollment_request.dart +++ b/packages/at_auth/lib/src/enroll/at_initial_enrollment_request.dart @@ -1,5 +1,8 @@ import 'package:at_auth/src/enroll/at_enrollment_request.dart'; +/// Class for attributes required specifically for enrollment from the first onboarding client that +/// has enableEnrollment flag set to true from client side in preferences. +/// Default encryption private key and default self encryption keys are encrypted using APKAM symmetric key generated for the onboarding client. class AtInitialEnrollmentRequest extends AtEnrollmentRequest { final String _encryptedDefaultEncryptionPrivateKey; final String _encryptedDefaultSelfEncryptionKey; diff --git a/packages/at_auth/lib/src/enroll/at_new_enrollment_request.dart b/packages/at_auth/lib/src/enroll/at_new_enrollment_request.dart index cf9d5d00..7051b274 100644 --- a/packages/at_auth/lib/src/enroll/at_new_enrollment_request.dart +++ b/packages/at_auth/lib/src/enroll/at_new_enrollment_request.dart @@ -1,5 +1,6 @@ import 'package:at_auth/src/enroll/at_enrollment_request.dart'; +/// Class for attributes required specifically for new enrollment requests from client. class AtNewEnrollmentRequest extends AtEnrollmentRequest { String _otp; @@ -19,7 +20,7 @@ class AtNewEnrollmentRequestBuilder extends AtEnrollmentRequestBuilder { return this; } - /// Builds and returns an instance of [AtInitialEnrollmentRequest]. + /// Builds and returns an instance of [AtNewEnrollmentRequest]. AtNewEnrollmentRequest build() { return AtNewEnrollmentRequest.builder(this); } diff --git a/packages/at_auth/test/enrollment_test.dart b/packages/at_auth/test/enrollment_test.dart index fcef798e..556ee53c 100644 --- a/packages/at_auth/test/enrollment_test.dart +++ b/packages/at_auth/test/enrollment_test.dart @@ -81,22 +81,20 @@ void main() { when(() => (mockAtLookUp as AtLookupImpl).close()) .thenAnswer((_) async => ()); - // AtEnrollmentRequest atEnrollmentRequest = (AtEnrollmentRequest.request() - // ..setAppName('wavi') - // ..setDeviceName('pixel') - // ..setOtp('12345') - // ..setNamespaces({'wavi': 'rw'})) - // .build(); - - AtPkamKeyPair atPkamKeyPair = - AtPkamKeyPair.create(apkamPublicKey, apkamPrivateKey); - SymmetricKey symmetricKey = AESKey(apkamSymmetricKey); - - // AtEnrollmentResponse enrollmentSubmissionResponse = - // await atEnrollmentServiceImpl.enrollInternal( - // atEnrollmentRequest, mockAtLookUp, atPkamKeyPair, symmetricKey); - // expect(enrollmentSubmissionResponse.enrollmentId, '123'); - // expect(enrollmentSubmissionResponse.enrollStatus, EnrollStatus.pending); + AtNewEnrollmentRequestBuilder atNewEnrollmentRequestBuilder = + AtNewEnrollmentRequestBuilder() + ..setAppName('wavi') + ..setDeviceName('pixel') + ..setNamespaces({'wavi': 'rw'}) + ..setOtp('A123FE') + ..setApkamPublicKey('testApkamPublicKey'); + AtNewEnrollmentRequest atNewEnrollmentRequest = + atNewEnrollmentRequestBuilder.build(); + + AtEnrollmentResponse atEnrollmentResponse = await atEnrollmentServiceImpl + .submitEnrollment(atNewEnrollmentRequest, mockAtLookUp); + expect(atEnrollmentResponse.enrollmentId, '123'); + expect(atEnrollmentResponse.enrollStatus, EnrollStatus.pending); }); group('A group of test related to AtEnrollmentBuilder', () { @@ -222,6 +220,58 @@ void main() { expect(atEnrollmentRequest.enrollmentId, 'ABC-123-ID'); }); }); + group('Group of tests to check createEnrollVerbBuilder method', () { + test( + 'A test to verify createEnrollVerbBuilder for AtInitialEnrollmentRequest', + () { + var enrollmentImpl = AtEnrollmentImpl('@alice'); + AtInitialEnrollmentRequest request = (AtInitialEnrollmentRequestBuilder() + ..setAppName('TestApp') + ..setDeviceName('TestDevice') + ..setNamespaces({"wavi": "rw"}) + ..setEncryptedDefaultEncryptionPrivateKey('encryptedPrivateKey') + ..setEncryptedDefaultSelfEncryptionKey('encryptedSelfEncryptionKey') + ..setApkamPublicKey('apkamPublicKey')) + .build(); + + var result = enrollmentImpl.createEnrollVerbBuilder(request); + + expect(result.appName, equals('TestApp')); + expect(result.deviceName, equals('TestDevice')); + expect(result.namespaces, equals({'wavi': 'rw'})); + expect(result.encryptedDefaultEncryptionPrivateKey, + equals('encryptedPrivateKey')); + expect(result.encryptedDefaultSelfEncryptionKey, + equals('encryptedSelfEncryptionKey')); + expect(result.apkamPublicKey, equals('apkamPublicKey')); + expect(result.otp, isNull); + expect(result.encryptedAPKAMSymmetricKey, isNull); + }); + + test('A test for createEnrollVerbBuilder for AtNewEnrollmentRequest', () { + var request = (AtNewEnrollmentRequestBuilder() + ..setAppName('TestApp') + ..setDeviceName('TestDevice') + ..setNamespaces({"wavi": "rw", "contact": "r"}) + ..setOtp('A1CFG3') + ..setApkamPublicKey('apkamPublicKey')) + .build(); + + var enrollmentImpl = AtEnrollmentImpl('@alice'); + AtPkamKeyPair atPkamKeyPair = AtChopsUtil.generateAtPkamKeyPair(); + var result = enrollmentImpl.createEnrollVerbBuilder(request, + atPkamKeyPair: atPkamKeyPair); + + // Assert + expect(result.appName, equals('TestApp')); + expect(result.deviceName, equals('TestDevice')); + expect(result.namespaces, equals({"wavi": "rw", "contact": "r"})); + expect(result.otp, equals('A1CFG3')); + expect(result.apkamPublicKey, isNotNull); + expect(result.encryptedDefaultEncryptionPrivateKey, isNull); + expect(result.encryptedDefaultSelfEncryptionKey, isNull); + }); + }); } class LookUpVerbBuilderMatcher extends Matcher {