Integrating latest 47acbe8
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#include <AWSClientAuthModule.h>
|
||||
#include <AWSClientAuthSystemComponent.h>
|
||||
|
||||
namespace AWSClientAuth
|
||||
{
|
||||
|
||||
AWSClientAuthModule::AWSClientAuthModule()
|
||||
: AZ::Module()
|
||||
{
|
||||
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
|
||||
m_descriptors.insert(m_descriptors.end(), {
|
||||
AWSClientAuthSystemComponent::CreateDescriptor()
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add required SystemComponents to the SystemEntity.
|
||||
*/
|
||||
AZ::ComponentTypeList AWSClientAuthModule::GetRequiredSystemComponents() const
|
||||
{
|
||||
return AZ::ComponentTypeList{
|
||||
azrtti_typeid<AWSClientAuthSystemComponent>(),
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// DO NOT MODIFY THIS LINE UNLESS YOU RENAME THE GEM
|
||||
// The first parameter should be GemName_GemIdLower
|
||||
// The second should be the fully qualified name of the class above
|
||||
AZ_DECLARE_MODULE_CLASS(AWSClientAuth_c74f2756f5874c0d8d29646dfc9cb0ad, AWSClientAuth::AWSClientAuthModule)
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AWSClientAuthSystemComponent.h>
|
||||
#include <Authentication/AuthenticationProviderTypes.h>
|
||||
#include <Authentication/AuthenticationNotificationBusBehaviorHandler.h>
|
||||
#include <UserManagement/UserManagementNotificationBusBehaviorHandler.h>
|
||||
#include <Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h>
|
||||
#include <Authorization/AWSCognitoAuthorizationController.h>
|
||||
#include <Authorization/AWSCognitoAuthorizationTypes.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <ResourceMapping/AWSResourceMappingBus.h>
|
||||
|
||||
#include <aws/cognito-identity/CognitoIdentityClient.h>
|
||||
#include <aws/cognito-idp/CognitoIdentityProviderClient.h>
|
||||
|
||||
namespace AWSClientAuth
|
||||
{
|
||||
constexpr char SERIALIZE_COMPONENT_NAME[] = "AWSClientAuth";
|
||||
|
||||
void AWSClientAuthSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<AWSClientAuthSystemComponent, AZ::Component>()->Version(0);
|
||||
|
||||
if (AZ::EditContext* ec = serialize->GetEditContext())
|
||||
{
|
||||
ec->Class<AWSClientAuthSystemComponent>("AWSClientAuth", "Provides Client Authentication and Authorization implementations")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System"))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true);
|
||||
}
|
||||
AWSClientAuth::AWSCognitoProviderSetting::Reflect(*serialize);
|
||||
AWSClientAuth::LWAProviderSetting::Reflect(*serialize);
|
||||
AWSClientAuth::GoogleProviderSetting::Reflect(*serialize);
|
||||
AWSClientAuth::CognitoAuthorizationSettings::Reflect(*serialize);
|
||||
AWSClientAuth::AWSCognitoUserManagementSetting::Reflect(*serialize);
|
||||
}
|
||||
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->EBus<AuthenticationProviderRequestBus>("AuthenticationProviderRequestBus")
|
||||
->Attribute(AZ::Script::Attributes::Category, SERIALIZE_COMPONENT_NAME)
|
||||
->Event("Initialize", &AuthenticationProviderRequestBus::Events::Initialize)
|
||||
->Event("IsSignedIn", &AuthenticationProviderRequestBus::Events::IsSignedIn)
|
||||
->Event("GetAuthenticationTokens", &AuthenticationProviderRequestBus::Events::GetAuthenticationTokens)
|
||||
->Event(
|
||||
"PasswordGrantSingleFactorSignInAsync", &AuthenticationProviderRequestBus::Events::PasswordGrantSingleFactorSignInAsync)
|
||||
->Event("DeviceCodeGrantSignInAsync", &AuthenticationProviderRequestBus::Events::DeviceCodeGrantSignInAsync)
|
||||
->Event("DeviceCodeGrantConfirmSignInAsync", &AuthenticationProviderRequestBus::Events::DeviceCodeGrantConfirmSignInAsync)
|
||||
->Event("RefreshTokensAsync", &AuthenticationProviderRequestBus::Events::RefreshTokensAsync)
|
||||
->Event("GetTokensWithRefreshAsync", &AuthenticationProviderRequestBus::Events::GetTokensWithRefreshAsync)
|
||||
->Event("SignOut", &AuthenticationProviderRequestBus::Events::SignOut);
|
||||
|
||||
behaviorContext->EBus<AWSCognitoAuthorizationRequestBus>("AWSCognitoAuthorizationRequestBus")
|
||||
->Attribute(AZ::Script::Attributes::Category, SERIALIZE_COMPONENT_NAME)
|
||||
->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>("AWSCognitoUserManagementRequestBus")
|
||||
->Attribute(AZ::Script::Attributes::Category, SERIALIZE_COMPONENT_NAME)
|
||||
->Event("Initialize", &AWSCognitoUserManagementRequestBus::Events::Initialize)
|
||||
->Event("EmailSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::EmailSignUpAsync)
|
||||
->Event("PhoneSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::PhoneSignUpAsync)
|
||||
->Event("ConfirmSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::ConfirmSignUpAsync)
|
||||
->Event("ForgotPasswordAsync", &AWSCognitoUserManagementRequestBus::Events::ForgotPasswordAsync)
|
||||
->Event("ConfirmForgotPasswordAsync", &AWSCognitoUserManagementRequestBus::Events::ConfirmForgotPasswordAsync)
|
||||
->Event("EnableMFAAsync", &AWSCognitoUserManagementRequestBus::Events::EnableMFAAsync);
|
||||
|
||||
behaviorContext->EBus<AuthenticationProviderNotificationBus>("AuthenticationProviderNotificationBus")
|
||||
->Handler<AuthenticationNotificationBusBehaviorHandler>();
|
||||
behaviorContext->EBus<AWSCognitoUserManagementNotificationBus>("AWSCognitoUserManagementNotificationBus")
|
||||
->Handler<UserManagementNotificationBusBehaviorHandler>();
|
||||
behaviorContext->EBus<AWSCognitoAuthorizationNotificationBus>("AWSCognitoAuthorizationNotificationBus")
|
||||
->Handler<AWSCognitoAuthorizationNotificationBusBehaviorHandler>();
|
||||
}
|
||||
}
|
||||
|
||||
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<IAWSClientAuthRequests>::Register(this);
|
||||
AWSClientAuthRequestBus::Handler::BusConnect();
|
||||
|
||||
// Objects below depend on bus above.
|
||||
m_authenticationProviderManager = AZStd::make_unique<AuthenticationProviderManager>();
|
||||
m_awsCognitoUserManagementController = AZStd::make_unique<AWSCognitoUserManagementController>();
|
||||
m_awsCognitoAuthorizationController = AZStd::make_unique<AWSCognitoAuthorizationController>();
|
||||
|
||||
AWSCore::AWSCoreEditorRequestBus::Broadcast(&AWSCore::AWSCoreEditorRequests::SetAWSClientAuthEnabled);
|
||||
}
|
||||
|
||||
void AWSClientAuthSystemComponent::Deactivate()
|
||||
{
|
||||
m_authenticationProviderManager.reset();
|
||||
m_awsCognitoUserManagementController.reset();
|
||||
m_awsCognitoAuthorizationController.reset();
|
||||
|
||||
AWSClientAuthRequestBus::Handler::BusDisconnect();
|
||||
AWSCore::AWSCoreNotificationsBus::Handler::BusDisconnect();
|
||||
AZ::Interface<IAWSClientAuthRequests>::Unregister(this);
|
||||
|
||||
m_cognitoIdentityProviderClient.reset();
|
||||
m_cognitoIdentityClient.reset();
|
||||
}
|
||||
|
||||
void AWSClientAuthSystemComponent::OnSDKInitialized()
|
||||
{
|
||||
Aws::Client::ClientConfiguration 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::CognitoIdentityProvider::CognitoIdentityProviderClient>(clientConfiguration);
|
||||
m_cognitoIdentityClient = std::make_shared<Aws::CognitoIdentity::CognitoIdentityClient>(clientConfiguration);
|
||||
}
|
||||
|
||||
std::shared_ptr<Aws::CognitoIdentityProvider::CognitoIdentityProviderClient> AWSClientAuthSystemComponent::GetCognitoIDPClient()
|
||||
{
|
||||
return m_cognitoIdentityProviderClient;
|
||||
}
|
||||
|
||||
std::shared_ptr<Aws::CognitoIdentity::CognitoIdentityClient> AWSClientAuthSystemComponent::GetCognitoIdentityClient()
|
||||
{
|
||||
return m_cognitoIdentityClient;
|
||||
}
|
||||
|
||||
} // namespace AWSClientAuth
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/std/smart_ptr/weak_ptr.h>
|
||||
#include <AzCore/Jobs/JobFunction.h>
|
||||
|
||||
#include <Authentication/AWSCognitoAuthenticationProvider.h>
|
||||
#include <Authentication/AuthenticationProviderTypes.h>
|
||||
#include <Authentication/AuthenticationProviderBus.h>
|
||||
#include <AWSClientAuthBus.h>
|
||||
#include <AWSCoreBus.h>
|
||||
|
||||
#include <aws/cognito-idp/model/InitiateAuthRequest.h>
|
||||
#include <aws/cognito-idp/model/InitiateAuthResult.h>
|
||||
#include <aws/cognito-idp/model/RespondToAuthChallengeRequest.h>
|
||||
#include <aws/cognito-idp/model/RespondToAuthChallengeResult.h>
|
||||
#include <aws/cognito-idp/CognitoIdentityProviderClient.h>
|
||||
#include <aws/cognito-idp/CognitoIdentityProviderErrors.h>
|
||||
|
||||
namespace AWSClientAuth
|
||||
{
|
||||
|
||||
constexpr char COGNITO_IDP_SETTINGS_PATH[] = "/AWS/CognitoIDP";
|
||||
constexpr char COGNITO_USERNAME_KEY[] = "USERNAME";
|
||||
constexpr char COGNITO_PASSWORD_KEY[] = "PASSWORD";
|
||||
constexpr char COGNITO_REFRESH_TOKEN_AUTHPARAM_KEY[] = "REFRESH_TOKEN";
|
||||
constexpr char COGNITO_SMS_MFA_CODE_KEY[] = "SMS_MFA_CODE";
|
||||
|
||||
AWSCognitoAuthenticationProvider::AWSCognitoAuthenticationProvider()
|
||||
{
|
||||
m_settings = AZStd::make_unique<AWSCognitoProviderSetting>();
|
||||
}
|
||||
|
||||
AWSCognitoAuthenticationProvider::~AWSCognitoAuthenticationProvider()
|
||||
{
|
||||
m_settings.reset();
|
||||
}
|
||||
|
||||
bool AWSCognitoAuthenticationProvider::Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry)
|
||||
{
|
||||
if (!settingsRegistry.lock()->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), COGNITO_IDP_SETTINGS_PATH))
|
||||
{
|
||||
AZ_Warning("AWSCognitoAuthenticationProvider", true, "Failed to get settings object for path %s", COGNITO_IDP_SETTINGS_PATH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void AWSCognitoAuthenticationProvider::PasswordGrantSingleFactorSignInAsync(const AZStd::string& username, const AZStd::string& password)
|
||||
{
|
||||
InitiateAuthInternalAsync(username, password, [this](Aws::CognitoIdentityProvider::Model::InitiateAuthOutcome initiateAuthOutcome)
|
||||
{
|
||||
if (initiateAuthOutcome.IsSuccess())
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::InitiateAuthResult initiateAuthResult{ initiateAuthOutcome.GetResult() };
|
||||
if (initiateAuthResult.GetChallengeName() == Aws::CognitoIdentityProvider::Model::ChallengeNameType::NOT_SET)
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::AuthenticationResultType authenticationResult = initiateAuthResult.GetAuthenticationResult();
|
||||
UpdateTokens(authenticationResult);
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnPasswordGrantSingleFactorSignInSuccess
|
||||
, m_authenticationTokens);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnPasswordGrantSingleFactorSignInFail
|
||||
, AZStd::string::format("Unexpected Challenge type: %s"
|
||||
, Aws::CognitoIdentityProvider::Model::ChallengeNameTypeMapper::GetNameForChallengeNameType(initiateAuthResult.GetChallengeName()).c_str()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Aws::Client::AWSError<Aws::CognitoIdentityProvider::CognitoIdentityProviderErrors> error = initiateAuthOutcome.GetError();
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnPasswordGrantSingleFactorSignInFail, error.GetMessage().c_str());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void AWSCognitoAuthenticationProvider::PasswordGrantMultiFactorSignInAsync(const AZStd::string& username, const AZStd::string& password)
|
||||
{
|
||||
InitiateAuthInternalAsync(username, password, [this](Aws::CognitoIdentityProvider::Model::InitiateAuthOutcome initiateAuthOutcome)
|
||||
{
|
||||
if (initiateAuthOutcome.IsSuccess())
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::InitiateAuthResult initiateAuthResult{ initiateAuthOutcome.GetResult() };
|
||||
if (initiateAuthResult.GetChallengeName() == Aws::CognitoIdentityProvider::Model::ChallengeNameType::SMS_MFA)
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::AuthenticationResultType authenticationResult = initiateAuthResult.GetAuthenticationResult();
|
||||
// Call on sign in success for MFA
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnPasswordGrantMultiFactorSignInSuccess);
|
||||
m_session = initiateAuthResult.GetSession().c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnPasswordGrantMultiFactorSignInFail
|
||||
, AZStd::string::format("Unexpected Challenge type: %s"
|
||||
, Aws::CognitoIdentityProvider::Model::ChallengeNameTypeMapper::GetNameForChallengeNameType(initiateAuthResult.GetChallengeName()).c_str()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Aws::Client::AWSError<Aws::CognitoIdentityProvider::CognitoIdentityProviderErrors> error = initiateAuthOutcome.GetError();
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnPasswordGrantMultiFactorSignInFail, error.GetMessage().c_str());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Call RespondToAuthChallenge for Cognito authentication flow.
|
||||
// Refer https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html.
|
||||
void AWSCognitoAuthenticationProvider::PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& username, const AZStd::string& confirmationCode)
|
||||
{
|
||||
std::shared_ptr<Aws::CognitoIdentityProvider::CognitoIdentityProviderClient> cognitoIdentityProviderClient =
|
||||
AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIDPClient();
|
||||
|
||||
AZ::JobContext* jobContext = nullptr;
|
||||
AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext);
|
||||
AZ::Job* confirmSignInJob = AZ::CreateJobFunction([this, cognitoIdentityProviderClient, confirmationCode, username]()
|
||||
{
|
||||
// Set Request parameters for SMS Multi factor authentication.
|
||||
// Note: Email MFA is no longer supported by Cognito, use SMS as MFA
|
||||
Aws::CognitoIdentityProvider::Model::RespondToAuthChallengeRequest respondToAuthChallengeRequest;
|
||||
respondToAuthChallengeRequest.SetClientId(m_settings->m_appClientId.c_str());
|
||||
respondToAuthChallengeRequest.AddChallengeResponses(COGNITO_SMS_MFA_CODE_KEY, confirmationCode.c_str());
|
||||
respondToAuthChallengeRequest.AddChallengeResponses(COGNITO_USERNAME_KEY, username.c_str());
|
||||
respondToAuthChallengeRequest.SetChallengeName(Aws::CognitoIdentityProvider::Model::ChallengeNameType::SMS_MFA);
|
||||
respondToAuthChallengeRequest.SetSession(m_session.c_str());
|
||||
|
||||
Aws::CognitoIdentityProvider::Model::RespondToAuthChallengeOutcome respondToAuthChallengeOutcome{ cognitoIdentityProviderClient->RespondToAuthChallenge(respondToAuthChallengeRequest) };
|
||||
if (respondToAuthChallengeOutcome.IsSuccess())
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::RespondToAuthChallengeResult respondToAuthChallengeResult{ respondToAuthChallengeOutcome.GetResult() };
|
||||
if (respondToAuthChallengeResult.GetChallengeName() == Aws::CognitoIdentityProvider::Model::ChallengeNameType::NOT_SET)
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::AuthenticationResultType authenticationResult = respondToAuthChallengeResult.GetAuthenticationResult();
|
||||
UpdateTokens(authenticationResult);
|
||||
AuthenticationProviderNotificationBus::Broadcast(
|
||||
&AuthenticationProviderNotifications::OnPasswordGrantMultiFactorConfirmSignInSuccess, m_authenticationTokens);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Aws::Client::AWSError<Aws::CognitoIdentityProvider::CognitoIdentityProviderErrors> error = respondToAuthChallengeOutcome.GetError();
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnPasswordGrantMultiFactorConfirmSignInFail, error.GetMessage().c_str());
|
||||
}
|
||||
}, true, jobContext);
|
||||
confirmSignInJob->Start();
|
||||
}
|
||||
|
||||
void AWSCognitoAuthenticationProvider::DeviceCodeGrantSignInAsync()
|
||||
{
|
||||
AZ_Assert(true, "Not supported");
|
||||
}
|
||||
|
||||
void AWSCognitoAuthenticationProvider::DeviceCodeGrantConfirmSignInAsync()
|
||||
{
|
||||
AZ_Assert(true, "Not supported");
|
||||
}
|
||||
|
||||
void AWSCognitoAuthenticationProvider::RefreshTokensAsync()
|
||||
{
|
||||
std::shared_ptr<Aws::CognitoIdentityProvider::CognitoIdentityProviderClient> cognitoIdentityProviderClient =
|
||||
AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIDPClient();
|
||||
|
||||
AZ::JobContext* jobContext = nullptr;
|
||||
AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext);
|
||||
|
||||
AZ::Job* initiateAuthJob = AZ::CreateJobFunction([this, cognitoIdentityProviderClient]()
|
||||
{
|
||||
// Set Request parameters.
|
||||
Aws::CognitoIdentityProvider::Model::InitiateAuthRequest initiateAuthRequest;
|
||||
initiateAuthRequest.SetClientId(m_settings->m_appClientId.c_str());
|
||||
initiateAuthRequest.SetAuthFlow(Aws::CognitoIdentityProvider::Model::AuthFlowType::REFRESH_TOKEN_AUTH);
|
||||
|
||||
// Set username and password for Password grant/ Initiate Auth flow.
|
||||
Aws::Map<Aws::String, Aws::String> authParameters
|
||||
{
|
||||
{COGNITO_REFRESH_TOKEN_AUTHPARAM_KEY, GetAuthenticationTokens().GetRefreshToken().c_str()}
|
||||
};
|
||||
initiateAuthRequest.SetAuthParameters(authParameters);
|
||||
|
||||
Aws::CognitoIdentityProvider::Model::InitiateAuthOutcome initiateAuthOutcome{ cognitoIdentityProviderClient->InitiateAuth(initiateAuthRequest) };
|
||||
if (initiateAuthOutcome.IsSuccess())
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::InitiateAuthResult initiateAuthResult{ initiateAuthOutcome.GetResult() };
|
||||
if (initiateAuthResult.GetChallengeName() == Aws::CognitoIdentityProvider::Model::ChallengeNameType::NOT_SET)
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::AuthenticationResultType authenticationResult = initiateAuthResult.GetAuthenticationResult();
|
||||
UpdateTokens(authenticationResult);
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensSuccess, m_authenticationTokens);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensFail
|
||||
, AZStd::string::format("Unexpected Challenge type: %s"
|
||||
, Aws::CognitoIdentityProvider::Model::ChallengeNameTypeMapper::GetNameForChallengeNameType(initiateAuthResult.GetChallengeName()).c_str()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Aws::Client::AWSError<Aws::CognitoIdentityProvider::CognitoIdentityProviderErrors> error = initiateAuthOutcome.GetError();
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensFail, error.GetMessage().c_str());
|
||||
}
|
||||
}, true, jobContext);
|
||||
initiateAuthJob->Start();
|
||||
}
|
||||
|
||||
// Call InitiateAuth for Cognito authentication flow.
|
||||
// Refer https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html.
|
||||
void AWSCognitoAuthenticationProvider::InitiateAuthInternalAsync(const AZStd::string& username, const AZStd::string& password
|
||||
, AZStd::function<void(Aws::CognitoIdentityProvider::Model::InitiateAuthOutcome outcome)> outcomeCallback)
|
||||
{
|
||||
std::shared_ptr<Aws::CognitoIdentityProvider::CognitoIdentityProviderClient> cognitoIdentityProviderClient =
|
||||
AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIDPClient();
|
||||
|
||||
AZ::JobContext* jobContext = nullptr;
|
||||
AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext);
|
||||
|
||||
AZ::Job* initiateAuthJob = AZ::CreateJobFunction([this, cognitoIdentityProviderClient, username, password, outcomeCallback]()
|
||||
{
|
||||
// Set Request parameters.
|
||||
Aws::CognitoIdentityProvider::Model::InitiateAuthRequest initiateAuthRequest;
|
||||
initiateAuthRequest.SetClientId(m_settings->m_appClientId.c_str());
|
||||
initiateAuthRequest.SetAuthFlow(Aws::CognitoIdentityProvider::Model::AuthFlowType::USER_PASSWORD_AUTH);
|
||||
|
||||
// Set username and password for Password grant/ Initiate Auth flow.
|
||||
Aws::Map<Aws::String, Aws::String> authParameters
|
||||
{
|
||||
{COGNITO_USERNAME_KEY, username.c_str()},
|
||||
{COGNITO_PASSWORD_KEY, password.c_str()}
|
||||
};
|
||||
initiateAuthRequest.SetAuthParameters(authParameters);
|
||||
|
||||
Aws::CognitoIdentityProvider::Model::InitiateAuthOutcome initiateAuthOutcome{ cognitoIdentityProviderClient->InitiateAuth(initiateAuthRequest) };
|
||||
outcomeCallback(initiateAuthOutcome);
|
||||
}, true, jobContext);
|
||||
initiateAuthJob->Start();
|
||||
}
|
||||
|
||||
void AWSCognitoAuthenticationProvider::UpdateTokens(const Aws::CognitoIdentityProvider::Model::AuthenticationResultType& authenticationResult)
|
||||
{
|
||||
m_authenticationTokens = AuthenticationTokens(authenticationResult.GetAccessToken().c_str(), authenticationResult.GetRefreshToken().c_str(),
|
||||
authenticationResult.GetIdToken().c_str(), ProviderNameEnum::AWSCognitoIDP,
|
||||
authenticationResult.GetExpiresIn());
|
||||
}
|
||||
} // namespace AWSClientAuth
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Authentication/AuthenticationProviderInterface.h>
|
||||
|
||||
namespace AWSClientAuth
|
||||
{
|
||||
AuthenticationTokens AuthenticationProviderInterface::GetAuthenticationTokens()
|
||||
{
|
||||
return m_authenticationTokens;
|
||||
}
|
||||
|
||||
void AuthenticationProviderInterface::SignOut()
|
||||
{
|
||||
m_authenticationTokens = AuthenticationTokens();
|
||||
}
|
||||
|
||||
|
||||
} // namespace AWSClientAuth
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/Settings/SettingsRegistryImpl.h>
|
||||
|
||||
#include <Authentication/AuthenticationProviderTypes.h>
|
||||
#include <Authentication/AWSCognitoAuthenticationProvider.h>
|
||||
#include <Authentication/LWAAuthenticationProvider.h>
|
||||
#include <Authentication/GoogleAuthenticationProvider.h>
|
||||
#include <Authentication/AuthenticationProviderManager.h>
|
||||
|
||||
namespace AWSClientAuth
|
||||
{
|
||||
AuthenticationProviderManager::AuthenticationProviderManager()
|
||||
{
|
||||
AZ::Interface<IAuthenticationProviderRequests>::Register(this);
|
||||
AuthenticationProviderRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
AuthenticationProviderManager::~AuthenticationProviderManager()
|
||||
{
|
||||
ResetProviders();
|
||||
m_settingsRegistry.reset();
|
||||
AuthenticationProviderRequestBus::Handler::BusDisconnect();
|
||||
AZ::Interface<IAuthenticationProviderRequests>::Unregister(this);
|
||||
}
|
||||
|
||||
bool AuthenticationProviderManager::Initialize(const AZStd::vector<ProviderNameEnum>& providerNames, const AZStd::string& settingsRegistryPath)
|
||||
{
|
||||
ResetProviders();
|
||||
m_settingsRegistry.reset();
|
||||
m_settingsRegistry = AZStd::make_shared<AZ::SettingsRegistryImpl>();
|
||||
|
||||
if (!m_settingsRegistry->MergeSettingsFile(settingsRegistryPath, AZ::SettingsRegistryInterface::Format::JsonMergePatch))
|
||||
{
|
||||
AZ_Error("AuthenticationProviderManager", true, "Error merging settings registry for path: %s", settingsRegistryPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool initializeSuccess = true;
|
||||
|
||||
for (auto providerName : providerNames)
|
||||
{
|
||||
m_authenticationProvidersMap[providerName] = CreateAuthenticationProviderObject(providerName);
|
||||
initializeSuccess = initializeSuccess && m_authenticationProvidersMap[providerName]->Initialize(m_settingsRegistry);
|
||||
}
|
||||
|
||||
return initializeSuccess;
|
||||
}
|
||||
|
||||
void AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password)
|
||||
{
|
||||
if (IsProviderInitialized(providerName))
|
||||
{
|
||||
m_authenticationProvidersMap[providerName]->PasswordGrantSingleFactorSignInAsync(username, password);
|
||||
}
|
||||
}
|
||||
|
||||
void AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password)
|
||||
{
|
||||
if (IsProviderInitialized(providerName))
|
||||
{
|
||||
m_authenticationProvidersMap[providerName]->PasswordGrantMultiFactorSignInAsync(username, password);
|
||||
}
|
||||
}
|
||||
|
||||
void AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& confirmationCode)
|
||||
{
|
||||
if (IsProviderInitialized(providerName))
|
||||
{
|
||||
m_authenticationProvidersMap[providerName]->PasswordGrantMultiFactorConfirmSignInAsync(username, confirmationCode);
|
||||
}
|
||||
}
|
||||
|
||||
void AuthenticationProviderManager::DeviceCodeGrantSignInAsync(const ProviderNameEnum& providerName)
|
||||
{
|
||||
if (IsProviderInitialized(providerName))
|
||||
{
|
||||
m_authenticationProvidersMap[providerName]->DeviceCodeGrantSignInAsync();
|
||||
}
|
||||
}
|
||||
|
||||
void AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync(const ProviderNameEnum& providerName)
|
||||
{
|
||||
if (IsProviderInitialized(providerName))
|
||||
{
|
||||
m_authenticationProvidersMap[providerName]->DeviceCodeGrantConfirmSignInAsync();
|
||||
}
|
||||
}
|
||||
|
||||
void AuthenticationProviderManager::RefreshTokensAsync(const ProviderNameEnum& providerName)
|
||||
{
|
||||
if (IsProviderInitialized(providerName))
|
||||
{
|
||||
m_authenticationProvidersMap[providerName]->RefreshTokensAsync();
|
||||
}
|
||||
}
|
||||
|
||||
void AuthenticationProviderManager::GetTokensWithRefreshAsync(const ProviderNameEnum& providerName)
|
||||
{
|
||||
if (!IsProviderInitialized(providerName))
|
||||
{
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensFail
|
||||
, "Provider is not initialized");
|
||||
}
|
||||
|
||||
AuthenticationTokens tokens = m_authenticationProvidersMap[providerName]->GetAuthenticationTokens();
|
||||
if (tokens.AreTokensValid())
|
||||
{
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensSuccess, tokens);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_authenticationProvidersMap[providerName]->RefreshTokensAsync();
|
||||
}
|
||||
}
|
||||
|
||||
bool AuthenticationProviderManager::IsSignedIn(const ProviderNameEnum& providerName)
|
||||
{
|
||||
if (IsProviderInitialized(providerName))
|
||||
{
|
||||
return m_authenticationProvidersMap[providerName]->GetAuthenticationTokens().AreTokensValid();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AuthenticationProviderManager::SignOut(const ProviderNameEnum& providerName)
|
||||
{
|
||||
if (IsProviderInitialized(providerName))
|
||||
{
|
||||
m_authenticationProvidersMap[providerName]->SignOut();
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnSignOut, providerName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
AuthenticationTokens AuthenticationProviderManager::GetAuthenticationTokens(const ProviderNameEnum& providerName)
|
||||
{
|
||||
return m_authenticationProvidersMap[providerName]->GetAuthenticationTokens();
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AuthenticationProviderInterface> AuthenticationProviderManager::CreateAuthenticationProviderObject(const ProviderNameEnum& providerName)
|
||||
{
|
||||
switch (providerName)
|
||||
{
|
||||
case ProviderNameEnum::AWSCognitoIDP:
|
||||
return AZStd::make_unique<AWSCognitoAuthenticationProvider>();
|
||||
case ProviderNameEnum::LoginWithAmazon:
|
||||
return AZStd::make_unique<LWAAuthenticationProvider>();
|
||||
case ProviderNameEnum::Google:
|
||||
return AZStd::make_unique<GoogleAuthenticationProvider>();
|
||||
default:
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool AuthenticationProviderManager::IsProviderInitialized(const ProviderNameEnum& providerName)
|
||||
{
|
||||
bool ret = m_authenticationProvidersMap.contains(providerName);
|
||||
AZ_Assert(ret, "ProviderName enum %i not initialized. Please call initialize first");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AuthenticationProviderManager::ResetProviders()
|
||||
{
|
||||
for (auto& [providerName, providerInterface] : m_authenticationProvidersMap)
|
||||
{
|
||||
providerInterface.reset();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AWSClientAuth
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Authentication/AuthenticationTokens.h>
|
||||
|
||||
namespace AWSClientAuth
|
||||
{
|
||||
//! Used to share authentication tokens to caller and to AWSCognitoAuthorizationController.
|
||||
|
||||
AuthenticationTokens::AuthenticationTokens()
|
||||
{
|
||||
m_tokensExpireTimeStamp = AZStd::chrono::system_clock::time_point::min();
|
||||
m_providerName = ProviderNameEnum::None;
|
||||
}
|
||||
|
||||
AuthenticationTokens::AuthenticationTokens(const AuthenticationTokens& other)
|
||||
{
|
||||
m_accessToken = other.m_accessToken;
|
||||
m_refreshToken = other.m_refreshToken;
|
||||
m_openIdToken = other.m_openIdToken;
|
||||
m_providerName = other.m_providerName;
|
||||
m_tokensExpireTimeSeconds = other.m_tokensExpireTimeSeconds;
|
||||
m_tokensExpireTimeStamp = other.m_tokensExpireTimeStamp;
|
||||
}
|
||||
|
||||
AuthenticationTokens::AuthenticationTokens(
|
||||
const AZStd::string& accessToken, const AZStd::string& refreshToken, const AZStd::string& openidToken, const ProviderNameEnum& providerName, int tokensExpireTimeSeconds)
|
||||
{
|
||||
m_accessToken = accessToken;
|
||||
m_refreshToken = refreshToken;
|
||||
m_openIdToken = openidToken;
|
||||
m_providerName = providerName;
|
||||
m_tokensExpireTimeSeconds = tokensExpireTimeSeconds;
|
||||
m_tokensExpireTimeStamp = AZStd::chrono::system_clock::now() + AZStd::chrono::seconds(tokensExpireTimeSeconds);
|
||||
}
|
||||
|
||||
//! Compares current time stamp to expired time stamp.
|
||||
//! @return True if current TS less than expiry TS.
|
||||
bool AuthenticationTokens::AreTokensValid() const
|
||||
{
|
||||
return AZStd::chrono::system_clock::now() < m_tokensExpireTimeStamp;
|
||||
}
|
||||
|
||||
//! @return Open id token from authentication.
|
||||
AZStd::string AuthenticationTokens::GetOpenIdToken() const
|
||||
{
|
||||
return m_openIdToken;
|
||||
}
|
||||
|
||||
//! @return Access token from authentication.
|
||||
AZStd::string AuthenticationTokens::GetAccessToken() const
|
||||
{
|
||||
return m_accessToken;
|
||||
}
|
||||
|
||||
//! @return Refresh token from authentication.
|
||||
AZStd::string AuthenticationTokens::GetRefreshToken() const
|
||||
{
|
||||
return m_refreshToken;
|
||||
}
|
||||
|
||||
//! @return Provide name for the tokens.
|
||||
ProviderNameEnum AuthenticationTokens::GetProviderName() const
|
||||
{
|
||||
return m_providerName;
|
||||
}
|
||||
|
||||
//! @return Expiration time in seconds.
|
||||
int AuthenticationTokens::GetTokensExpireTimeSeconds() const
|
||||
{
|
||||
return m_tokensExpireTimeSeconds;
|
||||
}
|
||||
} // namespace AWSClientAuth
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <Authentication/GoogleAuthenticationProvider.h>
|
||||
#include <Authentication/AuthenticationProviderBus.h>
|
||||
#include <Authentication/OAuthConstants.h>
|
||||
#include <HttpRequestor/HttpRequestorBus.h>
|
||||
#include <HttpRequestor/HttpTypes.h>
|
||||
|
||||
#include <aws/core/http/HttpResponse.h>
|
||||
|
||||
namespace AWSClientAuth
|
||||
{
|
||||
|
||||
constexpr char GOOGLE_SETTINGS_PATH[] = "/AWS/Google";
|
||||
constexpr char GOOGLE_VERIFICATION_URL_RESPONSE_KEY[] = "verification_url";
|
||||
|
||||
GoogleAuthenticationProvider::GoogleAuthenticationProvider()
|
||||
{
|
||||
m_settings = AZStd::make_unique<GoogleProviderSetting>();
|
||||
}
|
||||
|
||||
GoogleAuthenticationProvider::~GoogleAuthenticationProvider()
|
||||
{
|
||||
m_settings.reset();
|
||||
}
|
||||
|
||||
bool GoogleAuthenticationProvider::Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry)
|
||||
{
|
||||
if (!settingsRegistry.lock()->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), GOOGLE_SETTINGS_PATH))
|
||||
{
|
||||
AZ_Warning("AWSCognitoAuthenticationProvider", true, "Failed to get Google settings object for path %s", GOOGLE_SETTINGS_PATH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GoogleAuthenticationProvider::PasswordGrantSingleFactorSignInAsync(const AZStd::string& username, const AZStd::string& password)
|
||||
{
|
||||
AZ_UNUSED(username);
|
||||
AZ_UNUSED(password);
|
||||
AZ_Assert(true, "Not supported");
|
||||
}
|
||||
|
||||
void GoogleAuthenticationProvider::PasswordGrantMultiFactorSignInAsync(const AZStd::string& username, const AZStd::string& password)
|
||||
{
|
||||
AZ_UNUSED(username);
|
||||
AZ_UNUSED(password);
|
||||
AZ_Assert(true, "Not supported");
|
||||
}
|
||||
|
||||
void GoogleAuthenticationProvider::PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& username, const AZStd::string& confirmationCode)
|
||||
{
|
||||
AZ_UNUSED(username);
|
||||
AZ_UNUSED(confirmationCode);
|
||||
AZ_Assert(true, "Not supported");
|
||||
}
|
||||
|
||||
// Call Google authentication provider device code end point.
|
||||
// Refer https://developers.google.com/identity/protocols/oauth2/limited-input-device#step-1:-request-device-and-user-codes.
|
||||
void GoogleAuthenticationProvider::DeviceCodeGrantSignInAsync()
|
||||
{
|
||||
AZStd::string body = AZStd::string::format("%s=%s&%s=%s", OAUTH_CLIENT_ID_BODY_KEY, m_settings->m_appClientId.c_str()
|
||||
, OAUTH_SCOPE_BODY_KEY, OAUTH_SCOPE_BODY_VALUE);
|
||||
|
||||
// Set headers and body for device sign in http requests.
|
||||
AZStd::map<AZStd::string, AZStd::string> headers;
|
||||
headers[OAUTH_CONTENT_TYPE_HEADER_KEY] = OAUTH_CONTENT_TYPE_HEADER_VALUE;
|
||||
headers[OAUTH_CONTENT_LENGTH_HEADER_KEY] = AZStd::to_string(body.length());
|
||||
|
||||
HttpRequestor::HttpRequestorRequestBus::Broadcast(&HttpRequestor::HttpRequestorRequests::AddRequestWithHeadersAndBody, m_settings->m_oAuthCodeURL
|
||||
, Aws::Http::HttpMethod::HTTP_POST, headers, body
|
||||
, [this](const Aws::Utils::Json::JsonView& jsonView, Aws::Http::HttpResponseCode responseCode)
|
||||
{
|
||||
if (responseCode == Aws::Http::HttpResponseCode::OK)
|
||||
{
|
||||
m_cachedDeviceCode = jsonView.GetString(OAUTH_DEVICE_CODE_BODY_KEY).c_str();
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnDeviceCodeGrantSignInSuccess
|
||||
, jsonView.GetString(OAUTH_USER_CODE_RESPONSE_KEY).c_str(), jsonView.GetString(GOOGLE_VERIFICATION_URL_RESPONSE_KEY).c_str()
|
||||
, jsonView.GetInteger(OAUTH_EXPIRES_IN_RESPONSE_KEY));
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnDeviceCodeGrantSignInFail
|
||||
, jsonView.GetString(OAUTH_ERROR_RESPONSE_KEY).c_str());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Call Google authentication provider OAuth tokens endpoint
|
||||
// Refer https://developers.google.com/identity/protocols/oauth2/limited-input-device#step-4:-poll-googles-authorization-server.
|
||||
void GoogleAuthenticationProvider::DeviceCodeGrantConfirmSignInAsync()
|
||||
{
|
||||
// Set headers and body for device confirm sign in http requests.
|
||||
AZStd::map<AZStd::string, AZStd::string> headers;
|
||||
AZStd::string body = AZStd::string::format("%s=%s&%s=%s&%s=%s&%s=%s", OAUTH_CLIENT_ID_BODY_KEY, m_settings->m_appClientId.c_str()
|
||||
, OAUTH_CLIENT_SECRET_BODY_KEY, m_settings->m_clientSecret.c_str(), OAUTH_DEVICE_CODE_BODY_KEY, m_cachedDeviceCode.c_str()
|
||||
, OAUTH_GRANT_TYPE_BODY_KEY, m_settings->m_grantType.c_str());
|
||||
|
||||
headers[OAUTH_CONTENT_TYPE_HEADER_KEY] = OAUTH_CONTENT_TYPE_HEADER_VALUE;
|
||||
headers[OAUTH_CONTENT_LENGTH_HEADER_KEY] = AZStd::to_string(body.length());
|
||||
|
||||
HttpRequestor::HttpRequestorRequestBus::Broadcast(&HttpRequestor::HttpRequestorRequests::AddRequestWithHeadersAndBody, m_settings->m_oAuthTokensURL
|
||||
, Aws::Http::HttpMethod::HTTP_POST, headers, body
|
||||
, [this](const Aws::Utils::Json::JsonView& jsonView, Aws::Http::HttpResponseCode responseCode)
|
||||
{
|
||||
if (responseCode == Aws::Http::HttpResponseCode::OK)
|
||||
{
|
||||
UpdateTokens(jsonView);
|
||||
AuthenticationProviderNotificationBus::Broadcast(
|
||||
&AuthenticationProviderNotifications::OnDeviceCodeGrantConfirmSignInSuccess, m_authenticationTokens);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnDeviceCodeGrantConfirmSignInFail
|
||||
, jsonView.GetString(OAUTH_ERROR_RESPONSE_KEY).c_str());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Call Google authentication provider OAuth tokens endpoint
|
||||
// Refer https://developers.google.com/identity/protocols/oauth2/limited-input-device#offline.
|
||||
void GoogleAuthenticationProvider::RefreshTokensAsync()
|
||||
{
|
||||
AZStd::map<AZStd::string, AZStd::string> headers;
|
||||
AZStd::string body = AZStd::string::format("%s=%s&%s=%s&%s=%s&%s=%s", OAUTH_CLIENT_ID_BODY_KEY, m_settings->m_appClientId.c_str()
|
||||
, OAUTH_CLIENT_SECRET_BODY_KEY, m_settings->m_clientSecret.c_str()
|
||||
, OAUTH_GRANT_TYPE_BODY_KEY, OAUTH_REFRESH_TOKEN_BODY_VALUE, OAUTH_REFRESH_TOKEN_BODY_KEY, m_authenticationTokens.GetRefreshToken().c_str());
|
||||
|
||||
headers[OAUTH_CONTENT_TYPE_HEADER_KEY] = OAUTH_CONTENT_TYPE_HEADER_VALUE;
|
||||
headers[OAUTH_CONTENT_LENGTH_HEADER_KEY] = AZStd::to_string(body.length());
|
||||
|
||||
HttpRequestor::HttpRequestorRequestBus::Broadcast(&HttpRequestor::HttpRequestorRequests::AddRequestWithHeadersAndBody, m_settings->m_oAuthTokensURL
|
||||
, Aws::Http::HttpMethod::HTTP_POST, headers, body
|
||||
, [this](const Aws::Utils::Json::JsonView& jsonView, Aws::Http::HttpResponseCode responseCode)
|
||||
{
|
||||
if (responseCode == Aws::Http::HttpResponseCode::OK)
|
||||
{
|
||||
UpdateTokens(jsonView);
|
||||
AuthenticationProviderNotificationBus::Broadcast(
|
||||
&AuthenticationProviderNotifications::OnRefreshTokensSuccess, m_authenticationTokens);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensFail
|
||||
, jsonView.GetString(OAUTH_ERROR_RESPONSE_KEY).c_str());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void GoogleAuthenticationProvider::UpdateTokens(const Aws::Utils::Json::JsonView& jsonView)
|
||||
{
|
||||
m_authenticationTokens = AuthenticationTokens(jsonView.GetString(OAUTH_ACCESS_TOKEN_RESPONSE_KEY).c_str(),
|
||||
jsonView.GetString(OAUTH_REFRESH_TOKEN_RESPONSE_KEY).c_str() ,jsonView.GetString(OAUTH_ID_TOKEN_RESPONSE_KEY).c_str(), ProviderNameEnum::Google
|
||||
, jsonView.GetInteger(OAUTH_EXPIRES_IN_RESPONSE_KEY));
|
||||
}
|
||||
|
||||
} // namespace AWSClientAuth
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <Authentication/LWAAuthenticationProvider.h>
|
||||
#include <Authentication/AuthenticationProviderBus.h>
|
||||
#include <Authentication/OAuthConstants.h>
|
||||
#include <HttpRequestor/HttpRequestorBus.h>
|
||||
#include <HttpRequestor/HttpTypes.h>
|
||||
|
||||
#include <aws/core/http/HttpResponse.h>
|
||||
|
||||
namespace AWSClientAuth
|
||||
{
|
||||
constexpr char LWA_SETTINGS_PATH[] = "/AWS/LoginWithAmazon";
|
||||
constexpr char LWA_VERIFICATION_URL_RESPONSE_KEY[] = "verification_uri";
|
||||
|
||||
LWAAuthenticationProvider::LWAAuthenticationProvider()
|
||||
{
|
||||
m_settings = AZStd::make_unique<LWAProviderSetting>();
|
||||
}
|
||||
|
||||
LWAAuthenticationProvider::~LWAAuthenticationProvider()
|
||||
{
|
||||
m_settings.reset();
|
||||
}
|
||||
|
||||
bool LWAAuthenticationProvider::Initialize(AZStd::weak_ptr<AZ::SettingsRegistryInterface> settingsRegistry)
|
||||
{
|
||||
if (!settingsRegistry.lock()->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), LWA_SETTINGS_PATH))
|
||||
{
|
||||
AZ_Warning("AWSCognitoAuthenticationProvider", true, "Failed to get login with Amazon settings object for path %s", LWA_SETTINGS_PATH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LWAAuthenticationProvider::PasswordGrantSingleFactorSignInAsync(const AZStd::string& username, const AZStd::string& password)
|
||||
{
|
||||
AZ_UNUSED(username);
|
||||
AZ_UNUSED(password);
|
||||
AZ_Assert(true, "Not supported");
|
||||
}
|
||||
|
||||
void LWAAuthenticationProvider::PasswordGrantMultiFactorSignInAsync(const AZStd::string& username, const AZStd::string& password)
|
||||
{
|
||||
AZ_UNUSED(username);
|
||||
AZ_UNUSED(password);
|
||||
AZ_Assert(true, "Not supported");
|
||||
}
|
||||
|
||||
void LWAAuthenticationProvider::PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& username, const AZStd::string& confirmationCode)
|
||||
{
|
||||
AZ_UNUSED(username);
|
||||
AZ_UNUSED(confirmationCode);
|
||||
AZ_Assert(true, "Not supported");
|
||||
}
|
||||
|
||||
// Call LWA authentication provider device code end point.
|
||||
// Refer https://developer.amazon.com/docs/login-with-amazon/retrieve-code-other-platforms-cbl-docs.html.
|
||||
void LWAAuthenticationProvider::DeviceCodeGrantSignInAsync()
|
||||
{
|
||||
// Set headers and body for device sign in http requests.
|
||||
AZStd::string body = AZStd::string::format("%s=%s&%s=%s&%s=%s", OAUTH_RESPONSE_TYPE_BODY_KEY, m_settings->m_responseType.c_str()
|
||||
, OAUTH_CLIENT_ID_BODY_KEY, m_settings->m_appClientId.c_str(), OAUTH_SCOPE_BODY_KEY, OAUTH_SCOPE_BODY_VALUE);
|
||||
|
||||
AZStd::map<AZStd::string, AZStd::string> headers;
|
||||
headers[OAUTH_CONTENT_TYPE_HEADER_KEY] = OAUTH_CONTENT_TYPE_HEADER_VALUE;
|
||||
headers[OAUTH_CONTENT_LENGTH_HEADER_KEY] = AZStd::to_string(body.length());
|
||||
|
||||
HttpRequestor::HttpRequestorRequestBus::Broadcast(&HttpRequestor::HttpRequestorRequests::AddRequestWithHeadersAndBody, m_settings->m_oAuthCodeURL
|
||||
, Aws::Http::HttpMethod::HTTP_POST, headers, body
|
||||
, [this](const Aws::Utils::Json::JsonView& jsonView, Aws::Http::HttpResponseCode responseCode)
|
||||
{
|
||||
if (responseCode == Aws::Http::HttpResponseCode::OK)
|
||||
{
|
||||
m_cachedUserCode = jsonView.GetString(OAUTH_USER_CODE_RESPONSE_KEY).c_str();
|
||||
m_cachedDeviceCode = jsonView.GetString(OAUTH_DEVICE_CODE_BODY_KEY).c_str();
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnDeviceCodeGrantSignInSuccess
|
||||
, jsonView.GetString(OAUTH_USER_CODE_RESPONSE_KEY).c_str()
|
||||
, jsonView.GetString(LWA_VERIFICATION_URL_RESPONSE_KEY).c_str()
|
||||
, jsonView.GetInteger(OAUTH_EXPIRES_IN_RESPONSE_KEY));
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnDeviceCodeGrantSignInFail
|
||||
, jsonView.GetString(OAUTH_ERROR_RESPONSE_KEY).c_str());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Call LWA authentication provider OAuth tokens endpoint
|
||||
// Refer https://developer.amazon.com/docs/login-with-amazon/retrieve-token-other-platforms-cbl-docs.html
|
||||
void LWAAuthenticationProvider::DeviceCodeGrantConfirmSignInAsync()
|
||||
{
|
||||
// Set headers and body for device confirm sign in http requests.
|
||||
AZStd::string body = AZStd::string::format("%s=%s&%s=%s&%s=%s", OAUTH_USER_CODE_RESPONSE_KEY, m_cachedUserCode.c_str()
|
||||
, OAUTH_GRANT_TYPE_BODY_KEY, m_settings->m_grantType.c_str(), OAUTH_DEVICE_CODE_BODY_KEY, m_cachedDeviceCode.c_str());
|
||||
|
||||
AZStd::map<AZStd::string, AZStd::string> headers;
|
||||
headers[OAUTH_CONTENT_TYPE_HEADER_KEY] = OAUTH_CONTENT_TYPE_HEADER_VALUE;
|
||||
headers[OAUTH_CONTENT_LENGTH_HEADER_KEY] = AZStd::to_string(body.length());
|
||||
|
||||
HttpRequestor::HttpRequestorRequestBus::Broadcast(&HttpRequestor::HttpRequestorRequests::AddRequestWithHeadersAndBody, m_settings->m_oAuthTokensURL
|
||||
, Aws::Http::HttpMethod::HTTP_POST, headers, body
|
||||
, [this](const Aws::Utils::Json::JsonView& jsonView, Aws::Http::HttpResponseCode responseCode)
|
||||
{
|
||||
if (responseCode == Aws::Http::HttpResponseCode::OK)
|
||||
{
|
||||
// Id and access token are the same.
|
||||
UpdateTokens(jsonView);
|
||||
AuthenticationProviderNotificationBus::Broadcast(
|
||||
&AuthenticationProviderNotifications::OnDeviceCodeGrantConfirmSignInSuccess, m_authenticationTokens);
|
||||
m_cachedUserCode = "";
|
||||
m_cachedDeviceCode = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnDeviceCodeGrantConfirmSignInFail
|
||||
, jsonView.GetString("error").c_str());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void LWAAuthenticationProvider::RefreshTokensAsync()
|
||||
{
|
||||
// Set headers and body for device confirm sign in http requests.
|
||||
AZStd::string body = AZStd::string::format("%s=%s&%s=%s&%s=%s", OAUTH_CLIENT_ID_BODY_KEY, m_settings->m_appClientId.c_str(), OAUTH_GRANT_TYPE_BODY_KEY,
|
||||
OAUTH_REFRESH_TOKEN_BODY_VALUE, OAUTH_REFRESH_TOKEN_BODY_KEY, m_authenticationTokens.GetRefreshToken().c_str());
|
||||
|
||||
AZStd::map<AZStd::string, AZStd::string> headers;
|
||||
headers[OAUTH_CONTENT_TYPE_HEADER_KEY] = OAUTH_CONTENT_TYPE_HEADER_VALUE;
|
||||
headers[OAUTH_CONTENT_LENGTH_HEADER_KEY] = AZStd::to_string(body.length());
|
||||
|
||||
HttpRequestor::HttpRequestorRequestBus::Broadcast(&HttpRequestor::HttpRequestorRequests::AddRequestWithHeadersAndBody, m_settings->m_oAuthTokensURL
|
||||
, Aws::Http::HttpMethod::HTTP_POST, headers, body
|
||||
, [this](const Aws::Utils::Json::JsonView& jsonView, Aws::Http::HttpResponseCode responseCode)
|
||||
{
|
||||
if (responseCode == Aws::Http::HttpResponseCode::OK)
|
||||
{
|
||||
// Id and access token are the same.
|
||||
UpdateTokens(jsonView);
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensSuccess, m_authenticationTokens);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensFail
|
||||
, jsonView.GetString("error").c_str());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void LWAAuthenticationProvider::UpdateTokens(const Aws::Utils::Json::JsonView& jsonView)
|
||||
{
|
||||
// For Login with Amazon openId and access tokens are the same.
|
||||
m_authenticationTokens = AuthenticationTokens(jsonView.GetString(OAUTH_ACCESS_TOKEN_RESPONSE_KEY).c_str(), jsonView.GetString(OAUTH_REFRESH_TOKEN_RESPONSE_KEY).c_str(),
|
||||
jsonView.GetString(OAUTH_ACCESS_TOKEN_RESPONSE_KEY).c_str(), ProviderNameEnum::LoginWithAmazon
|
||||
, jsonView.GetInteger(OAUTH_EXPIRES_IN_RESPONSE_KEY));
|
||||
}
|
||||
|
||||
} // namespace AWSClientAuth
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Authorization/AWSClientAuthPersistentCognitoIdentityProvider.h>
|
||||
|
||||
namespace AWSClientAuth
|
||||
{
|
||||
AWSClientAuthPersistentCognitoIdentityProvider::~AWSClientAuthPersistentCognitoIdentityProvider()
|
||||
{
|
||||
m_logins.clear();
|
||||
m_awsAccountId = "";
|
||||
m_identityPoolId = "";
|
||||
m_identityId = "";
|
||||
m_identityIdUpdatedCallback = nullptr;
|
||||
m_loginsUpdatedCallback = nullptr;
|
||||
}
|
||||
|
||||
void AWSClientAuthPersistentCognitoIdentityProvider::Initialize(const Aws::String& awsAccountId, const Aws::String& identityPoolId)
|
||||
{
|
||||
m_identityPoolId = identityPoolId;
|
||||
m_awsAccountId = awsAccountId;
|
||||
}
|
||||
|
||||
bool AWSClientAuthPersistentCognitoIdentityProvider::HasIdentityId() const
|
||||
{
|
||||
return !m_identityId.empty();
|
||||
}
|
||||
|
||||
bool AWSClientAuthPersistentCognitoIdentityProvider::HasLogins() const
|
||||
{
|
||||
return m_logins.size() > 0;
|
||||
}
|
||||
|
||||
Aws::String AWSClientAuthPersistentCognitoIdentityProvider::GetIdentityId() const
|
||||
{
|
||||
return m_identityId;
|
||||
}
|
||||
|
||||
Aws::Map<Aws::String, Aws::Auth::LoginAccessTokens> AWSClientAuthPersistentCognitoIdentityProvider::GetLogins()
|
||||
{
|
||||
return m_logins;
|
||||
}
|
||||
|
||||
Aws::String AWSClientAuthPersistentCognitoIdentityProvider::GetAccountId() const
|
||||
{
|
||||
return m_awsAccountId;
|
||||
}
|
||||
|
||||
Aws::String AWSClientAuthPersistentCognitoIdentityProvider::GetIdentityPoolId() const
|
||||
{
|
||||
return m_identityPoolId;
|
||||
}
|
||||
|
||||
void AWSClientAuthPersistentCognitoIdentityProvider::PersistIdentityId(const Aws::String& identityId)
|
||||
{
|
||||
m_identityId = identityId;
|
||||
if (m_identityIdUpdatedCallback)
|
||||
{
|
||||
m_identityIdUpdatedCallback(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void AWSClientAuthPersistentCognitoIdentityProvider::PersistLogins(const Aws::Map<Aws::String, Aws::Auth::LoginAccessTokens>& logins)
|
||||
{
|
||||
m_logins = logins;
|
||||
if (m_loginsUpdatedCallback)
|
||||
{
|
||||
m_loginsUpdatedCallback(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void AWSClientAuthPersistentCognitoIdentityProvider::RemoveLogin(const Aws::String& key)
|
||||
{
|
||||
m_logins.erase(key);
|
||||
if (m_loginsUpdatedCallback)
|
||||
{
|
||||
m_loginsUpdatedCallback(*this);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AWSClientAuth
|
||||
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AWSClientAuthBus.h>
|
||||
#include <AWSCoreBus.h>
|
||||
#include <Authorization/AWSCognitoAuthorizationController.h>
|
||||
#include <AzCore/EBus/Internal/BusContainer.h>
|
||||
#include <AzCore/Jobs/JobFunction.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Settings/SettingsRegistryImpl.h>
|
||||
|
||||
#include <aws/identity-management/auth/CognitoCachingCredentialsProvider.h>
|
||||
|
||||
namespace AWSClientAuth
|
||||
{
|
||||
constexpr char COGNITO_AUTHORIZATION_SETTINGS_PATH[] = "/AWS/CognitoIdentityPool";
|
||||
|
||||
AWSCognitoAuthorizationController::AWSCognitoAuthorizationController()
|
||||
{
|
||||
AZ::Interface<IAWSCognitoAuthorizationRequests>::Register(this);
|
||||
AWSCognitoAuthorizationRequestBus::Handler::BusConnect();
|
||||
AuthenticationProviderNotificationBus::Handler::BusConnect();
|
||||
AWSCore::AWSCredentialRequestBus::Handler::BusConnect();
|
||||
|
||||
m_settings = AZStd::make_unique<CognitoAuthorizationSettings>();
|
||||
|
||||
m_persistentCognitoIdentityProvider = std::make_shared<AWSClientAuthPersistentCognitoIdentityProvider>();
|
||||
m_persistentAnonymousCognitoIdentityProvider = std::make_shared<AWSClientAuthPersistentCognitoIdentityProvider>();
|
||||
|
||||
auto identityClient = AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIdentityClient();
|
||||
|
||||
m_cognitoCachingCredentialsProvider =
|
||||
std::make_shared<Aws::Auth::CognitoCachingAuthenticatedCredentialsProvider>(m_persistentCognitoIdentityProvider, identityClient);
|
||||
|
||||
m_cognitoCachingAnonymousCredentialsProvider =
|
||||
std::make_shared<Aws::Auth::CognitoCachingAnonymousCredentialsProvider>(m_persistentAnonymousCognitoIdentityProvider, identityClient);
|
||||
}
|
||||
|
||||
AWSCognitoAuthorizationController::~AWSCognitoAuthorizationController()
|
||||
{
|
||||
m_cognitoCachingCredentialsProvider.reset();
|
||||
m_persistentAnonymousCognitoIdentityProvider.reset();
|
||||
m_persistentCognitoIdentityProvider.reset();
|
||||
m_persistentAnonymousCognitoIdentityProvider.reset();
|
||||
|
||||
m_settings.reset();
|
||||
|
||||
AWSCore::AWSCredentialRequestBus::Handler::BusDisconnect();
|
||||
AuthenticationProviderNotificationBus::Handler::BusDisconnect();
|
||||
AWSCognitoAuthorizationRequestBus::Handler::BusDisconnect();
|
||||
AZ::Interface<IAWSCognitoAuthorizationRequests>::Unregister(this);
|
||||
}
|
||||
|
||||
bool AWSCognitoAuthorizationController::Initialize(const AZStd::string& settingsRegistryPath)
|
||||
{
|
||||
AZStd::unique_ptr<AZ::SettingsRegistryInterface> settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
|
||||
|
||||
if (!settingsRegistry->MergeSettingsFile(settingsRegistryPath, AZ::SettingsRegistryInterface::Format::JsonMergePatch))
|
||||
{
|
||||
AZ_Error("AWSCognitoAuthorizationController", true, "Failed to merge settings file for path %s", settingsRegistryPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!settingsRegistry->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), COGNITO_AUTHORIZATION_SETTINGS_PATH))
|
||||
{
|
||||
AZ_Error("AWSCognitoAuthorizationController", true, "Failed to get settings object for path %s", COGNITO_AUTHORIZATION_SETTINGS_PATH);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_persistentCognitoIdentityProvider->Initialize(m_settings->m_awsAccountId.c_str(), m_settings->m_cognitoIdentityPoolId.c_str());
|
||||
m_persistentAnonymousCognitoIdentityProvider->Initialize(m_settings->m_awsAccountId.c_str(), m_settings->m_cognitoIdentityPoolId.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AWSCognitoAuthorizationController::Reset()
|
||||
{
|
||||
// Brackets for lock guard scopes
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_persistentAnonymousCognitoIdentityProviderMutex);
|
||||
m_persistentAnonymousCognitoIdentityProvider->ClearLogins();
|
||||
m_persistentAnonymousCognitoIdentityProvider->ClearIdentity();
|
||||
}
|
||||
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_persistentCognitoIdentityProviderMutex);
|
||||
m_persistentCognitoIdentityProvider->ClearLogins();
|
||||
m_persistentCognitoIdentityProvider->ClearIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string AWSCognitoAuthorizationController::GetIdentityId()
|
||||
{
|
||||
// Give preference to authenticated credentials provider.
|
||||
if (HasPersistedLogins())
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_persistentCognitoIdentityProviderMutex);
|
||||
return m_persistentCognitoIdentityProvider->GetIdentityId().c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_persistentAnonymousCognitoIdentityProviderMutex);
|
||||
return m_persistentAnonymousCognitoIdentityProvider->GetIdentityId().c_str();
|
||||
}
|
||||
}
|
||||
|
||||
bool AWSCognitoAuthorizationController::HasPersistedLogins()
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_persistentCognitoIdentityProviderMutex);
|
||||
return m_persistentCognitoIdentityProvider->HasLogins();
|
||||
}
|
||||
|
||||
std::shared_ptr<Aws::Auth::AWSCredentialsProvider> AWSCognitoAuthorizationController::GetCognitoCredentialsProvider()
|
||||
{
|
||||
return m_cognitoCachingCredentialsProvider;
|
||||
}
|
||||
|
||||
std::shared_ptr<Aws::Auth::AWSCredentialsProvider> AWSCognitoAuthorizationController::GetAnonymousCognitoCredentialsProvider()
|
||||
{
|
||||
return m_cognitoCachingAnonymousCredentialsProvider;
|
||||
}
|
||||
|
||||
void AWSCognitoAuthorizationController::RequestAWSCredentialsAsync()
|
||||
{
|
||||
bool anonymous = true;
|
||||
// Give preference to authenticated credentials provider.
|
||||
if (m_persistentCognitoIdentityProvider->HasLogins())
|
||||
{
|
||||
anonymous = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("AWSCognitoAuthorizationController", true, "No logins found. Fetching anonymous/unauthenticated credentials");
|
||||
}
|
||||
|
||||
AZ::JobContext* jobContext = nullptr;
|
||||
AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext);
|
||||
AZ::Job* job = AZ::CreateJobFunction(
|
||||
[this, anonymous]() {
|
||||
Aws::Auth::AWSCredentials credentials;
|
||||
// GetAWSCredentials makes Cognito GetId and GetCredentialsForIdentity Cognito identity pool API request if no valid cached credentials found.
|
||||
if (anonymous)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_persistentAnonymousCognitoIdentityProviderMutex);
|
||||
credentials = m_cognitoCachingAnonymousCredentialsProvider->GetAWSCredentials();
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_persistentCognitoIdentityProviderMutex);
|
||||
credentials = m_cognitoCachingCredentialsProvider->GetAWSCredentials();
|
||||
}
|
||||
|
||||
if (!credentials.IsEmpty())
|
||||
{
|
||||
ClientAuthAWSCredentials clientAuthAWSCrendentials(credentials.GetAWSAccessKeyId().c_str(), credentials.GetAWSSecretKey().c_str(), credentials.GetSessionToken().c_str());
|
||||
AWSClientAuth::AWSCognitoAuthorizationNotificationBus::Broadcast(
|
||||
&AWSClientAuth::AWSCognitoAuthorizationNotifications::OnRequestAWSCredentialsSuccess, clientAuthAWSCrendentials);
|
||||
}
|
||||
else
|
||||
{
|
||||
AWSClientAuth::AWSCognitoAuthorizationNotificationBus::Broadcast(
|
||||
&AWSClientAuth::AWSCognitoAuthorizationNotifications::OnRequestAWSCredentialsFail,
|
||||
"Failed to get AWS credentials");
|
||||
}
|
||||
},
|
||||
true, jobContext);
|
||||
job->Start();
|
||||
}
|
||||
|
||||
AZStd::string AWSCognitoAuthorizationController::GetAuthenticationProviderId(const ProviderNameEnum& providerName)
|
||||
{
|
||||
switch (providerName)
|
||||
{
|
||||
case ProviderNameEnum::AWSCognitoIDP:
|
||||
{
|
||||
return m_settings->m_cognitoUserPoolId;
|
||||
}
|
||||
case ProviderNameEnum::LoginWithAmazon:
|
||||
{
|
||||
return m_settings->m_loginWithAmazonId;
|
||||
}
|
||||
case ProviderNameEnum::Google:
|
||||
{
|
||||
return m_settings->m_googleId;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AWSCognitoAuthorizationController::PersistLoginsAndRefreshAWSCredentials(const AuthenticationTokens& authenticationTokens)
|
||||
{
|
||||
// lock to persist logins as the object is shared with Native SDK. Native SDK reads logins and persists identity id and expiry.
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_persistentCognitoIdentityProviderMutex);
|
||||
|
||||
// Save logins to the shared persistent Cognito identity provider for authenticated authorization.
|
||||
// Append logins to existing map.
|
||||
Aws::Map<Aws::String, Aws::Auth::LoginAccessTokens> logins = m_persistentCognitoIdentityProvider->GetLogins();
|
||||
Aws::Auth::LoginAccessTokens tokens;
|
||||
tokens.accessToken = authenticationTokens.GetOpenIdToken().c_str();
|
||||
|
||||
logins[GetAuthenticationProviderId(authenticationTokens.GetProviderName()).c_str()] = tokens;
|
||||
m_persistentCognitoIdentityProvider->PersistLogins(logins);
|
||||
}
|
||||
|
||||
void AWSCognitoAuthorizationController::OnPasswordGrantSingleFactorSignInSuccess(const AWSClientAuth::AuthenticationTokens& authenticationTokens)
|
||||
{
|
||||
PersistLoginsAndRefreshAWSCredentials(authenticationTokens);
|
||||
}
|
||||
|
||||
void AWSCognitoAuthorizationController::OnPasswordGrantMultiFactorConfirmSignInSuccess(
|
||||
const AWSClientAuth::AuthenticationTokens& authenticationTokens)
|
||||
{
|
||||
PersistLoginsAndRefreshAWSCredentials(authenticationTokens);
|
||||
}
|
||||
|
||||
void AWSCognitoAuthorizationController::OnDeviceCodeGrantConfirmSignInSuccess(
|
||||
const AWSClientAuth::AuthenticationTokens& authenticationTokens)
|
||||
{
|
||||
PersistLoginsAndRefreshAWSCredentials(authenticationTokens);
|
||||
}
|
||||
|
||||
void AWSCognitoAuthorizationController::OnRefreshTokensSuccess(const AWSClientAuth::AuthenticationTokens& authenticationTokens)
|
||||
{
|
||||
PersistLoginsAndRefreshAWSCredentials(authenticationTokens);
|
||||
}
|
||||
|
||||
void AWSCognitoAuthorizationController::OnSignOut(const ProviderNameEnum& provideName)
|
||||
{
|
||||
// lock to persist logins as the object is shared with Native SDK.
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_persistentCognitoIdentityProviderMutex);
|
||||
m_persistentCognitoIdentityProvider->RemoveLogin(GetAuthenticationProviderId(provideName).c_str());
|
||||
}
|
||||
|
||||
int AWSCognitoAuthorizationController::GetCredentialHandlerOrder() const
|
||||
{
|
||||
return AWSCore::CredentialHandlerOrder::COGNITO_IDENITY_POOL_CREDENTIAL_HANDLER;
|
||||
}
|
||||
|
||||
std::shared_ptr<Aws::Auth::AWSCredentialsProvider> AWSCognitoAuthorizationController::GetCredentialsProvider()
|
||||
{
|
||||
// If logins are persisted default to using authenticated credentials provide.
|
||||
// Check authenticated credentials to verify persisted logins are valid.
|
||||
if (HasPersistedLogins())
|
||||
{
|
||||
// lock to protect logins being persisted.
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_persistentCognitoIdentityProviderMutex);
|
||||
if (!m_cognitoCachingCredentialsProvider->GetAWSCredentials().IsEmpty())
|
||||
{
|
||||
return m_cognitoCachingCredentialsProvider;
|
||||
}
|
||||
}
|
||||
|
||||
// lock to protect getting identity id.
|
||||
AZStd::lock_guard<AZStd::mutex> lock(m_persistentAnonymousCognitoIdentityProviderMutex);
|
||||
// Check anonymous credentials as they are optional settings in Cognito Identity pool.
|
||||
if (!m_cognitoCachingAnonymousCredentialsProvider->GetAWSCredentials().IsEmpty())
|
||||
{
|
||||
AZ_Warning("AWSCognitoAuthorizationCredentialHandler", true, "No logins found. Using Anonymous credential provider");
|
||||
return m_cognitoCachingAnonymousCredentialsProvider;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace AWSClientAuth
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Jobs/JobFunction.h>
|
||||
|
||||
#include <UserManagement/AWSCognitoUserManagementController.h>
|
||||
#include <AWSClientAuthBus.h>
|
||||
#include <AWSCoreBus.h>
|
||||
|
||||
#include <aws/core/utils/Outcome.h>
|
||||
#include <aws/core/utils/memory/stl/AWSVector.h>
|
||||
#include <aws/cognito-idp/model/SignUpRequest.h>
|
||||
#include <aws/cognito-idp/CognitoIdentityProviderClient.h>
|
||||
#include <aws/cognito-idp/model/SignUpResult.h>
|
||||
#include <aws/cognito-idp/model/ConfirmSignUpRequest.h>
|
||||
#include <aws/cognito-idp/model/ConfirmSignUpResult.h>
|
||||
#include <aws/cognito-idp/model/ConfirmSignUpRequest.h>
|
||||
#include <aws/cognito-idp/model/ConfirmSignUpResult.h>
|
||||
#include <aws/cognito-idp/model/AttributeType.h>
|
||||
#include <aws/cognito-idp/model/ForgotPasswordRequest.h>
|
||||
#include <aws/cognito-idp/model/ForgotPasswordResult.h>
|
||||
#include <aws/cognito-idp/model/ConfirmForgotPasswordRequest.h>
|
||||
#include <aws/cognito-idp/model/ConfirmForgotPasswordResult.h>
|
||||
#include <aws/cognito-idp/model/SetUserMFAPreferenceRequest.h>
|
||||
#include <aws/cognito-idp/model/SetUserMFAPreferenceResult.h>
|
||||
|
||||
namespace AWSClientAuth
|
||||
{
|
||||
constexpr char COGNITO_USER_POOL[] = "/AWS/CognitoUserPool";
|
||||
|
||||
AWSCognitoUserManagementController::AWSCognitoUserManagementController()
|
||||
{
|
||||
AZ::Interface<IAWSCognitoUserManagementRequests>::Register(this);
|
||||
AWSCognitoUserManagementRequestBus::Handler::BusConnect();
|
||||
|
||||
m_settings = AZStd::make_unique<AWSCognitoUserManagementSetting>();
|
||||
}
|
||||
|
||||
AWSCognitoUserManagementController::~AWSCognitoUserManagementController()
|
||||
{
|
||||
m_settings.reset();
|
||||
|
||||
AWSCognitoUserManagementRequestBus::Handler::BusDisconnect();
|
||||
AZ::Interface<IAWSCognitoUserManagementRequests>::Unregister(this);
|
||||
}
|
||||
|
||||
bool AWSCognitoUserManagementController::Initialize(const AZStd::string& settingsRegistryPath)
|
||||
{
|
||||
AZStd::unique_ptr<AZ::SettingsRegistryInterface> settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
|
||||
|
||||
if (!settingsRegistry->MergeSettingsFile(settingsRegistryPath, AZ::SettingsRegistryInterface::Format::JsonMergePatch))
|
||||
{
|
||||
AZ_Error("AWSCognitoUserManagementController", true, "Failed to merge settings file for path %s", settingsRegistryPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!settingsRegistry->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), COGNITO_USER_POOL))
|
||||
{
|
||||
AZ_Error("AWSCognitoUserManagementController", true, "Failed to get settings object for path %s", COGNITO_USER_POOL);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Call Cognito user pool sign up using email. Confirmation code sent to the email set.
|
||||
// Refer https://docs.aws.amazon.com/cognito/latest/developerguide/signing-up-users-in-your-app.html
|
||||
void AWSCognitoUserManagementController::EmailSignUpAsync(const AZStd::string& username, const AZStd::string& password, const AZStd::string& email)
|
||||
{
|
||||
std::shared_ptr<Aws::CognitoIdentityProvider::CognitoIdentityProviderClient> cognitoIdentityProviderClient =
|
||||
AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIDPClient();
|
||||
|
||||
AZ::JobContext* jobContext = nullptr;
|
||||
AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext);
|
||||
|
||||
AZ::Job* emailSignUpJob = AZ::CreateJobFunction([this, cognitoIdentityProviderClient, username, password, email]()
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::SignUpRequest signUpRequest;
|
||||
signUpRequest.SetClientId(m_settings->m_appClientId.c_str());
|
||||
signUpRequest.SetUsername(username.c_str());
|
||||
signUpRequest.SetPassword(password.c_str());
|
||||
|
||||
Aws::Vector<Aws::CognitoIdentityProvider::Model::AttributeType> attributes;
|
||||
Aws::CognitoIdentityProvider::Model::AttributeType emailAttribute;
|
||||
emailAttribute.SetName("email");
|
||||
emailAttribute.SetValue(email.c_str());
|
||||
attributes.push_back(emailAttribute);
|
||||
signUpRequest.SetUserAttributes(attributes);
|
||||
|
||||
Aws::CognitoIdentityProvider::Model::SignUpOutcome signUpOutcome{ cognitoIdentityProviderClient->SignUp(signUpRequest) };
|
||||
if (signUpOutcome.IsSuccess())
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::SignUpResult signUpResult{ signUpOutcome.GetResult() };
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnEmailSignUpSuccess, signUpResult.GetUserSub().c_str());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Aws::Client::AWSError<Aws::CognitoIdentityProvider::CognitoIdentityProviderErrors> error = signUpOutcome.GetError();
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnEmailSignUpFail, error.GetMessage().c_str());
|
||||
}
|
||||
}, true, jobContext);
|
||||
emailSignUpJob->Start();
|
||||
}
|
||||
|
||||
void AWSCognitoUserManagementController::PhoneSignUpAsync(const AZStd::string& username, const AZStd::string& password, const AZStd::string& phoneNumber)
|
||||
{
|
||||
std::shared_ptr<Aws::CognitoIdentityProvider::CognitoIdentityProviderClient> cognitoIdentityProviderClient =
|
||||
AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIDPClient();
|
||||
|
||||
AZ::JobContext* jobContext = nullptr;
|
||||
AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext);
|
||||
|
||||
AZ::Job* phoneSignUpJob = AZ::CreateJobFunction([this, cognitoIdentityProviderClient, username, password, phoneNumber]()
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::SignUpRequest signUpRequest;
|
||||
signUpRequest.SetClientId(m_settings->m_appClientId.c_str());
|
||||
signUpRequest.SetUsername(username.c_str());
|
||||
signUpRequest.SetPassword(password.c_str());
|
||||
|
||||
Aws::Vector<Aws::CognitoIdentityProvider::Model::AttributeType> attributes;
|
||||
Aws::CognitoIdentityProvider::Model::AttributeType emailAttribute;
|
||||
emailAttribute.SetName("phone_number");
|
||||
emailAttribute.SetValue(phoneNumber.c_str());
|
||||
attributes.push_back(emailAttribute);
|
||||
signUpRequest.SetUserAttributes(attributes);
|
||||
|
||||
Aws::CognitoIdentityProvider::Model::SignUpOutcome signUpOutcome{ cognitoIdentityProviderClient->SignUp(signUpRequest) };
|
||||
if (signUpOutcome.IsSuccess())
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::SignUpResult signUpResult{ signUpOutcome.GetResult() };
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnPhoneSignUpSuccess, signUpResult.GetUserSub().c_str());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Aws::Client::AWSError<Aws::CognitoIdentityProvider::CognitoIdentityProviderErrors> error = signUpOutcome.GetError();
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnPhoneSignUpFail, error.GetMessage().c_str());
|
||||
}
|
||||
}, true, jobContext);
|
||||
phoneSignUpJob->Start();
|
||||
}
|
||||
|
||||
// Call Cognito user pool confirm sign up using code from email/phone.
|
||||
// Refer https://docs.aws.amazon.com/cognito/latest/developerguide/signing-up-users-in-your-app.html
|
||||
void AWSCognitoUserManagementController::ConfirmSignUpAsync(const AZStd::string& username, const AZStd::string& confirmationCode)
|
||||
{
|
||||
std::shared_ptr<Aws::CognitoIdentityProvider::CognitoIdentityProviderClient> cognitoIdentityProviderClient =
|
||||
AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIDPClient();
|
||||
|
||||
AZ::JobContext* jobContext = nullptr;
|
||||
AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext);
|
||||
|
||||
AZ::Job* confirmSignUpJob = AZ::CreateJobFunction([this, cognitoIdentityProviderClient, username, confirmationCode]()
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::ConfirmSignUpRequest confirmSignupRequest;
|
||||
confirmSignupRequest.SetClientId(m_settings->m_appClientId.c_str());
|
||||
confirmSignupRequest.SetUsername(username.c_str());
|
||||
confirmSignupRequest.SetConfirmationCode(confirmationCode.c_str());
|
||||
|
||||
Aws::CognitoIdentityProvider::Model::ConfirmSignUpOutcome confirmSignupOutcome{ cognitoIdentityProviderClient->ConfirmSignUp(confirmSignupRequest) };
|
||||
if (confirmSignupOutcome.IsSuccess())
|
||||
{
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnConfirmSignUpSuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
Aws::Client::AWSError<Aws::CognitoIdentityProvider::CognitoIdentityProviderErrors> error = confirmSignupOutcome.GetError();
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnConfirmSignUpFail, error.GetMessage().c_str());
|
||||
}
|
||||
}, true, jobContext);
|
||||
confirmSignUpJob->Start();
|
||||
}
|
||||
|
||||
void AWSCognitoUserManagementController::ForgotPasswordAsync(const AZStd::string& username)
|
||||
{
|
||||
std::shared_ptr<Aws::CognitoIdentityProvider::CognitoIdentityProviderClient> cognitoIdentityProviderClient =
|
||||
AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIDPClient();
|
||||
|
||||
AZ::JobContext* jobContext = nullptr;
|
||||
AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext);
|
||||
|
||||
AZ::Job* forgotPasswordJob = AZ::CreateJobFunction([this, cognitoIdentityProviderClient, username]()
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::ForgotPasswordRequest forgotPasswordRequest;
|
||||
forgotPasswordRequest.SetClientId(m_settings->m_appClientId.c_str());
|
||||
forgotPasswordRequest.SetUsername(username.c_str());
|
||||
|
||||
Aws::CognitoIdentityProvider::Model::ForgotPasswordOutcome forgotPasswordOutcome{ cognitoIdentityProviderClient->ForgotPassword(forgotPasswordRequest) };
|
||||
if (forgotPasswordOutcome.IsSuccess())
|
||||
{
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnForgotPasswordSuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
Aws::Client::AWSError<Aws::CognitoIdentityProvider::CognitoIdentityProviderErrors> error = forgotPasswordOutcome.GetError();
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnForgotPasswordFail, error.GetMessage().c_str());
|
||||
}
|
||||
}, true, jobContext);
|
||||
forgotPasswordJob->Start();
|
||||
}
|
||||
|
||||
void AWSCognitoUserManagementController::ConfirmForgotPasswordAsync(const AZStd::string& username, const AZStd::string& confirmationCode, const AZStd::string& newPassword)
|
||||
{
|
||||
std::shared_ptr<Aws::CognitoIdentityProvider::CognitoIdentityProviderClient> cognitoIdentityProviderClient =
|
||||
AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIDPClient();
|
||||
|
||||
AZ::JobContext* jobContext = nullptr;
|
||||
AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext);
|
||||
|
||||
AZ::Job* confirmForgotPasswordJob = AZ::CreateJobFunction([this, cognitoIdentityProviderClient, username, confirmationCode, newPassword]()
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::ConfirmForgotPasswordRequest confirmForgotPasswordRequest;
|
||||
confirmForgotPasswordRequest.SetClientId(m_settings->m_appClientId.c_str());
|
||||
confirmForgotPasswordRequest.SetUsername(username.c_str());
|
||||
confirmForgotPasswordRequest.SetConfirmationCode(confirmationCode.c_str());
|
||||
confirmForgotPasswordRequest.SetPassword(newPassword.c_str());
|
||||
|
||||
Aws::CognitoIdentityProvider::Model::ConfirmForgotPasswordOutcome confirmForgotPasswordOutcome{ cognitoIdentityProviderClient->ConfirmForgotPassword(confirmForgotPasswordRequest) };
|
||||
if (confirmForgotPasswordOutcome.IsSuccess())
|
||||
{
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnConfirmForgotPasswordSuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
Aws::Client::AWSError<Aws::CognitoIdentityProvider::CognitoIdentityProviderErrors> error = confirmForgotPasswordOutcome.GetError();
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnConfirmForgotPasswordFail, error.GetMessage().c_str());
|
||||
}
|
||||
}, true, jobContext);
|
||||
confirmForgotPasswordJob->Start();
|
||||
}
|
||||
|
||||
void AWSCognitoUserManagementController::EnableMFAAsync(const AZStd::string& accessToken)
|
||||
{
|
||||
std::shared_ptr<Aws::CognitoIdentityProvider::CognitoIdentityProviderClient> cognitoIdentityProviderClient =
|
||||
AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIDPClient();
|
||||
|
||||
AZ::JobContext* jobContext = nullptr;
|
||||
AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext);
|
||||
|
||||
AZ::Job* enableMFAJob = AZ::CreateJobFunction([this, cognitoIdentityProviderClient, accessToken]()
|
||||
{
|
||||
Aws::CognitoIdentityProvider::Model::SetUserMFAPreferenceRequest confirmForgotPasswordRequest;
|
||||
Aws::CognitoIdentityProvider::Model::SMSMfaSettingsType settings;
|
||||
settings.SetEnabled(true);
|
||||
settings.SetPreferredMfa(true);
|
||||
confirmForgotPasswordRequest.SetSMSMfaSettings(settings);
|
||||
confirmForgotPasswordRequest.SetAccessToken(accessToken.c_str());
|
||||
|
||||
Aws::CognitoIdentityProvider::Model::SetUserMFAPreferenceOutcome setUserMFAPreferenceOutcome{ cognitoIdentityProviderClient->SetUserMFAPreference(confirmForgotPasswordRequest) };
|
||||
if (setUserMFAPreferenceOutcome.IsSuccess())
|
||||
{
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnEnableMFASuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
Aws::Client::AWSError<Aws::CognitoIdentityProvider::CognitoIdentityProviderErrors> error = setUserMFAPreferenceOutcome.GetError();
|
||||
AWSCognitoUserManagementNotificationBus::Broadcast(&AWSCognitoUserManagementNotifications::OnEnableMFAFail, error.GetMessage().c_str());
|
||||
}
|
||||
}, true, jobContext);
|
||||
enableMFAJob->Start();
|
||||
}
|
||||
} // namespace AWSClientAuth
|
||||
Reference in New Issue
Block a user