/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include #include #include #include #include #include #include #include #include #include #include #include #include namespace AZ { AZ_TYPE_INFO_SPECIALIZE(AWSClientAuth::ProviderNameEnum, "{FB34B23A-B249-47A2-B1F1-C05284B50CCC}"); } namespace AWSClientAuth { constexpr char SerializeComponentName[] = "AWSClientAuth"; void AWSClientAuthSystemComponent::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serialize = azrtti_cast(context); if (serialize) { serialize->Class()->Version(2); if (AZ::EditContext* ec = serialize->GetEditContext()) { ec->Class("AWSClientAuth", "Provides Client Authentication and Authorization implementations") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AutoExpand, true); } AWSClientAuth::LWAProviderSetting::Reflect(*serialize); AWSClientAuth::GoogleProviderSetting::Reflect(*serialize); } AWSClientAuth::AuthenticationTokens::Reflect(context); AWSClientAuth::ClientAuthAWSCredentials::Reflect(context); if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { behaviorContext->Enum<(int)ProviderNameEnum::None>("ProviderNameEnum_None") ->Enum<(int)ProviderNameEnum::AWSCognitoIDP>("ProviderNameEnum_AWSCognitoIDP") ->Enum<(int)ProviderNameEnum::LoginWithAmazon>("ProviderNameEnum_LoginWithAmazon") ->Enum<(int)ProviderNameEnum::Google>("ProviderNameEnum_Google"); behaviorContext->EBus("AuthenticationProviderRequestBus") ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Event("Initialize", &AuthenticationProviderScriptCanvasRequestBus::Events::Initialize) ->Event("IsSignedIn", &AuthenticationProviderScriptCanvasRequestBus::Events::IsSignedIn, { { { "Provider name", "The identity provider name" } } }) ->Event("GetAuthenticationTokens", &AuthenticationProviderScriptCanvasRequestBus::Events::GetAuthenticationTokens, { { { "Provider name", "The identity provider name" } } }) ->Event( "PasswordGrantSingleFactorSignInAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantSingleFactorSignInAsync, { { { "Provider name", "The identity provider" }, { "Username", "The client's username" }, { "Password", "The client's password" } } }) ->Event( "PasswordGrantMultiFactorSignInAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantMultiFactorSignInAsync, { { { "Provider name", "The identity provider name" }, { "Username", "The client's username" }, { "Password", "The client's password" } } }) ->Event( "PasswordGrantMultiFactorConfirmSignInAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantMultiFactorConfirmSignInAsync, { { { "Provider name", "The identity provider name" }, { "Username", "The client's username" }, { "Confirmation code", "The client's confirmation code" } } }) ->Event( "DeviceCodeGrantSignInAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::DeviceCodeGrantSignInAsync, { { { "Provider name", "The identity provider name" } } }) ->Event( "DeviceCodeGrantConfirmSignInAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::DeviceCodeGrantConfirmSignInAsync, { { { "Provider name", "The identity provider name" } } }) ->Event( "RefreshTokensAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::RefreshTokensAsync, { { { "Provider name", "The identity provider name" } } }) ->Event("GetTokensWithRefreshAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::GetTokensWithRefreshAsync, { { { "Provider name", "The identity provider name" } } }) ->Event( "SignOut", &AuthenticationProviderScriptCanvasRequestBus::Events::SignOut, { { { "Provider name", "The identity provider name" } } }); behaviorContext->EBus("AWSCognitoAuthorizationRequestBus") ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Event("Initialize", &AWSCognitoAuthorizationRequestBus::Events::Initialize) ->Event("Reset", &AWSCognitoAuthorizationRequestBus::Events::Reset) ->Event("GetIdentityId", &AWSCognitoAuthorizationRequestBus::Events::GetIdentityId) ->Event("HasPersistedLogins", &AWSCognitoAuthorizationRequestBus::Events::HasPersistedLogins) ->Event("RequestAWSCredentialsAsync", &AWSCognitoAuthorizationRequestBus::Events::RequestAWSCredentialsAsync); behaviorContext->EBus("AWSCognitoUserManagementRequestBus") ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Event("Initialize", &AWSCognitoUserManagementRequestBus::Events::Initialize) ->Event( "EmailSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::EmailSignUpAsync, { { { "Username", "The client's username" }, { "Password", "The client's password" }, { "Email", "The email address used to sign up" } } }) ->Event( "PhoneSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::PhoneSignUpAsync, { { { "Username", "The client's username" }, { "Password", "The client's password" }, { "Phone number", "The phone number used to sign up" } } }) ->Event( "ConfirmSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::ConfirmSignUpAsync, { { { "Username", "The client's username" }, { "Confirmation code", "The client's confirmation code" } } }) ->Event( "ForgotPasswordAsync", &AWSCognitoUserManagementRequestBus::Events::ForgotPasswordAsync, { { { "Username", "The client's username" } } }) ->Event( "ConfirmForgotPasswordAsync", &AWSCognitoUserManagementRequestBus::Events::ConfirmForgotPasswordAsync, { { { "Username", "The client's username" }, { "Confirmation code", "The client's confirmation code" }, { "New password", "The new password for the client" } } }) ->Event("EnableMFAAsync", &AWSCognitoUserManagementRequestBus::Events::EnableMFAAsync, { { { "Access token", "The MFA access token" } } }); behaviorContext->EBus("AuthenticationProviderNotificationBus") ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Handler(); behaviorContext->EBus("AWSCognitoUserManagementNotificationBus") ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Handler(); behaviorContext->EBus("AWSCognitoAuthorizationNotificationBus") ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Handler(); } } void AWSClientAuthSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { provided.push_back(AZ_CRC_CE("AWSClientAuthService")); } void AWSClientAuthSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { incompatible.push_back(AZ_CRC_CE("AWSClientAuthService")); } void AWSClientAuthSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { required.push_back(AZ_CRC_CE("AWSCoreService")); } void AWSClientAuthSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) { AZ_UNUSED(dependent); } void AWSClientAuthSystemComponent::Init() { m_enabledProviderNames.push_back(ProviderNameEnum::AWSCognitoIDP); // As this Gem depends on AWSCore, AWSCoreSystemComponent gets activated before AWSClientAuth and will miss the OnSDKInitialized // notification if BusConnect is not in Init. AWSCore::AWSCoreNotificationsBus::Handler::BusConnect(); } void AWSClientAuthSystemComponent::Activate() { AZ::Interface::Register(this); AWSClientAuthRequestBus::Handler::BusConnect(); m_authenticationProviderManager = AZStd::make_unique(); // Sanity check if code should setup Cognito user and autorization controllers. // Only set up if Cognito settings appear to be provided in resource mapping file. // Cognito User Pools and Cognito Identity Pools are not dependent on one another, but we need at least one. // Create a controller for user pools and identity pools. bool awsCognitoUserPoolDefined = false; AWSCore::AWSResourceMappingRequestBus::BroadcastResult( awsCognitoUserPoolDefined, &AWSCore::AWSResourceMappingRequests::HasResource, CognitoUserPoolIdResourceMappingKey); if (awsCognitoUserPoolDefined) { m_awsCognitoUserManagementController = AZStd::make_unique(); } bool awsCognitoIdentityPoolDefined = false; AWSCore::AWSResourceMappingRequestBus::BroadcastResult( awsCognitoIdentityPoolDefined, &AWSCore::AWSResourceMappingRequests::HasResource, CognitoIdentityPoolIdResourceMappingKey); if (awsCognitoIdentityPoolDefined) { m_awsCognitoAuthorizationController = AZStd::make_unique(); } if (!awsCognitoUserPoolDefined && !awsCognitoIdentityPoolDefined) { AZ_Warning("AWSClientAuthSystemComponent", false, "Missing Cognito settings in resource mappings. Skipping set up of Cognito controllers."); } } void AWSClientAuthSystemComponent::Deactivate() { m_authenticationProviderManager.reset(); m_awsCognitoUserManagementController.reset(); m_awsCognitoAuthorizationController.reset(); AWSClientAuthRequestBus::Handler::BusDisconnect(); AWSCore::AWSCoreNotificationsBus::Handler::BusDisconnect(); AZ::Interface::Unregister(this); m_cognitoIdentityProviderClient.reset(); m_cognitoIdentityClient.reset(); } void AWSClientAuthSystemComponent::OnSDKInitialized() { AWSCore::AwsApiJobConfig* defaultConfig; AWSCore::AWSCoreRequestBus::BroadcastResult(defaultConfig, &AWSCore::AWSCoreRequests::GetDefaultConfig); Aws::Client::ClientConfiguration clientConfiguration = defaultConfig ? defaultConfig->GetClientConfiguration() : Aws::Client::ClientConfiguration(); AZStd::string region; AWSCore::AWSResourceMappingRequestBus::BroadcastResult(region, &AWSCore::AWSResourceMappingRequests::GetDefaultRegion); clientConfiguration.region = "us-west-2"; if (!region.empty()) { clientConfiguration.region = region.c_str(); } m_cognitoIdentityProviderClient = std::make_shared(Aws::Auth::AWSCredentials(), clientConfiguration); m_cognitoIdentityClient = std::make_shared(Aws::Auth::AWSCredentials(), clientConfiguration); } std::shared_ptr AWSClientAuthSystemComponent::GetCognitoIDPClient() { return m_cognitoIdentityProviderClient; } std::shared_ptr AWSClientAuthSystemComponent::GetCognitoIdentityClient() { return m_cognitoIdentityClient; } bool AWSClientAuthSystemComponent::HasCognitoControllers() const { return (m_awsCognitoUserManagementController != nullptr) || (m_awsCognitoAuthorizationController != nullptr); } } // namespace AWSClientAuth