Skip to content

Commit

Permalink
feat: migrate device secrets on iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
Jordan-Nelson authored and khatruong2009 committed Jan 25, 2024
1 parent 55b1998 commit 362cf97
Show file tree
Hide file tree
Showing 7 changed files with 390 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,36 @@ class LegacyCredentialProviderAndroid implements LegacyCredentialProvider {
final bridge = _stateMachine.expect<NativeAuthBridge>();
return bridge.clearLegacyCredentials();
}

@override
Future<LegacyDeviceDetails?> fetchLegacyDeviceSecrets({
CognitoUserPoolConfig? userPoolConfig,
}) {
// TODO: implement fetchLegacyDeviceSecrets
throw UnimplementedError();
}

@override
Future<void> deleteLegacyDeviceSecrets({
CognitoUserPoolConfig? userPoolConfig,
}) {
// TODO: implement deleteLegacyDeviceSecrets
throw UnimplementedError();
}

@override
Future<String?> fetchLegacyAsfDeviceId({
CognitoUserPoolConfig? userPoolConfig,
}) {
// TODO: implement fetchLegacyAsfDeviceId
throw UnimplementedError();
}

@override
Future<void> deleteLegacyAsfDeviceID({
CognitoUserPoolConfig? userPoolConfig,
}) {
// TODO: implement deleteLegacyAsfDeviceID
throw UnimplementedError();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,44 @@ class LegacyCredentialProviderImpl implements LegacyCredentialProvider {
hostedUiConfig: hostedUiConfig,
);
}

@override
Future<LegacyDeviceDetails?> fetchLegacyDeviceSecrets({
CognitoUserPoolConfig? userPoolConfig,
}) async {
if (_instance == null) return null;
return _instance!.fetchLegacyDeviceSecrets(
userPoolConfig: userPoolConfig,
);
}

@override
Future<void> deleteLegacyDeviceSecrets({
CognitoUserPoolConfig? userPoolConfig,
}) async {
if (_instance == null) return;
return _instance!.deleteLegacyDeviceSecrets(
userPoolConfig: userPoolConfig,
);
}

@override
Future<String?> fetchLegacyAsfDeviceId({
CognitoUserPoolConfig? userPoolConfig,
}) async {
if (_instance == null) return null;
return _instance!.fetchLegacyAsfDeviceId(
userPoolConfig: userPoolConfig,
);
}

@override
Future<void> deleteLegacyAsfDeviceID({
CognitoUserPoolConfig? userPoolConfig,
}) async {
if (_instance == null) return;
return _instance!.deleteLegacyAsfDeviceID(
userPoolConfig: userPoolConfig,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,114 @@ class LegacyCredentialProviderIOS implements LegacyCredentialProvider {
}
}

@override
Future<LegacyDeviceDetails?> fetchLegacyDeviceSecrets({
CognitoUserPoolConfig? userPoolConfig,
}) async {
if (userPoolConfig != null) {
final userPoolStorage = await _getUserPoolStorage();
final cognitoUserKeys = LegacyCognitoUserKeys(userPoolConfig);
final currentUserId = await userPoolStorage.read(
key: cognitoUserKeys[LegacyCognitoKey.currentUser],
);
if (currentUserId != null) {
final keys = LegacyDeviceSecretKeys(
currentUserId,
userPoolConfig,
);
final deviceKey = await userPoolStorage.read(
key: keys[LegacyDeviceSecretKey.id],
);
final devicePassword = await userPoolStorage.read(
key: keys[LegacyDeviceSecretKey.secret],
);
final deviceGroupKey = await userPoolStorage.read(
key: keys[LegacyDeviceSecretKey.group],
);
if (deviceKey != null &&
devicePassword != null &&
deviceGroupKey != null) {
return LegacyDeviceDetails(
deviceKey: deviceKey,
deviceGroupKey: deviceGroupKey,
devicePassword: devicePassword,
);
}
}
}

return null;
}

@override
Future<void> deleteLegacyDeviceSecrets({
CognitoUserPoolConfig? userPoolConfig,
}) async {
if (userPoolConfig != null) {
final userPoolStorage = await _getUserPoolStorage();
final cognitoUserKeys = LegacyCognitoUserKeys(userPoolConfig);
final currentUserId = await userPoolStorage.read(
key: cognitoUserKeys[LegacyCognitoKey.currentUser],
);
if (currentUserId != null) {
final keys = LegacyDeviceSecretKeys(
currentUserId,
userPoolConfig,
);
await userPoolStorage.deleteMany([
keys[LegacyDeviceSecretKey.id],
keys[LegacyDeviceSecretKey.secret],
keys[LegacyDeviceSecretKey.group],
]);
}
}
}

@override
Future<String?> fetchLegacyAsfDeviceId({
CognitoUserPoolConfig? userPoolConfig,
}) async {
if (userPoolConfig != null) {
final userPoolStorage = await _getUserPoolStorage();
final cognitoUserKeys = LegacyCognitoUserKeys(userPoolConfig);
final currentUserId = await userPoolStorage.read(
key: cognitoUserKeys[LegacyCognitoKey.currentUser],
);
if (currentUserId != null) {
final keys = LegacyAsfDeviceKeys(
currentUserId,
userPoolConfig,
);
final deviceKey = await userPoolStorage.read(
key: keys[LegacyAsfDeviceKey.id],
);
return deviceKey;
}
}

return null;
}

@override
Future<void> deleteLegacyAsfDeviceID({
CognitoUserPoolConfig? userPoolConfig,
}) async {
if (userPoolConfig != null) {
final userPoolStorage = await _getUserPoolStorage();
final cognitoUserKeys = LegacyCognitoUserKeys(userPoolConfig);
final currentUserId = await userPoolStorage.read(
key: cognitoUserKeys[LegacyCognitoKey.currentUser],
);
if (currentUserId != null) {
final keys = LegacyAsfDeviceKeys(
currentUserId,
userPoolConfig,
);
await userPoolStorage.delete(key: keys[LegacyAsfDeviceKey.id]);
}
}
}

final _bundleIdMemoizer = AsyncMemoizer<String>();

/// Gets the bundle ID.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,24 @@ enum LegacyCognitoIdentityPoolKey {
identityId,
}

/// Discrete keys stored for Legacy Device Secrets on iOS.
enum LegacyDeviceSecretKey {
/// The device key.
id,

/// The device password.
secret,

/// The device group key.
group,
}

/// Discrete keys stored for Legacy ASF on iOS.
enum LegacyAsfDeviceKey {
/// The advanced security feature (ASF) device identifier.
id;
}

/// {@template amplify_auth_cognito.legacy_cognito_identity_pool_keys}
/// Enumerates and iterates over the keys stored in secure storage by
/// legacy Cognito Identity Pool operations.
Expand Down Expand Up @@ -112,6 +130,51 @@ class LegacyCognitoUserPoolKeys
String get prefix => '${config.appClientId}.$currentUserId';
}

/// {@template amplify_auth_cognito.cognito_user_pool_keys}
/// Enumerates and iterates over the keys stored in secure storage for
/// Device Secrets.
/// {@endtemplate}
class LegacyDeviceSecretKeys
extends LegacyIOSCognitoKeys<LegacyDeviceSecretKey> {
/// {@macro amplify_auth_cognito.cognito_user_pool_keys}
const LegacyDeviceSecretKeys(this.currentUserId, this.config);

/// The Cognito identity pool configuration, used to determine the key
/// prefixes.
final CognitoUserPoolConfig config;

/// The current user ID, used to determine the key prefixes.
final String currentUserId;

@override
List<LegacyDeviceSecretKey> get _values => LegacyDeviceSecretKey.values;

@override
String get prefix => '${config.poolId}.$currentUserId.device';
}

/// {@template amplify_auth_cognito.cognito_user_pool_keys}
/// Enumerates and iterates over the keys stored in secure storage for
/// ASF Device Secrets.
/// {@endtemplate}
class LegacyAsfDeviceKeys extends LegacyIOSCognitoKeys<LegacyAsfDeviceKey> {
/// {@macro amplify_auth_cognito.cognito_user_pool_keys}
const LegacyAsfDeviceKeys(this.currentUserId, this.config);

/// The Cognito identity pool configuration, used to determine the key
/// prefixes.
final CognitoUserPoolConfig config;

/// The current user ID, used to determine the key prefixes.
final String currentUserId;

@override
List<LegacyAsfDeviceKey> get _values => LegacyAsfDeviceKey.values;

@override
String get prefix => '${config.poolId}.$currentUserId.asf.device';
}

/// {@template amplify_auth_cognito.cognito_keys}
/// Iterable secure storage keys.
/// {@endtemplate}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,51 @@ abstract interface class LegacyCredentialProvider {
CognitoOAuthConfig? hostedUiConfig,
});

/// Fetches legacy device secrets if they are present.
Future<LegacyDeviceDetails?> fetchLegacyDeviceSecrets({
CognitoUserPoolConfig? userPoolConfig,
});

/// Fetches legacy asf device ID if present.
Future<String?> fetchLegacyAsfDeviceId({
CognitoUserPoolConfig? userPoolConfig,
});

/// Deletes legacy credentials if they are present.
Future<void> deleteLegacyCredentials({
CognitoUserPoolConfig? userPoolConfig,
CognitoIdentityCredentialsProvider? identityPoolConfig,
CognitoOAuthConfig? hostedUiConfig,
});

/// Deletes legacy device secrets if they are present.
Future<void> deleteLegacyDeviceSecrets({
CognitoUserPoolConfig? userPoolConfig,
});

/// Deletes legacy asf device ID if present.
Future<void> deleteLegacyAsfDeviceID({
CognitoUserPoolConfig? userPoolConfig,
});
}

/// {@template amplify_auth_cognito_dart.legacy_device_details}
/// The legacy device details.
/// {@endtemplate}
class LegacyDeviceDetails {
/// {@macro amplify_auth_cognito_dart.legacy_device_details}
const LegacyDeviceDetails({
required this.deviceKey,
required this.deviceGroupKey,
required this.devicePassword,
});

/// The device key/ID.
final String deviceKey;

/// The device group key.
final String deviceGroupKey;

/// The device password.
final String devicePassword;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'package:amplify_auth_cognito_dart/src/credentials/legacy_credential_provider.dart';
import 'package:amplify_auth_cognito_dart/src/sdk/cognito_identity_provider.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
Expand All @@ -18,6 +19,18 @@ abstract class CognitoDeviceSecrets
factory CognitoDeviceSecrets([
void Function(CognitoDeviceSecretsBuilder) updates,
]) = _$CognitoDeviceSecrets;

/// Creates a [CognitoDeviceSecrets] from a [LegacyDeviceDetails].
factory CognitoDeviceSecrets.fromLegacyDeviceDetails(
LegacyDeviceDetails details,
) {
return CognitoDeviceSecrets((b) {
b
..devicePassword = details.devicePassword
..deviceGroupKey = details.deviceGroupKey
..devicePassword = details.devicePassword;
});
}
CognitoDeviceSecrets._();

@BuiltValueHook(finalizeBuilder: true)
Expand Down
Loading

0 comments on commit 362cf97

Please sign in to comment.