diff --git a/packages/auth/amplify_auth_cognito/android/app/src/main/java/com/example/app/NativeAuthPlugin.kt b/packages/auth/amplify_auth_cognito/android/app/src/main/java/com/example/app/NativeAuthPlugin.kt new file mode 100644 index 0000000000..903cf609aa --- /dev/null +++ b/packages/auth/amplify_auth_cognito/android/app/src/main/java/com/example/app/NativeAuthPlugin.kt @@ -0,0 +1,931 @@ +// +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +package com.amazonaws.amplify.amplify_auth_cognito; + +import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import io.flutter.plugin.common.BasicMessageChannel; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MessageCodec; +import io.flutter.plugin.common.StandardMessageCodec; +import java.io.ByteArrayOutputStream; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** Generated class from Pigeon. */ +@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"}) +public class NativeAuthPlugin { + + /** Error class for passing custom error details to Flutter via a thrown PlatformException. */ + public static class FlutterError extends RuntimeException { + + /** The error code. */ + public final String code; + + /** The error details. Must be a datatype supported by the api codec. */ + public final Object details; + + public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) + { + super(message); + this.code = code; + this.details = details; + } + } + + @NonNull + protected static ArrayList wrapError(@NonNull Throwable exception) { + ArrayList errorList = new ArrayList(3); + if (exception instanceof FlutterError) { + FlutterError error = (FlutterError) exception; + errorList.add(error.code); + errorList.add(error.getMessage()); + errorList.add(error.details); + } else { + errorList.add(exception.toString()); + errorList.add(exception.getClass().getSimpleName()); + errorList.add( + "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); + } + return errorList; + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class NativeUserContextData { + private @Nullable String deviceName; + + public @Nullable String getDeviceName() { + return deviceName; + } + + public void setDeviceName(@Nullable String setterArg) { + this.deviceName = setterArg; + } + + private @Nullable String thirdPartyDeviceId; + + public @Nullable String getThirdPartyDeviceId() { + return thirdPartyDeviceId; + } + + public void setThirdPartyDeviceId(@Nullable String setterArg) { + this.thirdPartyDeviceId = setterArg; + } + + private @Nullable String deviceFingerprint; + + public @Nullable String getDeviceFingerprint() { + return deviceFingerprint; + } + + public void setDeviceFingerprint(@Nullable String setterArg) { + this.deviceFingerprint = setterArg; + } + + private @Nullable String applicationName; + + public @Nullable String getApplicationName() { + return applicationName; + } + + public void setApplicationName(@Nullable String setterArg) { + this.applicationName = setterArg; + } + + private @Nullable String applicationVersion; + + public @Nullable String getApplicationVersion() { + return applicationVersion; + } + + public void setApplicationVersion(@Nullable String setterArg) { + this.applicationVersion = setterArg; + } + + private @Nullable String deviceLanguage; + + public @Nullable String getDeviceLanguage() { + return deviceLanguage; + } + + public void setDeviceLanguage(@Nullable String setterArg) { + this.deviceLanguage = setterArg; + } + + private @Nullable String deviceOsReleaseVersion; + + public @Nullable String getDeviceOsReleaseVersion() { + return deviceOsReleaseVersion; + } + + public void setDeviceOsReleaseVersion(@Nullable String setterArg) { + this.deviceOsReleaseVersion = setterArg; + } + + private @Nullable Long screenHeightPixels; + + public @Nullable Long getScreenHeightPixels() { + return screenHeightPixels; + } + + public void setScreenHeightPixels(@Nullable Long setterArg) { + this.screenHeightPixels = setterArg; + } + + private @Nullable Long screenWidthPixels; + + public @Nullable Long getScreenWidthPixels() { + return screenWidthPixels; + } + + public void setScreenWidthPixels(@Nullable Long setterArg) { + this.screenWidthPixels = setterArg; + } + + public static final class Builder { + + private @Nullable String deviceName; + + public @NonNull Builder setDeviceName(@Nullable String setterArg) { + this.deviceName = setterArg; + return this; + } + + private @Nullable String thirdPartyDeviceId; + + public @NonNull Builder setThirdPartyDeviceId(@Nullable String setterArg) { + this.thirdPartyDeviceId = setterArg; + return this; + } + + private @Nullable String deviceFingerprint; + + public @NonNull Builder setDeviceFingerprint(@Nullable String setterArg) { + this.deviceFingerprint = setterArg; + return this; + } + + private @Nullable String applicationName; + + public @NonNull Builder setApplicationName(@Nullable String setterArg) { + this.applicationName = setterArg; + return this; + } + + private @Nullable String applicationVersion; + + public @NonNull Builder setApplicationVersion(@Nullable String setterArg) { + this.applicationVersion = setterArg; + return this; + } + + private @Nullable String deviceLanguage; + + public @NonNull Builder setDeviceLanguage(@Nullable String setterArg) { + this.deviceLanguage = setterArg; + return this; + } + + private @Nullable String deviceOsReleaseVersion; + + public @NonNull Builder setDeviceOsReleaseVersion(@Nullable String setterArg) { + this.deviceOsReleaseVersion = setterArg; + return this; + } + + private @Nullable Long screenHeightPixels; + + public @NonNull Builder setScreenHeightPixels(@Nullable Long setterArg) { + this.screenHeightPixels = setterArg; + return this; + } + + private @Nullable Long screenWidthPixels; + + public @NonNull Builder setScreenWidthPixels(@Nullable Long setterArg) { + this.screenWidthPixels = setterArg; + return this; + } + + public @NonNull NativeUserContextData build() { + NativeUserContextData pigeonReturn = new NativeUserContextData(); + pigeonReturn.setDeviceName(deviceName); + pigeonReturn.setThirdPartyDeviceId(thirdPartyDeviceId); + pigeonReturn.setDeviceFingerprint(deviceFingerprint); + pigeonReturn.setApplicationName(applicationName); + pigeonReturn.setApplicationVersion(applicationVersion); + pigeonReturn.setDeviceLanguage(deviceLanguage); + pigeonReturn.setDeviceOsReleaseVersion(deviceOsReleaseVersion); + pigeonReturn.setScreenHeightPixels(screenHeightPixels); + pigeonReturn.setScreenWidthPixels(screenWidthPixels); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(9); + toListResult.add(deviceName); + toListResult.add(thirdPartyDeviceId); + toListResult.add(deviceFingerprint); + toListResult.add(applicationName); + toListResult.add(applicationVersion); + toListResult.add(deviceLanguage); + toListResult.add(deviceOsReleaseVersion); + toListResult.add(screenHeightPixels); + toListResult.add(screenWidthPixels); + return toListResult; + } + + static @NonNull NativeUserContextData fromList(@NonNull ArrayList list) { + NativeUserContextData pigeonResult = new NativeUserContextData(); + Object deviceName = list.get(0); + pigeonResult.setDeviceName((String) deviceName); + Object thirdPartyDeviceId = list.get(1); + pigeonResult.setThirdPartyDeviceId((String) thirdPartyDeviceId); + Object deviceFingerprint = list.get(2); + pigeonResult.setDeviceFingerprint((String) deviceFingerprint); + Object applicationName = list.get(3); + pigeonResult.setApplicationName((String) applicationName); + Object applicationVersion = list.get(4); + pigeonResult.setApplicationVersion((String) applicationVersion); + Object deviceLanguage = list.get(5); + pigeonResult.setDeviceLanguage((String) deviceLanguage); + Object deviceOsReleaseVersion = list.get(6); + pigeonResult.setDeviceOsReleaseVersion((String) deviceOsReleaseVersion); + Object screenHeightPixels = list.get(7); + pigeonResult.setScreenHeightPixels((screenHeightPixels == null) ? null : ((screenHeightPixels instanceof Integer) ? (Integer) screenHeightPixels : (Long) screenHeightPixels)); + Object screenWidthPixels = list.get(8); + pigeonResult.setScreenWidthPixels((screenWidthPixels == null) ? null : ((screenWidthPixels instanceof Integer) ? (Integer) screenWidthPixels : (Long) screenWidthPixels)); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class LegacyCredentialStoreData { + private @Nullable String identityId; + + public @Nullable String getIdentityId() { + return identityId; + } + + public void setIdentityId(@Nullable String setterArg) { + this.identityId = setterArg; + } + + private @Nullable String accessKeyId; + + public @Nullable String getAccessKeyId() { + return accessKeyId; + } + + public void setAccessKeyId(@Nullable String setterArg) { + this.accessKeyId = setterArg; + } + + private @Nullable String secretAccessKey; + + public @Nullable String getSecretAccessKey() { + return secretAccessKey; + } + + public void setSecretAccessKey(@Nullable String setterArg) { + this.secretAccessKey = setterArg; + } + + private @Nullable String sessionToken; + + public @Nullable String getSessionToken() { + return sessionToken; + } + + public void setSessionToken(@Nullable String setterArg) { + this.sessionToken = setterArg; + } + + private @Nullable Long expirationMsSinceEpoch; + + public @Nullable Long getExpirationMsSinceEpoch() { + return expirationMsSinceEpoch; + } + + public void setExpirationMsSinceEpoch(@Nullable Long setterArg) { + this.expirationMsSinceEpoch = setterArg; + } + + private @Nullable String accessToken; + + public @Nullable String getAccessToken() { + return accessToken; + } + + public void setAccessToken(@Nullable String setterArg) { + this.accessToken = setterArg; + } + + private @Nullable String refreshToken; + + public @Nullable String getRefreshToken() { + return refreshToken; + } + + public void setRefreshToken(@Nullable String setterArg) { + this.refreshToken = setterArg; + } + + private @Nullable String idToken; + + public @Nullable String getIdToken() { + return idToken; + } + + public void setIdToken(@Nullable String setterArg) { + this.idToken = setterArg; + } + + public static final class Builder { + + private @Nullable String identityId; + + public @NonNull Builder setIdentityId(@Nullable String setterArg) { + this.identityId = setterArg; + return this; + } + + private @Nullable String accessKeyId; + + public @NonNull Builder setAccessKeyId(@Nullable String setterArg) { + this.accessKeyId = setterArg; + return this; + } + + private @Nullable String secretAccessKey; + + public @NonNull Builder setSecretAccessKey(@Nullable String setterArg) { + this.secretAccessKey = setterArg; + return this; + } + + private @Nullable String sessionToken; + + public @NonNull Builder setSessionToken(@Nullable String setterArg) { + this.sessionToken = setterArg; + return this; + } + + private @Nullable Long expirationMsSinceEpoch; + + public @NonNull Builder setExpirationMsSinceEpoch(@Nullable Long setterArg) { + this.expirationMsSinceEpoch = setterArg; + return this; + } + + private @Nullable String accessToken; + + public @NonNull Builder setAccessToken(@Nullable String setterArg) { + this.accessToken = setterArg; + return this; + } + + private @Nullable String refreshToken; + + public @NonNull Builder setRefreshToken(@Nullable String setterArg) { + this.refreshToken = setterArg; + return this; + } + + private @Nullable String idToken; + + public @NonNull Builder setIdToken(@Nullable String setterArg) { + this.idToken = setterArg; + return this; + } + + public @NonNull LegacyCredentialStoreData build() { + LegacyCredentialStoreData pigeonReturn = new LegacyCredentialStoreData(); + pigeonReturn.setIdentityId(identityId); + pigeonReturn.setAccessKeyId(accessKeyId); + pigeonReturn.setSecretAccessKey(secretAccessKey); + pigeonReturn.setSessionToken(sessionToken); + pigeonReturn.setExpirationMsSinceEpoch(expirationMsSinceEpoch); + pigeonReturn.setAccessToken(accessToken); + pigeonReturn.setRefreshToken(refreshToken); + pigeonReturn.setIdToken(idToken); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(8); + toListResult.add(identityId); + toListResult.add(accessKeyId); + toListResult.add(secretAccessKey); + toListResult.add(sessionToken); + toListResult.add(expirationMsSinceEpoch); + toListResult.add(accessToken); + toListResult.add(refreshToken); + toListResult.add(idToken); + return toListResult; + } + + static @NonNull LegacyCredentialStoreData fromList(@NonNull ArrayList list) { + LegacyCredentialStoreData pigeonResult = new LegacyCredentialStoreData(); + Object identityId = list.get(0); + pigeonResult.setIdentityId((String) identityId); + Object accessKeyId = list.get(1); + pigeonResult.setAccessKeyId((String) accessKeyId); + Object secretAccessKey = list.get(2); + pigeonResult.setSecretAccessKey((String) secretAccessKey); + Object sessionToken = list.get(3); + pigeonResult.setSessionToken((String) sessionToken); + Object expirationMsSinceEpoch = list.get(4); + pigeonResult.setExpirationMsSinceEpoch((expirationMsSinceEpoch == null) ? null : ((expirationMsSinceEpoch instanceof Integer) ? (Integer) expirationMsSinceEpoch : (Long) expirationMsSinceEpoch)); + Object accessToken = list.get(5); + pigeonResult.setAccessToken((String) accessToken); + Object refreshToken = list.get(6); + pigeonResult.setRefreshToken((String) refreshToken); + Object idToken = list.get(7); + pigeonResult.setIdToken((String) idToken); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class LegacyDeviceDetailsSecret { + private @Nullable String deviceKey; + + public @Nullable String getDeviceKey() { + return deviceKey; + } + + public void setDeviceKey(@Nullable String setterArg) { + this.deviceKey = setterArg; + } + + private @Nullable String deviceGroupKey; + + public @Nullable String getDeviceGroupKey() { + return deviceGroupKey; + } + + public void setDeviceGroupKey(@Nullable String setterArg) { + this.deviceGroupKey = setterArg; + } + + private @Nullable String devicePassword; + + public @Nullable String getDevicePassword() { + return devicePassword; + } + + public void setDevicePassword(@Nullable String setterArg) { + this.devicePassword = setterArg; + } + + private @Nullable String asfDeviceId; + + public @Nullable String getAsfDeviceId() { + return asfDeviceId; + } + + public void setAsfDeviceId(@Nullable String setterArg) { + this.asfDeviceId = setterArg; + } + + public static final class Builder { + + private @Nullable String deviceKey; + + public @NonNull Builder setDeviceKey(@Nullable String setterArg) { + this.deviceKey = setterArg; + return this; + } + + private @Nullable String deviceGroupKey; + + public @NonNull Builder setDeviceGroupKey(@Nullable String setterArg) { + this.deviceGroupKey = setterArg; + return this; + } + + private @Nullable String devicePassword; + + public @NonNull Builder setDevicePassword(@Nullable String setterArg) { + this.devicePassword = setterArg; + return this; + } + + private @Nullable String asfDeviceId; + + public @NonNull Builder setAsfDeviceId(@Nullable String setterArg) { + this.asfDeviceId = setterArg; + return this; + } + + public @NonNull LegacyDeviceDetailsSecret build() { + LegacyDeviceDetailsSecret pigeonReturn = new LegacyDeviceDetailsSecret(); + pigeonReturn.setDeviceKey(deviceKey); + pigeonReturn.setDeviceGroupKey(deviceGroupKey); + pigeonReturn.setDevicePassword(devicePassword); + pigeonReturn.setAsfDeviceId(asfDeviceId); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(4); + toListResult.add(deviceKey); + toListResult.add(deviceGroupKey); + toListResult.add(devicePassword); + toListResult.add(asfDeviceId); + return toListResult; + } + + static @NonNull LegacyDeviceDetailsSecret fromList(@NonNull ArrayList list) { + LegacyDeviceDetailsSecret pigeonResult = new LegacyDeviceDetailsSecret(); + Object deviceKey = list.get(0); + pigeonResult.setDeviceKey((String) deviceKey); + Object deviceGroupKey = list.get(1); + pigeonResult.setDeviceGroupKey((String) deviceGroupKey); + Object devicePassword = list.get(2); + pigeonResult.setDevicePassword((String) devicePassword); + Object asfDeviceId = list.get(3); + pigeonResult.setAsfDeviceId((String) asfDeviceId); + return pigeonResult; + } + } + + public interface Result { + @SuppressWarnings("UnknownNullness") + void success(T result); + + void error(@NonNull Throwable error); + } + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ + public static class NativeAuthPlugin { + private final @NonNull BinaryMessenger binaryMessenger; + + public NativeAuthPlugin(@NonNull BinaryMessenger argBinaryMessenger) { + this.binaryMessenger = argBinaryMessenger; + } + + /** Public interface for sending reply. */ + @SuppressWarnings("UnknownNullness") + public interface Reply { + void reply(T reply); + } + /** The codec used by NativeAuthPlugin. */ + static @NonNull MessageCodec getCodec() { + return new StandardMessageCodec(); + } + /** + * Exchanges the route parameters used to launch the app, i.e. if the app + * was closed and a redirect happened to the custom URI scheme (iOS) or an + * intent was launched with the redirect parameters (Android). + */ + public void exchange(@NonNull Map paramsArg, @NonNull Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthPlugin.exchange", getCodec()); + channel.send( + new ArrayList(Collections.singletonList(paramsArg)), + channelReply -> callback.reply(null)); + } + } + + private static class NativeAuthBridgeCodec extends StandardMessageCodec { + public static final NativeAuthBridgeCodec INSTANCE = new NativeAuthBridgeCodec(); + + private NativeAuthBridgeCodec() {} + + @Override + protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { + switch (type) { + case (byte) 128: + return LegacyCredentialStoreData.fromList((ArrayList) readValue(buffer)); + case (byte) 129: + return LegacyDeviceDetailsSecret.fromList((ArrayList) readValue(buffer)); + case (byte) 130: + return NativeUserContextData.fromList((ArrayList) readValue(buffer)); + default: + return super.readValueOfType(type, buffer); + } + } + + @Override + protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { + if (value instanceof LegacyCredentialStoreData) { + stream.write(128); + writeValue(stream, ((LegacyCredentialStoreData) value).toList()); + } else if (value instanceof LegacyDeviceDetailsSecret) { + stream.write(129); + writeValue(stream, ((LegacyDeviceDetailsSecret) value).toList()); + } else if (value instanceof NativeUserContextData) { + stream.write(130); + writeValue(stream, ((NativeUserContextData) value).toList()); + } else { + super.writeValue(stream, value); + } + } + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface NativeAuthBridge { + /** + * Sign in by presenting [url] and waiting for a response to a URL with + * [callbackUrlScheme]. + * + * If [preferPrivateSession] is `true`, do not persist session cookies. + */ + void signInWithUrl(@NonNull String url, @NonNull String callbackUrlScheme, @NonNull Boolean preferPrivateSession, @Nullable String browserPackageName, @NonNull Result> result); + /** + * Sign out by presenting [url] and waiting for a response to a URL with + * [callbackUrlScheme]. + */ + void signOutWithUrl(@NonNull String url, @NonNull String callbackUrlScheme, @NonNull Boolean preferPrivateSession, @Nullable String browserPackageName, @NonNull Result result); + /** Retrieves the validation data for the current iOS/Android device. */ + @NonNull + Map getValidationData(); + /** Retrieves context data as required for advanced security features (ASF). */ + @NonNull + NativeUserContextData getContextData(); + + @NonNull + String getBundleId(); + /** Fetch legacy credentials stored by native SDKs. */ + void getLegacyCredentials(@Nullable String identityPoolId, @Nullable String appClientId, @NonNull Result result); + /** Clears the legacy credential store data. */ + void clearLegacyCredentials(@NonNull Result result); + /** Fetch legacy device secrets stored by native SDKs. */ + void fetchLegacyDeviceSecrets(@Nullable String userPoolId, @Nullable String appClientId, @NonNull Result result); + /** Clears the legacy device secrets. */ + void deleteLegacyDeviceSecrets(@Nullable String userPoolId, @Nullable String appClientId, @NonNull Result result); + + /** The codec used by NativeAuthBridge. */ + static @NonNull MessageCodec getCodec() { + return NativeAuthBridgeCodec.INSTANCE; + } + /**Sets up an instance of `NativeAuthBridge` to handle messages through the `binaryMessenger`. */ + static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable NativeAuthBridge api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.signInWithUrl", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + String urlArg = (String) args.get(0); + String callbackUrlSchemeArg = (String) args.get(1); + Boolean preferPrivateSessionArg = (Boolean) args.get(2); + String browserPackageNameArg = (String) args.get(3); + Result> resultCallback = + new Result>() { + public void success(Map result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.signInWithUrl(urlArg, callbackUrlSchemeArg, preferPrivateSessionArg, browserPackageNameArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.signOutWithUrl", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + String urlArg = (String) args.get(0); + String callbackUrlSchemeArg = (String) args.get(1); + Boolean preferPrivateSessionArg = (Boolean) args.get(2); + String browserPackageNameArg = (String) args.get(3); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.signOutWithUrl(urlArg, callbackUrlSchemeArg, preferPrivateSessionArg, browserPackageNameArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.getValidationData", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Map output = api.getValidationData(); + wrapped.add(0, output); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.getContextData", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + NativeUserContextData output = api.getContextData(); + wrapped.add(0, output); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.getBundleId", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + String output = api.getBundleId(); + wrapped.add(0, output); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.getLegacyCredentials", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + String identityPoolIdArg = (String) args.get(0); + String appClientIdArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(LegacyCredentialStoreData result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.getLegacyCredentials(identityPoolIdArg, appClientIdArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.clearLegacyCredentials", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.clearLegacyCredentials(resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.fetchLegacyDeviceSecrets", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + String userPoolIdArg = (String) args.get(0); + String appClientIdArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(LegacyDeviceDetailsSecret result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.fetchLegacyDeviceSecrets(userPoolIdArg, appClientIdArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.deleteLegacyDeviceSecrets", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + String userPoolIdArg = (String) args.get(0); + String appClientIdArg = (String) args.get(1); + Result resultCallback = + new Result() { + public void success(Void result) { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.deleteLegacyDeviceSecrets(userPoolIdArg, appClientIdArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } +} diff --git a/packages/auth/amplify_auth_cognito/android/src/main/kotlin/com/amazonaws/amplify/amplify_auth_cognito/AmplifyAuthCognitoPlugin.kt b/packages/auth/amplify_auth_cognito/android/src/main/kotlin/com/amazonaws/amplify/amplify_auth_cognito/AmplifyAuthCognitoPlugin.kt index 1cb2cfe6cf..38aaf66bf8 100644 --- a/packages/auth/amplify_auth_cognito/android/src/main/kotlin/com/amazonaws/amplify/amplify_auth_cognito/AmplifyAuthCognitoPlugin.kt +++ b/packages/auth/amplify_auth_cognito/android/src/main/kotlin/com/amazonaws/amplify/amplify_auth_cognito/AmplifyAuthCognitoPlugin.kt @@ -103,6 +103,16 @@ open class AmplifyAuthCognitoPlugin : ) } + /** + ASF Device Secrets Storage. + */ + private val asfDeviceSecretsStore: LegacyKeyValueStore by lazy { + LegacyKeyValueStore( + applicationContext!!, + "AWS.Cognito.ContextData" + ) + } + override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { Log.d(TAG, "onAttachedToEngine") applicationContext = binding.applicationContext @@ -241,7 +251,7 @@ open class AmplifyAuthCognitoPlugin : * - https://github.com/aws-amplify/aws-sdk-android/blob/main/aws-android-sdk-cognitoauth/src/main/java/com/amazonaws/mobileconnectors/cognitoauth/util/ClientConstants.java */ override fun getLegacyCredentials(identityPoolId: String?, appClientId: String?, callback: (Result) -> Unit) { - val data = LegacyCredentialStoreData.builder() + val data = LegacyCredentialStoreDataBuilder() if (appClientId != null) { val lastAuthUser = legacyUserPoolStore["CognitoIdentityProvider.$appClientId.LastAuthUser"] @@ -273,6 +283,64 @@ open class AmplifyAuthCognitoPlugin : callback(Result.success(data.build())) } + /** + * Get Legacy Device Secrets + */ + override fun fetchLegacyDeviceSecrets( + userPoolId: String?, + appClientId: String?, + callback: (Result) -> Unit + ) { + val data = LegacyDeviceDetailsBuilder() + + if (appClientId != null) { + val lastAuthUser = legacyUserPoolStore["CognitoIdentityProvider.$appClientId.LastAuthUser"] + + val newLegacyDeviceSecretsStore = LegacyKeyValueStore( + applicationContext!!, + "CognitoIdentityProviderDeviceCache.$userPoolId.$lastAuthUser" + ) + + val deviceKey = newLegacyDeviceSecretsStore["DeviceKey"] + val deviceSecret = newLegacyDeviceSecretsStore["DeviceSecret"] + val deviceGroup = newLegacyDeviceSecretsStore["DeviceGroupKey"] + + data.apply { + this.deviceKey = deviceKey + this.deviceSecret = deviceSecret + this.deviceGroupKey = deviceGroup + } + + } + + val asfDeviceId = asfDeviceSecretsStore["CognitoDeviceId"] + data.apply { + this.asfDeviceId = asfDeviceId + } + + callback(Result.success(data.build())) + } + + /** + * Delete Legacy Device Secrets + */ + override fun deleteLegacyDeviceSecrets(userPoolId: String?, appClientId: String?, callback: (Result) -> Unit) { + if (appClientId != null) { + val lastAuthUser = legacyUserPoolStore["CognitoIdentityProvider.$appClientId.LastAuthUser"] + + val legacyDeviceSecretsStore = LegacyKeyValueStore( + applicationContext!!, + "CognitoIdentityProviderDeviceCache.$userPoolId.$lastAuthUser" + ) + + legacyDeviceSecretsStore.clear() + } + + asfDeviceSecretsStore.clear() + + callback(Result.success(Unit)) + } + /** * Clears the legacy credentials set by the Android SDK */ @@ -572,3 +640,19 @@ class LegacyCredentialStoreDataBuilder( idToken, ) } + +fun LegacyDeviceDetailsSecret.Companion.builder() = LegacyDeviceDetailsBuilder() + +class LegacyDeviceDetailsBuilder( + var deviceKey: String? = null, + var deviceSecret: String? = null, + var deviceGroupKey: String? = null, + var asfDeviceId: String? = null, +) { + fun build(): LegacyDeviceDetailsSecret = LegacyDeviceDetailsSecret( + deviceKey, + deviceSecret, + deviceGroupKey, + asfDeviceId, + ) +} diff --git a/packages/auth/amplify_auth_cognito/android/src/main/kotlin/com/amazonaws/amplify/amplify_auth_cognito/LegacySecretHandler.txt b/packages/auth/amplify_auth_cognito/android/src/main/kotlin/com/amazonaws/amplify/amplify_auth_cognito/LegacySecretHandler.txt new file mode 100644 index 0000000000..8ba1fa7c06 --- /dev/null +++ b/packages/auth/amplify_auth_cognito/android/src/main/kotlin/com/amazonaws/amplify/amplify_auth_cognito/LegacySecretHandler.txt @@ -0,0 +1,26 @@ +package com.amazonaws.amplify.amplify_auth_cognito + +import android.content.Context +import io.flutter.plugin.common.PluginRegistry + +class LegacySecretHandlerImpl(private val context: Context) : LegacySecretHandler, MethodChannel.MethodCallHandler { + + private val channel = MethodChannel(registrar.messenger(), "com.amazonaws.amplify/amplify_auth_cognito") + + fun fetchLegacyDeviceSecrets(userPoolConfig: CognitoUserPoolConfig?): LegacyDeviceDetails?{ + return null + } + + fun deleteLegacyDeviceSecrets(userPoolConfig: CognitoUserPoolConfig?) { + channel.invokeMethod("deleteLegacyDeviceSecrets", userPoolConfig?.poolId) + } + + fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + if (call.method == "getDeviceId") { + result.success(getDeviceId()) + } else { + result.notImplemented() + } + } + +} diff --git a/packages/auth/amplify_auth_cognito/android/src/main/kotlin/com/amazonaws/amplify/amplify_auth_cognito/pigeons/NativeAuthPluginBindingsPigeon.kt b/packages/auth/amplify_auth_cognito/android/src/main/kotlin/com/amazonaws/amplify/amplify_auth_cognito/pigeons/NativeAuthPluginBindingsPigeon.kt index f76163165a..ec11d841f6 100644 --- a/packages/auth/amplify_auth_cognito/android/src/main/kotlin/com/amazonaws/amplify/amplify_auth_cognito/pigeons/NativeAuthPluginBindingsPigeon.kt +++ b/packages/auth/amplify_auth_cognito/android/src/main/kotlin/com/amazonaws/amplify/amplify_auth_cognito/pigeons/NativeAuthPluginBindingsPigeon.kt @@ -1,7 +1,7 @@ // // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Autogenerated from Pigeon (v11.0.0), do not edit directly. +// Autogenerated from Pigeon (v11.0.1), do not edit directly. // See also: https://pub.dev/packages/pigeon package com.amazonaws.amplify.amplify_auth_cognito @@ -129,6 +129,34 @@ data class LegacyCredentialStoreData ( } } +/** Generated class from Pigeon that represents data sent in messages. */ +data class LegacyDeviceDetailsSecret ( + val deviceKey: String? = null, + val deviceGroupKey: String? = null, + val devicePassword: String? = null, + val asfDeviceId: String? = null + +) { + companion object { + @Suppress("UNCHECKED_CAST") + fun fromList(list: List): LegacyDeviceDetailsSecret { + val deviceKey = list[0] as String? + val deviceGroupKey = list[1] as String? + val devicePassword = list[2] as String? + val asfDeviceId = list[3] as String? + return LegacyDeviceDetailsSecret(deviceKey, deviceGroupKey, devicePassword, asfDeviceId) + } + } + fun toList(): List { + return listOf( + deviceKey, + deviceGroupKey, + devicePassword, + asfDeviceId, + ) + } +} + /** Generated class from Pigeon that represents Flutter messages that can be called from Kotlin. */ @Suppress("UNCHECKED_CAST") class NativeAuthPlugin(private val binaryMessenger: BinaryMessenger) { @@ -160,6 +188,11 @@ private object NativeAuthBridgeCodec : StandardMessageCodec() { } } 129.toByte() -> { + return (readValue(buffer) as? List)?.let { + LegacyDeviceDetailsSecret.fromList(it) + } + } + 130.toByte() -> { return (readValue(buffer) as? List)?.let { NativeUserContextData.fromList(it) } @@ -173,10 +206,14 @@ private object NativeAuthBridgeCodec : StandardMessageCodec() { stream.write(128) writeValue(stream, value.toList()) } - is NativeUserContextData -> { + is LegacyDeviceDetailsSecret -> { stream.write(129) writeValue(stream, value.toList()) } + is NativeUserContextData -> { + stream.write(130) + writeValue(stream, value.toList()) + } else -> super.writeValue(stream, value) } } @@ -205,6 +242,10 @@ interface NativeAuthBridge { fun getLegacyCredentials(identityPoolId: String?, appClientId: String?, callback: (Result) -> Unit) /** Clears the legacy credential store data. */ fun clearLegacyCredentials(callback: (Result) -> Unit) + /** Fetch legacy device secrets stored by native SDKs. */ + fun fetchLegacyDeviceSecrets(userPoolId: String?, appClientId: String?, callback: (Result) -> Unit) + /** Clears the legacy device secrets. */ + fun deleteLegacyDeviceSecrets(userPoolId: String?, appClientId: String?, callback: (Result) -> Unit) companion object { /** The codec used by NativeAuthBridge. */ @@ -345,6 +386,47 @@ interface NativeAuthBridge { channel.setMessageHandler(null) } } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.fetchLegacyDeviceSecrets", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val userPoolIdArg = args[0] as String? + val appClientIdArg = args[1] as String? + api.fetchLegacyDeviceSecrets(userPoolIdArg, appClientIdArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.deleteLegacyDeviceSecrets", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val userPoolIdArg = args[0] as String? + val appClientIdArg = args[1] as String? + api.deleteLegacyDeviceSecrets(userPoolIdArg, appClientIdArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + reply.reply(wrapResult(null)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } } } } diff --git a/packages/auth/amplify_auth_cognito/darwin/Classes/AmplifyAuthCognitoPlugin.swift b/packages/auth/amplify_auth_cognito/darwin/Classes/AmplifyAuthCognitoPlugin.swift index 6b174cd4d0..c37a6d04eb 100644 --- a/packages/auth/amplify_auth_cognito/darwin/Classes/AmplifyAuthCognitoPlugin.swift +++ b/packages/auth/amplify_auth_cognito/darwin/Classes/AmplifyAuthCognitoPlugin.swift @@ -171,5 +171,35 @@ public class AmplifyAuthCognitoPlugin: NSObject, FlutterPlugin, NativeAuthBridge func clearLegacyCredentials(completion: @escaping (Result) -> Void) { preconditionFailure("clearing legacy credentials via method channel is not supported in iOS/macOS") } + + func fetchLegacyDeviceSecrets(userPoolId: String?, appClientId: String?, completion: @escaping (Result) -> Void) { + guard let appClientId = appClientId else { + completion(.failure(FlutterError(code: "AmplifyException", message: "appClientId is required", details: nil))) + return + } + + let userDefaults = UserDefaults.standard + let deviceSecrets = LegacyDeviceDetailsSecret( + deviceKey: userDefaults.string(forKey: "\(appClientId).deviceKey"), + deviceGroupKey: userDefaults.string(forKey: "\(appClientId).deviceGroupKey"), + devicePassword: userDefaults.string(forKey: "\(appClientId).devicePasswrd"), + asfDeviceId: userDefaults.string(forKey: "\(appClientId).asfDeviceId") + ) + completion(.success(deviceSecrets)) + } + + func deleteLegacyDeviceSecrets(userPoolId: String?, appClientId: String?, completion: @escaping (Result) -> Void) { + guard let appClientId = appClientId else { + completion(.failure(FlutterError(code: "AmplifyException", message: "appClientId is required", details: nil))) + return + } + + let userDefaults = UserDefaults.standard + userDefaults.removeObject(forKey: "\(appClientId).deviceGroupKey") + userDefaults.removeObject(forKey: "\(appClientId).deviceKey") + userDefaults.removeObject(forKey: "\(appClientId).devicePassword") + userDefaults.removeObject(forKey: "\(appClientId).asfDeviceId") + completion(.success(())) + } } diff --git a/packages/auth/amplify_auth_cognito/darwin/Classes/pigeons/messages.g.swift b/packages/auth/amplify_auth_cognito/darwin/Classes/pigeons/messages.g.swift index 0ce21750f6..b13f47a4b6 100644 --- a/packages/auth/amplify_auth_cognito/darwin/Classes/pigeons/messages.g.swift +++ b/packages/auth/amplify_auth_cognito/darwin/Classes/pigeons/messages.g.swift @@ -1,7 +1,7 @@ // // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Autogenerated from Pigeon (v11.0.0), do not edit directly. +// Autogenerated from Pigeon (v11.0.1), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -137,6 +137,36 @@ struct LegacyCredentialStoreData { } } +/// Generated class from Pigeon that represents data sent in messages. +struct LegacyDeviceDetailsSecret { + var deviceKey: String? = nil + var deviceGroupKey: String? = nil + var devicePassword: String? = nil + var asfDeviceId: String? = nil + + static func fromList(_ list: [Any?]) -> LegacyDeviceDetailsSecret? { + let deviceKey: String? = nilOrValue(list[0]) + let deviceGroupKey: String? = nilOrValue(list[1]) + let devicePassword: String? = nilOrValue(list[2]) + let asfDeviceId: String? = nilOrValue(list[3]) + + return LegacyDeviceDetailsSecret( + deviceKey: deviceKey, + deviceGroupKey: deviceGroupKey, + devicePassword: devicePassword, + asfDeviceId: asfDeviceId + ) + } + func toList() -> [Any?] { + return [ + deviceKey, + deviceGroupKey, + devicePassword, + asfDeviceId, + ] + } +} + /// Generated class from Pigeon that represents Flutter messages that can be called from Swift. class NativeAuthPlugin { private let binaryMessenger: FlutterBinaryMessenger @@ -159,6 +189,8 @@ private class NativeAuthBridgeCodecReader: FlutterStandardReader { case 128: return LegacyCredentialStoreData.fromList(self.readValue() as! [Any?]) case 129: + return LegacyDeviceDetailsSecret.fromList(self.readValue() as! [Any?]) + case 130: return NativeUserContextData.fromList(self.readValue() as! [Any?]) default: return super.readValue(ofType: type) @@ -171,9 +203,12 @@ private class NativeAuthBridgeCodecWriter: FlutterStandardWriter { if let value = value as? LegacyCredentialStoreData { super.writeByte(128) super.writeValue(value.toList()) - } else if let value = value as? NativeUserContextData { + } else if let value = value as? LegacyDeviceDetailsSecret { super.writeByte(129) super.writeValue(value.toList()) + } else if let value = value as? NativeUserContextData { + super.writeByte(130) + super.writeValue(value.toList()) } else { super.writeValue(value) } @@ -213,6 +248,10 @@ protocol NativeAuthBridge { func getLegacyCredentials(identityPoolId: String?, appClientId: String?, completion: @escaping (Result) -> Void) /// Clears the legacy credential store data. func clearLegacyCredentials(completion: @escaping (Result) -> Void) + /// Fetch legacy device secrets stored by native SDKs. + func fetchLegacyDeviceSecrets(userPoolId: String?, appClientId: String?, completion: @escaping (Result) -> Void) + /// Clears the legacy device secrets. + func deleteLegacyDeviceSecrets(userPoolId: String?, appClientId: String?, completion: @escaping (Result) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -343,5 +382,43 @@ class NativeAuthBridgeSetup { } else { clearLegacyCredentialsChannel.setMessageHandler(nil) } + /// Fetch legacy device secrets stored by native SDKs. + let fetchLegacyDeviceSecretsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.fetchLegacyDeviceSecrets", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fetchLegacyDeviceSecretsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let userPoolIdArg: String? = nilOrValue(args[0]) + let appClientIdArg: String? = nilOrValue(args[1]) + api.fetchLegacyDeviceSecrets(userPoolId: userPoolIdArg, appClientId: appClientIdArg) { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + fetchLegacyDeviceSecretsChannel.setMessageHandler(nil) + } + /// Clears the legacy device secrets. + let deleteLegacyDeviceSecretsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.deleteLegacyDeviceSecrets", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + deleteLegacyDeviceSecretsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let userPoolIdArg: String? = nilOrValue(args[0]) + let appClientIdArg: String? = nilOrValue(args[1]) + api.deleteLegacyDeviceSecrets(userPoolId: userPoolIdArg, appClientId: appClientIdArg) { result in + switch result { + case .success: + reply(wrapResult(nil)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + deleteLegacyDeviceSecretsChannel.setMessageHandler(nil) + } } } diff --git a/packages/auth/amplify_auth_cognito/ios/Runner/native_auth_plugin.h b/packages/auth/amplify_auth_cognito/ios/Runner/native_auth_plugin.h new file mode 100644 index 0000000000..4b10894d40 --- /dev/null +++ b/packages/auth/amplify_auth_cognito/ios/Runner/native_auth_plugin.h @@ -0,0 +1,116 @@ +// +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#import + +@protocol FlutterBinaryMessenger; +@protocol FlutterMessageCodec; +@class FlutterError; +@class FlutterStandardTypedData; + +NS_ASSUME_NONNULL_BEGIN + +@class NativeUserContextData; +@class LegacyCredentialStoreData; +@class LegacyDeviceDetailsSecret; + +@interface NativeUserContextData : NSObject ++ (instancetype)makeWithDeviceName:(nullable NSString *)deviceName + thirdPartyDeviceId:(nullable NSString *)thirdPartyDeviceId + deviceFingerprint:(nullable NSString *)deviceFingerprint + applicationName:(nullable NSString *)applicationName + applicationVersion:(nullable NSString *)applicationVersion + deviceLanguage:(nullable NSString *)deviceLanguage + deviceOsReleaseVersion:(nullable NSString *)deviceOsReleaseVersion + screenHeightPixels:(nullable NSNumber *)screenHeightPixels + screenWidthPixels:(nullable NSNumber *)screenWidthPixels; +@property(nonatomic, copy, nullable) NSString * deviceName; +@property(nonatomic, copy, nullable) NSString * thirdPartyDeviceId; +@property(nonatomic, copy, nullable) NSString * deviceFingerprint; +@property(nonatomic, copy, nullable) NSString * applicationName; +@property(nonatomic, copy, nullable) NSString * applicationVersion; +@property(nonatomic, copy, nullable) NSString * deviceLanguage; +@property(nonatomic, copy, nullable) NSString * deviceOsReleaseVersion; +@property(nonatomic, strong, nullable) NSNumber * screenHeightPixels; +@property(nonatomic, strong, nullable) NSNumber * screenWidthPixels; +@end + +@interface LegacyCredentialStoreData : NSObject ++ (instancetype)makeWithIdentityId:(nullable NSString *)identityId + accessKeyId:(nullable NSString *)accessKeyId + secretAccessKey:(nullable NSString *)secretAccessKey + sessionToken:(nullable NSString *)sessionToken + expirationMsSinceEpoch:(nullable NSNumber *)expirationMsSinceEpoch + accessToken:(nullable NSString *)accessToken + refreshToken:(nullable NSString *)refreshToken + idToken:(nullable NSString *)idToken; +@property(nonatomic, copy, nullable) NSString * identityId; +@property(nonatomic, copy, nullable) NSString * accessKeyId; +@property(nonatomic, copy, nullable) NSString * secretAccessKey; +@property(nonatomic, copy, nullable) NSString * sessionToken; +@property(nonatomic, strong, nullable) NSNumber * expirationMsSinceEpoch; +@property(nonatomic, copy, nullable) NSString * accessToken; +@property(nonatomic, copy, nullable) NSString * refreshToken; +@property(nonatomic, copy, nullable) NSString * idToken; +@end + +@interface LegacyDeviceDetailsSecret : NSObject ++ (instancetype)makeWithDeviceKey:(nullable NSString *)deviceKey + deviceGroupKey:(nullable NSString *)deviceGroupKey + devicePassword:(nullable NSString *)devicePassword + asfDeviceId:(nullable NSString *)asfDeviceId; +@property(nonatomic, copy, nullable) NSString * deviceKey; +@property(nonatomic, copy, nullable) NSString * deviceGroupKey; +@property(nonatomic, copy, nullable) NSString * devicePassword; +@property(nonatomic, copy, nullable) NSString * asfDeviceId; +@end + +/// The codec used by NativeAuthPlugin. +NSObject *NativeAuthPluginGetCodec(void); + +@interface NativeAuthPlugin : NSObject +- (instancetype)initWithBinaryMessenger:(id)binaryMessenger; +/// Exchanges the route parameters used to launch the app, i.e. if the app +/// was closed and a redirect happened to the custom URI scheme (iOS) or an +/// intent was launched with the redirect parameters (Android). +- (void)exchangeParams:(NSDictionary *)params completion:(void (^)(FlutterError *_Nullable))completion; +@end + +/// The codec used by NativeAuthBridge. +NSObject *NativeAuthBridgeGetCodec(void); + +@protocol NativeAuthBridge +/// Sign in by presenting [url] and waiting for a response to a URL with +/// [callbackUrlScheme]. +/// +/// If [preferPrivateSession] is `true`, do not persist session cookies. +- (void)signInWithUrlUrl:(NSString *)url callbackUrlScheme:(NSString *)callbackUrlScheme preferPrivateSession:(NSNumber *)preferPrivateSession browserPackageName:(nullable NSString *)browserPackageName completion:(void (^)(NSDictionary *_Nullable, FlutterError *_Nullable))completion; +/// Sign out by presenting [url] and waiting for a response to a URL with +/// [callbackUrlScheme]. +- (void)signOutWithUrlUrl:(NSString *)url callbackUrlScheme:(NSString *)callbackUrlScheme preferPrivateSession:(NSNumber *)preferPrivateSession browserPackageName:(nullable NSString *)browserPackageName completion:(void (^)(FlutterError *_Nullable))completion; +/// Retrieves the validation data for the current iOS/Android device. +/// +/// @return `nil` only when `error != nil`. +- (nullable NSDictionary *)getValidationDataWithError:(FlutterError *_Nullable *_Nonnull)error; +/// Retrieves context data as required for advanced security features (ASF). +/// +/// @return `nil` only when `error != nil`. +- (nullable NativeUserContextData *)getContextDataWithError:(FlutterError *_Nullable *_Nonnull)error; +/// @return `nil` only when `error != nil`. +- (nullable NSString *)getBundleIdWithError:(FlutterError *_Nullable *_Nonnull)error; +/// Fetch legacy credentials stored by native SDKs. +- (void)getLegacyCredentialsIdentityPoolId:(nullable NSString *)identityPoolId appClientId:(nullable NSString *)appClientId completion:(void (^)(LegacyCredentialStoreData *_Nullable, FlutterError *_Nullable))completion; +/// Clears the legacy credential store data. +- (void)clearLegacyCredentialsWithCompletion:(void (^)(FlutterError *_Nullable))completion; +/// Fetch legacy device secrets stored by native SDKs. +- (void)fetchLegacyDeviceSecretsUserPoolId:(nullable NSString *)userPoolId appClientId:(nullable NSString *)appClientId completion:(void (^)(LegacyDeviceDetailsSecret *_Nullable, FlutterError *_Nullable))completion; +/// Clears the legacy device secrets. +- (void)deleteLegacyDeviceSecretsUserPoolId:(nullable NSString *)userPoolId appClientId:(nullable NSString *)appClientId completion:(void (^)(FlutterError *_Nullable))completion; +@end + +extern void NativeAuthBridgeSetup(id binaryMessenger, NSObject *_Nullable api); + +NS_ASSUME_NONNULL_END diff --git a/packages/auth/amplify_auth_cognito/ios/Runner/native_auth_plugin.m b/packages/auth/amplify_auth_cognito/ios/Runner/native_auth_plugin.m new file mode 100644 index 0000000000..5ac8d05ab9 --- /dev/null +++ b/packages/auth/amplify_auth_cognito/ios/Runner/native_auth_plugin.m @@ -0,0 +1,458 @@ +// +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#import "native_auth_plugin.h" + +#if TARGET_OS_OSX +#import +#else +#import +#endif + +#if !__has_feature(objc_arc) +#error File requires ARC to be enabled. +#endif + +static NSArray *wrapResult(id result, FlutterError *error) { + if (error) { + return @[ + error.code ?: [NSNull null], error.message ?: [NSNull null], error.details ?: [NSNull null] + ]; + } + return @[ result ?: [NSNull null] ]; +} +static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { + id result = array[key]; + return (result == [NSNull null]) ? nil : result; +} + +@interface NativeUserContextData () ++ (NativeUserContextData *)fromList:(NSArray *)list; ++ (nullable NativeUserContextData *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface LegacyCredentialStoreData () ++ (LegacyCredentialStoreData *)fromList:(NSArray *)list; ++ (nullable LegacyCredentialStoreData *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface LegacyDeviceDetailsSecret () ++ (LegacyDeviceDetailsSecret *)fromList:(NSArray *)list; ++ (nullable LegacyDeviceDetailsSecret *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@implementation NativeUserContextData ++ (instancetype)makeWithDeviceName:(nullable NSString *)deviceName + thirdPartyDeviceId:(nullable NSString *)thirdPartyDeviceId + deviceFingerprint:(nullable NSString *)deviceFingerprint + applicationName:(nullable NSString *)applicationName + applicationVersion:(nullable NSString *)applicationVersion + deviceLanguage:(nullable NSString *)deviceLanguage + deviceOsReleaseVersion:(nullable NSString *)deviceOsReleaseVersion + screenHeightPixels:(nullable NSNumber *)screenHeightPixels + screenWidthPixels:(nullable NSNumber *)screenWidthPixels { + NativeUserContextData* pigeonResult = [[NativeUserContextData alloc] init]; + pigeonResult.deviceName = deviceName; + pigeonResult.thirdPartyDeviceId = thirdPartyDeviceId; + pigeonResult.deviceFingerprint = deviceFingerprint; + pigeonResult.applicationName = applicationName; + pigeonResult.applicationVersion = applicationVersion; + pigeonResult.deviceLanguage = deviceLanguage; + pigeonResult.deviceOsReleaseVersion = deviceOsReleaseVersion; + pigeonResult.screenHeightPixels = screenHeightPixels; + pigeonResult.screenWidthPixels = screenWidthPixels; + return pigeonResult; +} ++ (NativeUserContextData *)fromList:(NSArray *)list { + NativeUserContextData *pigeonResult = [[NativeUserContextData alloc] init]; + pigeonResult.deviceName = GetNullableObjectAtIndex(list, 0); + pigeonResult.thirdPartyDeviceId = GetNullableObjectAtIndex(list, 1); + pigeonResult.deviceFingerprint = GetNullableObjectAtIndex(list, 2); + pigeonResult.applicationName = GetNullableObjectAtIndex(list, 3); + pigeonResult.applicationVersion = GetNullableObjectAtIndex(list, 4); + pigeonResult.deviceLanguage = GetNullableObjectAtIndex(list, 5); + pigeonResult.deviceOsReleaseVersion = GetNullableObjectAtIndex(list, 6); + pigeonResult.screenHeightPixels = GetNullableObjectAtIndex(list, 7); + pigeonResult.screenWidthPixels = GetNullableObjectAtIndex(list, 8); + return pigeonResult; +} ++ (nullable NativeUserContextData *)nullableFromList:(NSArray *)list { + return (list) ? [NativeUserContextData fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.deviceName ?: [NSNull null]), + (self.thirdPartyDeviceId ?: [NSNull null]), + (self.deviceFingerprint ?: [NSNull null]), + (self.applicationName ?: [NSNull null]), + (self.applicationVersion ?: [NSNull null]), + (self.deviceLanguage ?: [NSNull null]), + (self.deviceOsReleaseVersion ?: [NSNull null]), + (self.screenHeightPixels ?: [NSNull null]), + (self.screenWidthPixels ?: [NSNull null]), + ]; +} +@end + +@implementation LegacyCredentialStoreData ++ (instancetype)makeWithIdentityId:(nullable NSString *)identityId + accessKeyId:(nullable NSString *)accessKeyId + secretAccessKey:(nullable NSString *)secretAccessKey + sessionToken:(nullable NSString *)sessionToken + expirationMsSinceEpoch:(nullable NSNumber *)expirationMsSinceEpoch + accessToken:(nullable NSString *)accessToken + refreshToken:(nullable NSString *)refreshToken + idToken:(nullable NSString *)idToken { + LegacyCredentialStoreData* pigeonResult = [[LegacyCredentialStoreData alloc] init]; + pigeonResult.identityId = identityId; + pigeonResult.accessKeyId = accessKeyId; + pigeonResult.secretAccessKey = secretAccessKey; + pigeonResult.sessionToken = sessionToken; + pigeonResult.expirationMsSinceEpoch = expirationMsSinceEpoch; + pigeonResult.accessToken = accessToken; + pigeonResult.refreshToken = refreshToken; + pigeonResult.idToken = idToken; + return pigeonResult; +} ++ (LegacyCredentialStoreData *)fromList:(NSArray *)list { + LegacyCredentialStoreData *pigeonResult = [[LegacyCredentialStoreData alloc] init]; + pigeonResult.identityId = GetNullableObjectAtIndex(list, 0); + pigeonResult.accessKeyId = GetNullableObjectAtIndex(list, 1); + pigeonResult.secretAccessKey = GetNullableObjectAtIndex(list, 2); + pigeonResult.sessionToken = GetNullableObjectAtIndex(list, 3); + pigeonResult.expirationMsSinceEpoch = GetNullableObjectAtIndex(list, 4); + pigeonResult.accessToken = GetNullableObjectAtIndex(list, 5); + pigeonResult.refreshToken = GetNullableObjectAtIndex(list, 6); + pigeonResult.idToken = GetNullableObjectAtIndex(list, 7); + return pigeonResult; +} ++ (nullable LegacyCredentialStoreData *)nullableFromList:(NSArray *)list { + return (list) ? [LegacyCredentialStoreData fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.identityId ?: [NSNull null]), + (self.accessKeyId ?: [NSNull null]), + (self.secretAccessKey ?: [NSNull null]), + (self.sessionToken ?: [NSNull null]), + (self.expirationMsSinceEpoch ?: [NSNull null]), + (self.accessToken ?: [NSNull null]), + (self.refreshToken ?: [NSNull null]), + (self.idToken ?: [NSNull null]), + ]; +} +@end + +@implementation LegacyDeviceDetailsSecret ++ (instancetype)makeWithDeviceKey:(nullable NSString *)deviceKey + deviceGroupKey:(nullable NSString *)deviceGroupKey + devicePassword:(nullable NSString *)devicePassword + asfDeviceId:(nullable NSString *)asfDeviceId { + LegacyDeviceDetailsSecret* pigeonResult = [[LegacyDeviceDetailsSecret alloc] init]; + pigeonResult.deviceKey = deviceKey; + pigeonResult.deviceGroupKey = deviceGroupKey; + pigeonResult.devicePassword = devicePassword; + pigeonResult.asfDeviceId = asfDeviceId; + return pigeonResult; +} ++ (LegacyDeviceDetailsSecret *)fromList:(NSArray *)list { + LegacyDeviceDetailsSecret *pigeonResult = [[LegacyDeviceDetailsSecret alloc] init]; + pigeonResult.deviceKey = GetNullableObjectAtIndex(list, 0); + pigeonResult.deviceGroupKey = GetNullableObjectAtIndex(list, 1); + pigeonResult.devicePassword = GetNullableObjectAtIndex(list, 2); + pigeonResult.asfDeviceId = GetNullableObjectAtIndex(list, 3); + return pigeonResult; +} ++ (nullable LegacyDeviceDetailsSecret *)nullableFromList:(NSArray *)list { + return (list) ? [LegacyDeviceDetailsSecret fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.deviceKey ?: [NSNull null]), + (self.deviceGroupKey ?: [NSNull null]), + (self.devicePassword ?: [NSNull null]), + (self.asfDeviceId ?: [NSNull null]), + ]; +} +@end + +NSObject *NativeAuthPluginGetCodec(void) { + static FlutterStandardMessageCodec *sSharedObject = nil; + sSharedObject = [FlutterStandardMessageCodec sharedInstance]; + return sSharedObject; +} + +@interface NativeAuthPlugin () +@property(nonatomic, strong) NSObject *binaryMessenger; +@end + +@implementation NativeAuthPlugin + +- (instancetype)initWithBinaryMessenger:(NSObject *)binaryMessenger { + self = [super init]; + if (self) { + _binaryMessenger = binaryMessenger; + } + return self; +} +- (void)exchangeParams:(NSDictionary *)arg_params completion:(void (^)(FlutterError *_Nullable))completion { + FlutterBasicMessageChannel *channel = + [FlutterBasicMessageChannel + messageChannelWithName:@"dev.flutter.pigeon.amplify_auth_cognito.NativeAuthPlugin.exchange" + binaryMessenger:self.binaryMessenger + codec:NativeAuthPluginGetCodec()]; + [channel sendMessage:@[arg_params ?: [NSNull null]] reply:^(id reply) { + completion(nil); + }]; +} +@end + +@interface NativeAuthBridgeCodecReader : FlutterStandardReader +@end +@implementation NativeAuthBridgeCodecReader +- (nullable id)readValueOfType:(UInt8)type { + switch (type) { + case 128: + return [LegacyCredentialStoreData fromList:[self readValue]]; + case 129: + return [LegacyDeviceDetailsSecret fromList:[self readValue]]; + case 130: + return [NativeUserContextData fromList:[self readValue]]; + default: + return [super readValueOfType:type]; + } +} +@end + +@interface NativeAuthBridgeCodecWriter : FlutterStandardWriter +@end +@implementation NativeAuthBridgeCodecWriter +- (void)writeValue:(id)value { + if ([value isKindOfClass:[LegacyCredentialStoreData class]]) { + [self writeByte:128]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[LegacyDeviceDetailsSecret class]]) { + [self writeByte:129]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[NativeUserContextData class]]) { + [self writeByte:130]; + [self writeValue:[value toList]]; + } else { + [super writeValue:value]; + } +} +@end + +@interface NativeAuthBridgeCodecReaderWriter : FlutterStandardReaderWriter +@end +@implementation NativeAuthBridgeCodecReaderWriter +- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { + return [[NativeAuthBridgeCodecWriter alloc] initWithData:data]; +} +- (FlutterStandardReader *)readerWithData:(NSData *)data { + return [[NativeAuthBridgeCodecReader alloc] initWithData:data]; +} +@end + +NSObject *NativeAuthBridgeGetCodec(void) { + static FlutterStandardMessageCodec *sSharedObject = nil; + static dispatch_once_t sPred = 0; + dispatch_once(&sPred, ^{ + NativeAuthBridgeCodecReaderWriter *readerWriter = [[NativeAuthBridgeCodecReaderWriter alloc] init]; + sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; + }); + return sSharedObject; +} + +void NativeAuthBridgeSetup(id binaryMessenger, NSObject *api) { + /// Sign in by presenting [url] and waiting for a response to a URL with + /// [callbackUrlScheme]. + /// + /// If [preferPrivateSession] is `true`, do not persist session cookies. + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.signInWithUrl" + binaryMessenger:binaryMessenger + codec:NativeAuthBridgeGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(signInWithUrlUrl:callbackUrlScheme:preferPrivateSession:browserPackageName:completion:)], @"NativeAuthBridge api (%@) doesn't respond to @selector(signInWithUrlUrl:callbackUrlScheme:preferPrivateSession:browserPackageName:completion:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSString *arg_url = GetNullableObjectAtIndex(args, 0); + NSString *arg_callbackUrlScheme = GetNullableObjectAtIndex(args, 1); + NSNumber *arg_preferPrivateSession = GetNullableObjectAtIndex(args, 2); + NSString *arg_browserPackageName = GetNullableObjectAtIndex(args, 3); + [api signInWithUrlUrl:arg_url callbackUrlScheme:arg_callbackUrlScheme preferPrivateSession:arg_preferPrivateSession browserPackageName:arg_browserPackageName completion:^(NSDictionary *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + /// Sign out by presenting [url] and waiting for a response to a URL with + /// [callbackUrlScheme]. + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.signOutWithUrl" + binaryMessenger:binaryMessenger + codec:NativeAuthBridgeGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(signOutWithUrlUrl:callbackUrlScheme:preferPrivateSession:browserPackageName:completion:)], @"NativeAuthBridge api (%@) doesn't respond to @selector(signOutWithUrlUrl:callbackUrlScheme:preferPrivateSession:browserPackageName:completion:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSString *arg_url = GetNullableObjectAtIndex(args, 0); + NSString *arg_callbackUrlScheme = GetNullableObjectAtIndex(args, 1); + NSNumber *arg_preferPrivateSession = GetNullableObjectAtIndex(args, 2); + NSString *arg_browserPackageName = GetNullableObjectAtIndex(args, 3); + [api signOutWithUrlUrl:arg_url callbackUrlScheme:arg_callbackUrlScheme preferPrivateSession:arg_preferPrivateSession browserPackageName:arg_browserPackageName completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + /// Retrieves the validation data for the current iOS/Android device. + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.getValidationData" + binaryMessenger:binaryMessenger + codec:NativeAuthBridgeGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(getValidationDataWithError:)], @"NativeAuthBridge api (%@) doesn't respond to @selector(getValidationDataWithError:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + NSDictionary *output = [api getValidationDataWithError:&error]; + callback(wrapResult(output, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + /// Retrieves context data as required for advanced security features (ASF). + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.getContextData" + binaryMessenger:binaryMessenger + codec:NativeAuthBridgeGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(getContextDataWithError:)], @"NativeAuthBridge api (%@) doesn't respond to @selector(getContextDataWithError:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + NativeUserContextData *output = [api getContextDataWithError:&error]; + callback(wrapResult(output, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.getBundleId" + binaryMessenger:binaryMessenger + codec:NativeAuthBridgeGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(getBundleIdWithError:)], @"NativeAuthBridge api (%@) doesn't respond to @selector(getBundleIdWithError:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + FlutterError *error; + NSString *output = [api getBundleIdWithError:&error]; + callback(wrapResult(output, error)); + }]; + } else { + [channel setMessageHandler:nil]; + } + } + /// Fetch legacy credentials stored by native SDKs. + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.getLegacyCredentials" + binaryMessenger:binaryMessenger + codec:NativeAuthBridgeGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(getLegacyCredentialsIdentityPoolId:appClientId:completion:)], @"NativeAuthBridge api (%@) doesn't respond to @selector(getLegacyCredentialsIdentityPoolId:appClientId:completion:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSString *arg_identityPoolId = GetNullableObjectAtIndex(args, 0); + NSString *arg_appClientId = GetNullableObjectAtIndex(args, 1); + [api getLegacyCredentialsIdentityPoolId:arg_identityPoolId appClientId:arg_appClientId completion:^(LegacyCredentialStoreData *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + /// Clears the legacy credential store data. + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.clearLegacyCredentials" + binaryMessenger:binaryMessenger + codec:NativeAuthBridgeGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(clearLegacyCredentialsWithCompletion:)], @"NativeAuthBridge api (%@) doesn't respond to @selector(clearLegacyCredentialsWithCompletion:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + [api clearLegacyCredentialsWithCompletion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + /// Fetch legacy device secrets stored by native SDKs. + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.fetchLegacyDeviceSecrets" + binaryMessenger:binaryMessenger + codec:NativeAuthBridgeGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(fetchLegacyDeviceSecretsUserPoolId:appClientId:completion:)], @"NativeAuthBridge api (%@) doesn't respond to @selector(fetchLegacyDeviceSecretsUserPoolId:appClientId:completion:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSString *arg_userPoolId = GetNullableObjectAtIndex(args, 0); + NSString *arg_appClientId = GetNullableObjectAtIndex(args, 1); + [api fetchLegacyDeviceSecretsUserPoolId:arg_userPoolId appClientId:arg_appClientId completion:^(LegacyDeviceDetailsSecret *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } + /// Clears the legacy device secrets. + { + FlutterBasicMessageChannel *channel = + [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.deleteLegacyDeviceSecrets" + binaryMessenger:binaryMessenger + codec:NativeAuthBridgeGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(deleteLegacyDeviceSecretsUserPoolId:appClientId:completion:)], @"NativeAuthBridge api (%@) doesn't respond to @selector(deleteLegacyDeviceSecretsUserPoolId:appClientId:completion:)", api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + NSString *arg_userPoolId = GetNullableObjectAtIndex(args, 0); + NSString *arg_appClientId = GetNullableObjectAtIndex(args, 1); + [api deleteLegacyDeviceSecretsUserPoolId:arg_userPoolId appClientId:arg_appClientId completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } +} diff --git a/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_android.dart b/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_android.dart index 101164b5b4..d5182dac92 100644 --- a/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_android.dart +++ b/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_android.dart @@ -4,7 +4,9 @@ // ignore_for_file: implementation_imports, invalid_use_of_internal_member import 'package:amplify_auth_cognito/src/credentials/legacy_credential_store_data_extension.dart'; -import 'package:amplify_auth_cognito/src/native_auth_plugin.g.dart'; +import 'package:amplify_auth_cognito/src/credentials/legacy_device_details_extension.dart'; +import 'package:amplify_auth_cognito/src/native_auth_plugin.g.dart' + as auth_cognito; import 'package:amplify_auth_cognito_dart/src/credentials/legacy_credential_provider.dart'; import 'package:amplify_auth_cognito_dart/src/state/cognito_state_machine.dart'; import 'package:amplify_auth_cognito_dart/src/state/state.dart'; @@ -28,7 +30,7 @@ class LegacyCredentialProviderAndroid implements LegacyCredentialProvider { CognitoIdentityCredentialsProvider? identityPoolConfig, CognitoOAuthConfig? hostedUiConfig, }) async { - final bridge = _stateMachine.expect(); + final bridge = _stateMachine.expect(); final legacyCredentials = await bridge.getLegacyCredentials( identityPoolConfig?.poolId, userPoolConfig?.appClientId, @@ -42,7 +44,30 @@ class LegacyCredentialProviderAndroid implements LegacyCredentialProvider { CognitoIdentityCredentialsProvider? identityPoolConfig, CognitoOAuthConfig? hostedUiConfig, }) { - final bridge = _stateMachine.expect(); + final bridge = _stateMachine.expect(); return bridge.clearLegacyCredentials(); } + + @override + Future fetchLegacyDeviceSecrets({ + CognitoUserPoolConfig? userPoolConfig, + }) async { + final bridge = _stateMachine.expect(); + final device = await bridge.fetchLegacyDeviceSecrets( + userPoolConfig?.poolId, + userPoolConfig?.appClientId, + ); + return device?.toLegacyDeviceDetails(); + } + + @override + Future deleteLegacyDeviceSecrets({ + CognitoUserPoolConfig? userPoolConfig, + }) { + final bridge = _stateMachine.expect(); + return bridge.deleteLegacyDeviceSecrets( + userPoolConfig?.poolId, + userPoolConfig?.appClientId, + ); + } } diff --git a/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_impl.dart b/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_impl.dart index 3421989ce2..0e811a789a 100644 --- a/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_impl.dart +++ b/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_impl.dart @@ -61,4 +61,24 @@ class LegacyCredentialProviderImpl implements LegacyCredentialProvider { hostedUiConfig: hostedUiConfig, ); } + + @override + Future fetchLegacyDeviceSecrets({ + CognitoUserPoolConfig? userPoolConfig, + }) async { + if (_instance == null) return null; + return _instance!.fetchLegacyDeviceSecrets( + userPoolConfig: userPoolConfig, + ); + } + + @override + Future deleteLegacyDeviceSecrets({ + CognitoUserPoolConfig? userPoolConfig, + }) async { + if (_instance == null) return; + return _instance!.deleteLegacyDeviceSecrets( + userPoolConfig: userPoolConfig, + ); + } } diff --git a/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_ios.dart b/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_ios.dart index df9497d9a0..f12e5623ac 100644 --- a/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_ios.dart +++ b/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_credential_provider_ios.dart @@ -5,7 +5,8 @@ import 'dart:async'; import 'package:amplify_auth_cognito/src/credentials/legacy_ios_cognito_keys.dart'; import 'package:amplify_auth_cognito/src/credentials/secure_storage_extension.dart'; -import 'package:amplify_auth_cognito/src/native_auth_plugin.g.dart'; +import 'package:amplify_auth_cognito/src/native_auth_plugin.g.dart' + as auth_cognito; import 'package:amplify_auth_cognito_dart/amplify_auth_cognito_dart.dart'; // ignore: implementation_imports import 'package:amplify_auth_cognito_dart/src/credentials/legacy_credential_provider.dart'; @@ -160,12 +161,80 @@ class LegacyCredentialProviderIOS implements LegacyCredentialProvider { } } + @override + Future 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], + ); + final asfDeviceId = + await userPoolStorage.read(key: keys[LegacyDeviceSecretKey.id]); + + if (deviceKey != null && + devicePassword != null && + deviceGroupKey != null && + asfDeviceId != null) { + return LegacyDeviceDetails( + deviceKey: deviceKey, + deviceGroupKey: deviceGroupKey, + devicePassword: devicePassword, + asfDeviceId: asfDeviceId, + ); + } + } + } + + return null; + } + + @override + Future 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], + ]); + } + } + } + final _bundleIdMemoizer = AsyncMemoizer(); /// Gets the bundle ID. FutureOr _getBundleId() { return _bundleIdMemoizer.runOnce(() { - final bridge = _stateMachine.expect(); + final bridge = _stateMachine.expect(); return bridge.getBundleId(); }); } diff --git a/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_device_details_extension.dart b/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_device_details_extension.dart new file mode 100644 index 0000000000..cedc003ff3 --- /dev/null +++ b/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_device_details_extension.dart @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import 'package:amplify_auth_cognito/src/native_auth_plugin.g.dart'; +// ignore: implementation_imports +import 'package:amplify_auth_cognito_dart/src/credentials/legacy_credential_provider.dart'; + +/// {@template amplify_auth_cognito.legacy_device_details_extension} +/// Extensions to convert legacy device details secret stored by +/// the legacy Android SDK to legacy device details. +/// {@endtemplate} + +extension LegacyDeviceDetailsX on LegacyDeviceDetailsSecret { + /// {@macro amplify_auth_cognito.legacy_device_details} + LegacyDeviceDetails? toLegacyDeviceDetails() { + if (deviceKey == null || deviceGroupKey == null || devicePassword == null) { + return null; + } + return LegacyDeviceDetails( + deviceKey: deviceKey, + deviceGroupKey: deviceGroupKey, + devicePassword: devicePassword, + asfDeviceId: asfDeviceId, + ); + } +} diff --git a/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_ios_cognito_keys.dart b/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_ios_cognito_keys.dart index ab69acba81..a7f74a832d 100644 --- a/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_ios_cognito_keys.dart +++ b/packages/auth/amplify_auth_cognito/lib/src/credentials/legacy_ios_cognito_keys.dart @@ -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. @@ -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 { + /// {@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 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 { + /// {@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 get _values => LegacyAsfDeviceKey.values; + + @override + String get prefix => '${config.poolId}.$currentUserId.asf.device'; +} + /// {@template amplify_auth_cognito.cognito_keys} /// Iterable secure storage keys. /// {@endtemplate} diff --git a/packages/auth/amplify_auth_cognito/lib/src/native_auth_plugin.g.dart b/packages/auth/amplify_auth_cognito/lib/src/native_auth_plugin.g.dart index 6565384954..5b02976ba5 100644 --- a/packages/auth/amplify_auth_cognito/lib/src/native_auth_plugin.g.dart +++ b/packages/auth/amplify_auth_cognito/lib/src/native_auth_plugin.g.dart @@ -1,7 +1,7 @@ // // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Autogenerated from Pigeon (v11.0.0), do not edit directly. +// Autogenerated from Pigeon (v11.0.1), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import @@ -128,6 +128,42 @@ class LegacyCredentialStoreData { } } +class LegacyDeviceDetailsSecret { + LegacyDeviceDetailsSecret({ + this.deviceKey, + this.deviceGroupKey, + this.devicePassword, + this.asfDeviceId, + }); + + String? deviceKey; + + String? deviceGroupKey; + + String? devicePassword; + + String? asfDeviceId; + + Object encode() { + return [ + deviceKey, + deviceGroupKey, + devicePassword, + asfDeviceId, + ]; + } + + static LegacyDeviceDetailsSecret decode(Object result) { + result as List; + return LegacyDeviceDetailsSecret( + deviceKey: result[0] as String?, + deviceGroupKey: result[1] as String?, + devicePassword: result[2] as String?, + asfDeviceId: result[3] as String?, + ); + } +} + abstract class NativeAuthPlugin { static const MessageCodec codec = StandardMessageCodec(); @@ -168,9 +204,12 @@ class _NativeAuthBridgeCodec extends StandardMessageCodec { if (value is LegacyCredentialStoreData) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else if (value is NativeUserContextData) { + } else if (value is LegacyDeviceDetailsSecret) { buffer.putUint8(129); writeValue(buffer, value.encode()); + } else if (value is NativeUserContextData) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -182,6 +221,8 @@ class _NativeAuthBridgeCodec extends StandardMessageCodec { case 128: return LegacyCredentialStoreData.decode(readValue(buffer)!); case 129: + return LegacyDeviceDetailsSecret.decode(readValue(buffer)!); + case 130: return NativeUserContextData.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -404,4 +445,54 @@ class NativeAuthBridge { return; } } + + /// Fetch legacy device secrets stored by native SDKs. + Future fetchLegacyDeviceSecrets( + String? arg_userPoolId, String? arg_appClientId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.fetchLegacyDeviceSecrets', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_userPoolId, arg_appClientId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return (replyList[0] as LegacyDeviceDetailsSecret?); + } + } + + /// Clears the legacy device secrets. + Future deleteLegacyDeviceSecrets( + String? arg_userPoolId, String? arg_appClientId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.amplify_auth_cognito.NativeAuthBridge.deleteLegacyDeviceSecrets', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_userPoolId, arg_appClientId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } } diff --git a/packages/auth/amplify_auth_cognito/pigeons/native_auth_plugin.dart b/packages/auth/amplify_auth_cognito/pigeons/native_auth_plugin.dart index 732e599505..0adbafb3b3 100644 --- a/packages/auth/amplify_auth_cognito/pigeons/native_auth_plugin.dart +++ b/packages/auth/amplify_auth_cognito/pigeons/native_auth_plugin.dart @@ -69,6 +69,20 @@ abstract class NativeAuthBridge { /// Clears the legacy credential store data. @async void clearLegacyCredentials(); + + /// Fetch legacy device secrets stored by native SDKs. + @async + LegacyDeviceDetailsSecret? fetchLegacyDeviceSecrets( + String? userPoolId, + String? appClientId, + ); + + /// Clears the legacy device secrets. + @async + void deleteLegacyDeviceSecrets( + String? userPoolId, + String? appClientId, + ); } class NativeUserContextData { @@ -93,3 +107,14 @@ class LegacyCredentialStoreData { String? refreshToken; String? idToken; } + +class CognitoUserPoolConfig { + String? poolId; +} + +class LegacyDeviceDetailsSecret { + String? deviceKey; + String? deviceGroupKey; + String? devicePassword; + String? asfDeviceId; +} diff --git a/packages/auth/amplify_auth_cognito_dart/lib/src/credentials/legacy_credential_provider.dart b/packages/auth/amplify_auth_cognito_dart/lib/src/credentials/legacy_credential_provider.dart index b01e4bcbaa..faf725defc 100644 --- a/packages/auth/amplify_auth_cognito_dart/lib/src/credentials/legacy_credential_provider.dart +++ b/packages/auth/amplify_auth_cognito_dart/lib/src/credentials/legacy_credential_provider.dart @@ -18,10 +18,45 @@ abstract interface class LegacyCredentialProvider { CognitoOAuthConfig? hostedUiConfig, }); + /// Fetches legacy device secrets if they are present. + Future fetchLegacyDeviceSecrets({ + CognitoUserPoolConfig? userPoolConfig, + }); + /// Deletes legacy credentials if they are present. Future deleteLegacyCredentials({ CognitoUserPoolConfig? userPoolConfig, CognitoIdentityCredentialsProvider? identityPoolConfig, CognitoOAuthConfig? hostedUiConfig, }); + + /// Deletes legacy device secrets if they are present. + Future deleteLegacyDeviceSecrets({ + 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, + required this.asfDeviceId, + }); + + /// The device key/ID. + final String? deviceKey; + + /// The device group key. + final String? deviceGroupKey; + + /// The device password. + final String? devicePassword; + + /// The asf device ID. + final String? asfDeviceId; } diff --git a/packages/auth/amplify_auth_cognito_dart/lib/src/model/cognito_device_secrets.dart b/packages/auth/amplify_auth_cognito_dart/lib/src/model/cognito_device_secrets.dart index 0ad52e8aac..d12eafa6b6 100644 --- a/packages/auth/amplify_auth_cognito_dart/lib/src/model/cognito_device_secrets.dart +++ b/packages/auth/amplify_auth_cognito_dart/lib/src/model/cognito_device_secrets.dart @@ -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'; @@ -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 + ..deviceKey = details.deviceKey + ..deviceGroupKey = details.deviceGroupKey + ..devicePassword = details.devicePassword; + }); + } CognitoDeviceSecrets._(); @BuiltValueHook(finalizeBuilder: true) diff --git a/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/credential_store_state_machine.dart b/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/credential_store_state_machine.dart index 4ca8fd74f8..4770114e28 100644 --- a/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/credential_store_state_machine.dart +++ b/packages/auth/amplify_auth_cognito_dart/lib/src/state/machines/credential_store_state_machine.dart @@ -7,9 +7,11 @@ import 'dart:convert'; import 'package:amplify_auth_cognito_dart/amplify_auth_cognito_dart.dart'; import 'package:amplify_auth_cognito_dart/src/credentials/cognito_keys.dart'; import 'package:amplify_auth_cognito_dart/src/credentials/credential_store_keys.dart'; +import 'package:amplify_auth_cognito_dart/src/credentials/device_metadata_repository.dart'; import 'package:amplify_auth_cognito_dart/src/credentials/legacy_credential_provider.dart'; import 'package:amplify_auth_cognito_dart/src/credentials/secure_storage_extension.dart'; import 'package:amplify_auth_cognito_dart/src/model/auth_configuration.dart'; +import 'package:amplify_auth_cognito_dart/src/model/cognito_device_secrets.dart'; import 'package:amplify_auth_cognito_dart/src/model/session/cognito_sign_in_details.dart'; import 'package:amplify_auth_cognito_dart/src/sdk/cognito_identity_provider.dart'; import 'package:amplify_auth_cognito_dart/src/state/cognito_state_machine.dart'; @@ -45,6 +47,8 @@ final class CredentialStoreStateMachine SecureStorageInterface get _secureStorage => getOrCreate(); + DeviceMetadataRepository get _deviceRepository => getOrCreate(); + @override Future resolve(CredentialStoreEvent event) async { switch (event) { @@ -310,43 +314,97 @@ final class CredentialStoreStateMachine await _secureStorage.deleteMany(deletions); } + /// Migrates legacy credential store data, include AWS Credentials, User Pool + /// tokens, Device Info, and ASF Device ID. Future _migrateLegacyCredentialStore() async { final version = await getVersion(); if (version != CredentialStoreVersion.none) { return; } - emit(const CredentialStoreState.migratingLegacyStore()); - final legacyCredentialProvider = get(); - if (legacyCredentialProvider != null) { - final authConfig = expect(); + final credentialData = await _migrateLegacyCredentials(); + final username = credentialData?.userPoolTokens?.username; + if (username != null) { + await _migrateDeviceSecrets(username); + } + await _deleteLegacyCredentials(); + await _updateVersion(CredentialStoreVersion.v1); + } + + /// Migrates AWS Credentials and User Pool tokens. + Future _migrateLegacyCredentials() async { + final provider = get(); + final authConfig = expect(); + if (provider == null) return null; + CredentialStoreData? legacyData; + try { + legacyData = await provider.fetchLegacyCredentials( + userPoolConfig: authConfig.userPoolConfig, + identityPoolConfig: authConfig.identityPoolConfig, + hostedUiConfig: authConfig.hostedUiConfig, + ); + if (legacyData != null) { + await _storeCredentials(legacyData); + } + } on Object catch (e, s) { + logger.error('Error migrating legacy credentials', e, s); + } + return legacyData; + } + + /// Migrates legacy device secrets. + Future _migrateDeviceSecrets(String username) async { + final credentialProvider = get(); + final authConfig = expect(); + final userPoolKeys = CognitoUserPoolKeys(authConfig.userPoolConfig!); + if (credentialProvider == null) return; + try { + final legacySecrets = await credentialProvider.fetchLegacyDeviceSecrets( + userPoolConfig: authConfig.userPoolConfig, + ); + if (legacySecrets != null) { + final secrets = CognitoDeviceSecrets.fromLegacyDeviceDetails( + legacySecrets, + ); + await _deviceRepository.put(username, secrets); + } + + // Migrate Asf Device ID + final asfDeviceId = legacySecrets?.asfDeviceId; + if (asfDeviceId != null) { + await _secureStorage.write( + key: userPoolKeys[CognitoUserPoolKey.asfDeviceId], + value: asfDeviceId, + ); + } + } on Object catch (e, s) { + logger.error('Error migrating legacy device secrets', e, s); + } finally { try { - final legacyData = - await legacyCredentialProvider.fetchLegacyCredentials( + await credentialProvider.deleteLegacyDeviceSecrets( userPoolConfig: authConfig.userPoolConfig, - identityPoolConfig: authConfig.identityPoolConfig, - hostedUiConfig: authConfig.hostedUiConfig, ); - if (legacyData != null) { - await _storeCredentials(legacyData); - } } on Object catch (e, s) { - logger.error('Error migrating legacy credentials', e, s); - } finally { - try { - await legacyCredentialProvider.deleteLegacyCredentials( - userPoolConfig: authConfig.userPoolConfig, - identityPoolConfig: authConfig.identityPoolConfig, - hostedUiConfig: authConfig.hostedUiConfig, - ); - } on Object catch (e, s) { - logger.error('Error clearing legacy credentials', e, s); - } + logger.error('Error clearing legacy device secrets', e, s); } } + } - await _updateVersion(CredentialStoreVersion.v1); + /// Deletes legacy credentials. + Future _deleteLegacyCredentials() async { + final provider = get(); + final authConfig = expect(); + if (provider == null) return; + try { + await provider.deleteLegacyCredentials( + userPoolConfig: authConfig.userPoolConfig, + identityPoolConfig: authConfig.identityPoolConfig, + hostedUiConfig: authConfig.hostedUiConfig, + ); + } on Object catch (e, s) { + logger.error('Error clearing legacy credentials', e, s); } +} /// State machine callback for the [CredentialStoreLoadCredentialStore] event. Future onLoadCredentialStore( diff --git a/packages/auth/amplify_auth_cognito_test/lib/common/mock_legacy_credential_provider.dart b/packages/auth/amplify_auth_cognito_test/lib/common/mock_legacy_credential_provider.dart index 65401e9f18..f68d0c9c08 100644 --- a/packages/auth/amplify_auth_cognito_test/lib/common/mock_legacy_credential_provider.dart +++ b/packages/auth/amplify_auth_cognito_test/lib/common/mock_legacy_credential_provider.dart @@ -30,4 +30,18 @@ class MockLegacyCredentialProvider implements LegacyCredentialProvider { }) async { return data; } + + @override + Future deleteLegacyDeviceSecrets({ + CognitoUserPoolConfig? userPoolConfig, + }) async { + return; + } + + @override + Future fetchLegacyDeviceSecrets({ + CognitoUserPoolConfig? userPoolConfig, + }) async { + return null; + } }