From fd3ba9a8d5a3cb8990bd0bfbfec7545eabea2cbb Mon Sep 17 00:00:00 2001 From: Soumava Bera Date: Fri, 17 Jan 2025 16:24:22 -0500 Subject: [PATCH 1/2] pending tests --- cmake/sdksCommon.cmake | 1 + tests/android-unified-tests/CMakeLists.txt | 1 + .../CMakeLists.txt | 48 +++++ .../OperationTest.cpp | 194 ++++++++++++++++++ .../RunTests.cpp | 30 +++ 5 files changed, 274 insertions(+) create mode 100644 tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/CMakeLists.txt create mode 100644 tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/OperationTest.cpp create mode 100644 tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/RunTests.cpp diff --git a/cmake/sdksCommon.cmake b/cmake/sdksCommon.cmake index 7eb26f8e40b..f3addce30f5 100644 --- a/cmake/sdksCommon.cmake +++ b/cmake/sdksCommon.cmake @@ -87,6 +87,7 @@ list(APPEND HIGH_LEVEL_SDK_LIST "text-to-speech") set(SDK_TEST_PROJECT_LIST "") list(APPEND SDK_TEST_PROJECT_LIST "cloudfront:tests/aws-cpp-sdk-cloudfront-integration-tests") list(APPEND SDK_TEST_PROJECT_LIST "cognito-identity:tests/aws-cpp-sdk-cognitoidentity-integration-tests") +list(APPEND SDK_TEST_PROJECT_LIST "cognito-idp:tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests") list(APPEND SDK_TEST_PROJECT_LIST "core:tests/aws-cpp-sdk-core-tests") list(APPEND SDK_TEST_PROJECT_LIST "dynamodb:tests/aws-cpp-sdk-dynamodb-integration-tests") list(APPEND SDK_TEST_PROJECT_LIST "dynamodb:tests/aws-cpp-sdk-dynamodb-unit-tests") diff --git a/tests/android-unified-tests/CMakeLists.txt b/tests/android-unified-tests/CMakeLists.txt index 382b291062f..b6de1b3f4be 100644 --- a/tests/android-unified-tests/CMakeLists.txt +++ b/tests/android-unified-tests/CMakeLists.txt @@ -19,6 +19,7 @@ file(GLOB SQS_SRC "${AWS_NATIVE_SDK_ROOT}/aws-cpp-sdk-sqs-integration-tests/Queu file(GLOB S3_SRC "${AWS_NATIVE_SDK_ROOT}/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp") file(GLOB LAMBDA_SRC "${AWS_NATIVE_SDK_ROOT}/aws-cpp-sdk-lambda-integration-tests/FunctionTest.cpp") file(GLOB COGNITO_IDENTITY_IDENTITY_POOL_SRC "${AWS_NATIVE_SDK_ROOT}/aws-cpp-sdk-cognitoidentity-integration-tests/IdentityPoolOperationTest.cpp") +file(GLOB COGNITO_IDENTITY_IDENTITY_POOL_SRC "${AWS_NATIVE_SDK_ROOT}/aws-cpp-sdk-cognitoidentityprovider-integration-tests/OperationTest.cpp") file(GLOB TRANSFER_SRC "${AWS_NATIVE_SDK_ROOT}/aws-cpp-sdk-transfer-tests/TransferTests.cpp") file(GLOB IDENTITY_MANAGEMENT_SRC "${AWS_NATIVE_SDK_ROOT}/aws-cpp-sdk-identity-management-tests/auth/*.cpp") file(GLOB ENCRYPTION_TESTS_SRC "${AWS_NATIVE_SDK_ROOT}/aws-cpp-sdk-s3-encryption-tests/CryptoModulesTest.cpp" diff --git a/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/CMakeLists.txt b/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/CMakeLists.txt new file mode 100644 index 00000000000..2dbec1015f3 --- /dev/null +++ b/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/CMakeLists.txt @@ -0,0 +1,48 @@ +add_project(aws-cpp-sdk-cognitoidentityprovider-integration-tests + "Tests for the AWS Cognito Identity C++ SDK" + #aws-cpp-sdk-access-management + aws-cpp-sdk-cognito-idp + #aws-cpp-sdk-iam + testing-resources + aws-cpp-sdk-core +) + +# Headers are included in the source so that they show up in Visual Studio. +# They are included elsewhere for consistency. + +file(GLOB AWS_COGNITO_SRC + "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" +) + +file(GLOB AWS_COGNITO_INTEGRATION_TESTS_SRC + ${AWS_COGNITO_SRC} +) + +if(MSVC AND BUILD_SHARED_LIBS) + add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1) +endif() + +enable_testing() + +if(PLATFORM_ANDROID AND BUILD_SHARED_LIBS) + add_library(${PROJECT_NAME} ${AWS_COGNITO_INTEGRATION_TESTS_SRC}) +else() + add_executable(${PROJECT_NAME} ${AWS_COGNITO_INTEGRATION_TESTS_SRC}) +endif() + +set_compiler_flags(${PROJECT_NAME}) +set_compiler_warnings(${PROJECT_NAME}) + +find_package(OpenSSL REQUIRED) +# Include directories for OpenSSL headers +include_directories(${OPENSSL_INCLUDE_DIR}) + +target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBS}) + + + +if(MSVC AND BUILD_SHARED_LIBS) + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS + "/DELAYLOAD:aws-cpp-sdk-access-management.dll /DELAYLOAD:aws-cpp-sdk-cognito-idp /DELAYLOAD:aws-cpp-sdk-iam /DELAYLOAD:aws-cpp-sdk-core.dll") + target_link_libraries(${PROJECT_NAME} delayimp.lib) +endif() diff --git a/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/OperationTest.cpp b/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/OperationTest.cpp new file mode 100644 index 00000000000..c32d9af9c89 --- /dev/null +++ b/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/OperationTest.cpp @@ -0,0 +1,194 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +using namespace Aws::CognitoIdentityProvider; +using namespace Aws::CognitoIdentityProvider::Model; +using namespace Aws::Client; +using namespace Aws::Region; + +#define TEST_POOL_PREFIX "IntegrationTest_" + +namespace +{ +static const char* ALLOCATION_TAG = "IdentityProviderOperationTest"; + + +class IdentityProviderOperationTest : public ::testing::Test +{ +public: + IdentityProviderOperationTest() : + client(nullptr) + {} + + std::shared_ptr client; + Aws::String testTrace; + +protected: + + const Aws::String m_clientName{"testClient"}; + + void SetUp() + { + Aws::Client::ClientConfiguration config; + config.region = AWS_TEST_REGION; + + //TODO: move this over to profile config file. + client = Aws::MakeShared(ALLOCATION_TAG, config); + } + + void TearDown() + { + client = nullptr; + if (::testing::Test::HasFailure()) + { + std::cout << "Test traces: " << testTrace << "\n"; + } + testTrace.erase(); + } + + + void registerUser(const Aws::String& username, const Aws::String& password) + { + // Set up the request for creating a new User Pool Client + Aws::CognitoIdentityProvider::Model::SignUpRequest request; + request.SetClientId(m_clientName); + request.SetUsername(username); + request.SetPassword(password); + + auto outcome = client->SignUp(request); + ASSERT_TRUE(outcome.IsSuccess()); + if (outcome.IsSuccess()) + { + std::cout << "User registered successfully." << std::endl; + std::cout << "User confirmed: " << (outcome.GetResult().GetUserConfirmed() ? "Yes" : "No") << std::endl; + std::cout << "User sub: " << outcome.GetResult().GetUserSub() << std::endl; + + + } + } + + CreateUserPoolClientOutcome createPoolClient() + { + // Set up the request for creating a new User Pool Client + Aws::CognitoIdentityProvider::Model::CreateUserPoolClientRequest request; + request.SetUserPoolId("test-pool-id"); + request.SetClientName("testClient"); + + request.SetGenerateSecret(true); // If you need a secret for your client + Aws::Vector authFlows{Aws::CognitoIdentityProvider::Model::ExplicitAuthFlowsType::ALLOW_USER_SRP_AUTH}; + request.SetExplicitAuthFlows(authFlows); + + // Make the call to create the user pool client + auto outcome = client->CreateUserPoolClient(request); + ASSERT_TRUE(outcome.IsSuccess()); + if (outcome.IsSuccess()) + { + std::cout << "User Pool Client created successfully." << std::endl; + std::cout << "Client ID: " << outcome.GetResult().GetUserPoolClient().GetClientId() << std::endl; + if (request.GetGenerateSecret()) + { + std::cout << "Client Secret: " << outcome.GetResult().GetUserPoolClient().GetClientSecret() << std::endl; + } + } + return outcome; + } + + void deletePoolClient() + { + // Set up the request for deleting the User Pool Client + Aws::CognitoIdentityProvider::Model::DeleteUserPoolClientRequest request; + request.SetUserPoolId("test-pool-id"); + request.SetClientId("testClient"); + + // Make the call to delete the user pool client + auto outcome = client->DeleteUserPoolClient(request); + ASSERT_TRUE(outcome.IsSuccess()); + if (outcome.IsSuccess()) + { + std::cout << "User Pool Client deleted successfully." << std::endl; + } + } + + +}; + + + + + + +TEST_F(IdentityProviderOperationTest, testSecret) +{ + auto outcome = createPoolClient(); + + + Aws::String ComputeSecretHash(const Aws::String &userPoolClientId, const Aws::String &userPoolClientSecret, const Aws::String &userName) + { + const auto secret = userPoolClientSecret; + const auto message = userName + userPoolClientId; + + unsigned char * digest = HMAC(EVP_sha256(), + secret.c_str(), static_cast(secret.length()), + reinterpret_cast(message.c_str()), + static_cast(message.length()), + NULL, NULL); + + char mdString[SHA256_DIGEST_LENGTH * 2 + 1]; + for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) + sprintf(&mdString[i*2], "%02x", (unsigned int)digest[i]); + + mdString[64] = '\0'; // null-terminate the string + + return Aws::String(mdString); + } + + + Aws::Map authParameters; + authParameters["USERNAME"] = "dummyuser"; // Replace with actual username + + // Compute SECRET_HASH if the client has a secret + const Aws::String clientId = outcome.GetResult().GetUserPoolClient().GetClientId(); // Client ID from previous step + const Aws::String clientSecret = outcome.GetResult().GetUserPoolClient().GetClientSecret(); // Client Secret if generated + authParameters["SECRET_HASH"] = ComputeSecretHash(clientId, clientSecret, "dummyuser"); + + // Note: SRP_A is part of the SRP protocol, you need to implement or use a library for SRP + // This is a placeholder for a correct SRP implementation: + authParameters["SRP_A"] = "dummy"; // Replace with actual SRP_A value + + Aws::CognitoIdentityProvider::Model::InitiateAuthRequest authRequest; + authRequest.SetClientId(clientId); // Client ID from when you created the client + authRequest.SetAuthFlow(Aws::CognitoIdentityProvider::Model::AuthFlowType::USER_SRP_AUTH); + authRequest.SetAuthParameters(authParameters); + + Aws::CognitoIdentityProvider::Model::InitiateAuthOutcome authResult = client->InitiateAuth( authRequest ); + + EXPECT_TRUE(authResult.IsSuccess()); + + + deletePoolClient(); +} + +} diff --git a/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/RunTests.cpp b/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/RunTests.cpp new file mode 100644 index 00000000000..06dc9951d5d --- /dev/null +++ b/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/RunTests.cpp @@ -0,0 +1,30 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + Aws::Testing::SetDefaultSigPipeHandler(); + Aws::SDKOptions options; + options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Debug; + AWS_BEGIN_MEMORY_TEST_EX(options, 1024, 128); + + Aws::Testing::InitPlatformTest(options); + Aws::Testing::ParseArgs(argc, argv); + + Aws::InitAPI(options); + ::testing::InitGoogleTest(&argc, argv); + int exitCode = RUN_ALL_TESTS(); + + Aws::ShutdownAPI(options); + AWS_END_MEMORY_TEST_EX; + Aws::Testing::ShutdownPlatformTest(options); + return exitCode; +} From 00f1858a884d18447f01f3485d21d38af424a3fc Mon Sep 17 00:00:00 2001 From: Soumava Bera Date: Mon, 3 Feb 2025 15:22:07 -0500 Subject: [PATCH 2/2] cognito-idp tests --- .../CMakeLists.txt | 6 +- .../OperationTest.cpp | 347 ++++++++++++++---- tools/scripts/run_integration_tests.py | 4 +- 3 files changed, 271 insertions(+), 86 deletions(-) diff --git a/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/CMakeLists.txt b/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/CMakeLists.txt index 2dbec1015f3..0319d478926 100644 --- a/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/CMakeLists.txt +++ b/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/CMakeLists.txt @@ -1,8 +1,6 @@ add_project(aws-cpp-sdk-cognitoidentityprovider-integration-tests - "Tests for the AWS Cognito Identity C++ SDK" - #aws-cpp-sdk-access-management + "Tests for the AWS Cognito IDP C++ SDK" aws-cpp-sdk-cognito-idp - #aws-cpp-sdk-iam testing-resources aws-cpp-sdk-core ) @@ -37,7 +35,7 @@ find_package(OpenSSL REQUIRED) # Include directories for OpenSSL headers include_directories(${OPENSSL_INCLUDE_DIR}) -target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBS}) +target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBS} OpenSSL::Crypto) diff --git a/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/OperationTest.cpp b/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/OperationTest.cpp index c32d9af9c89..f137a1cec43 100644 --- a/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/OperationTest.cpp +++ b/tests/aws-cpp-sdk-cognitoidentityprovider-integration-tests/OperationTest.cpp @@ -14,23 +14,32 @@ #include #include #include -#include #include +#include #include - +#include +#include +#include +#include +#include +#include #include #include #include #include #include -#include +#include +#include +#include +#include +#include + + using namespace Aws::CognitoIdentityProvider; using namespace Aws::CognitoIdentityProvider::Model; using namespace Aws::Client; using namespace Aws::Region; -#define TEST_POOL_PREFIX "IntegrationTest_" - namespace { static const char* ALLOCATION_TAG = "IdentityProviderOperationTest"; @@ -49,146 +58,322 @@ class IdentityProviderOperationTest : public ::testing::Test protected: const Aws::String m_clientName{"testClient"}; + Aws::String m_userPoolId; + Aws::String m_clientId; + const Aws::String m_username{"testUser"}; + Aws::String m_clientSecret; void SetUp() { Aws::Client::ClientConfiguration config; config.region = AWS_TEST_REGION; - //TODO: move this over to profile config file. client = Aws::MakeShared(ALLOCATION_TAG, config); + + //make user pool + m_userPoolId = createUserPool("TestPool"); + + ASSERT_TRUE(!m_userPoolId.empty()); + + //make client + if(!m_userPoolId.empty()) + { + auto ret = createPoolClient(m_userPoolId, m_clientName); + m_clientId = ret.first; + m_clientSecret = ret.second; + } + + ASSERT_TRUE(!m_clientId.empty()); + ASSERT_TRUE(!m_clientSecret.empty()); + + //create user + if(!m_userPoolId.empty() && !m_clientId.empty()) + { + ASSERT_TRUE(createUser(m_username, "Password123!", m_userPoolId)); + } + } void TearDown() { - client = nullptr; + + //delete user + if(!m_userPoolId.empty()) + { + ASSERT_TRUE(deleteUser(m_username, m_userPoolId)); + } + + // delete client + if(!m_userPoolId.empty() && !m_clientId.empty()) + { + ASSERT_TRUE(deletePoolClient(m_userPoolId, m_clientId)); + } + + // delete user pool + if(!m_userPoolId.empty()) + { + ASSERT_TRUE(deleteUserPool(m_userPoolId)); + } + + if (::testing::Test::HasFailure()) { - std::cout << "Test traces: " << testTrace << "\n"; + AWS_LOGSTREAM_DEBUG(ALLOCATION_TAG, "Test traces: " << testTrace); } testTrace.erase(); } + private: + Aws::String createUserPool(Aws::String poolName) + { + if(poolName.empty()) + { + return {}; + } + Aws::CognitoIdentityProvider::Model::CreateUserPoolRequest userPoolRequest; + userPoolRequest.SetPoolName(poolName); - void registerUser(const Aws::String& username, const Aws::String& password) - { - // Set up the request for creating a new User Pool Client - Aws::CognitoIdentityProvider::Model::SignUpRequest request; - request.SetClientId(m_clientName); - request.SetUsername(username); - request.SetPassword(password); + CreateUserPoolOutcome userPoolOutcome = client->CreateUserPool(userPoolRequest); + if (!userPoolOutcome.IsSuccess()) { + return {}; + } - auto outcome = client->SignUp(request); - ASSERT_TRUE(outcome.IsSuccess()); - if (outcome.IsSuccess()) + auto poolId = userPoolOutcome.GetResult().GetUserPool().GetId(); + AWS_LOGSTREAM_DEBUG(ALLOCATION_TAG, "Created User Pool with ID: " << poolId << " for pool name="<< poolName ); + return poolId; + } + + bool deleteUserPool(const Aws::String& poolId) + { + if (poolId.empty()) { - std::cout << "User registered successfully." << std::endl; - std::cout << "User confirmed: " << (outcome.GetResult().GetUserConfirmed() ? "Yes" : "No") << std::endl; - std::cout << "User sub: " << outcome.GetResult().GetUserSub() << std::endl; + return false; + } + Aws::CognitoIdentityProvider::Model::DeleteUserPoolRequest deletePoolRequest; + deletePoolRequest.SetUserPoolId(poolId); + auto deletePoolOutcome = client->DeleteUserPool(deletePoolRequest); + if (!deletePoolOutcome.IsSuccess()) { + AWS_LOGSTREAM_ERROR(ALLOCATION_TAG, "Failed to delete User Pool: " << deletePoolOutcome.GetError().GetMessage()); + } + else + { + AWS_LOGSTREAM_DEBUG(ALLOCATION_TAG, "Deleted User Pool with ID: " << poolId); + } + return deletePoolOutcome.IsSuccess(); + } + bool createUser(const Aws::String& username, const Aws::String& password, const Aws::String& userPoolId) + { + if (userPoolId.empty() || username.empty() || password.empty()) + { + return false; + } + + Aws::CognitoIdentityProvider::Model::AdminCreateUserRequest createUserRequest; + createUserRequest.SetUserPoolId(userPoolId); + createUserRequest.SetUsername(username); + + Aws::CognitoIdentityProvider::Model::AttributeType emailAttribute; + emailAttribute.SetName("email"); + emailAttribute.SetValue("testuser@example.com"); + createUserRequest.AddUserAttributes(emailAttribute); + + // Set a temporary password + createUserRequest.SetTemporaryPassword(password); + + // Suppress sending an email to the user + createUserRequest.SetMessageAction(Aws::CognitoIdentityProvider::Model::MessageActionType::SUPPRESS); + + auto outcome = client->AdminCreateUser(createUserRequest); + if (outcome.IsSuccess()) { + AWS_LOGSTREAM_DEBUG(ALLOCATION_TAG, "User created successfully: " << outcome.GetResult().GetUser().GetUsername()); + } else { + AWS_LOGSTREAM_ERROR(ALLOCATION_TAG, "Failed to create user: " << outcome.GetError().GetMessage()); } + + return outcome.IsSuccess(); } - CreateUserPoolClientOutcome createPoolClient() + bool deleteUser(const Aws::String& username, const Aws::String& userPoolId) + { + if (username.empty() || userPoolId.empty()) + { + return false; + } + + Aws::CognitoIdentityProvider::Model::AdminDeleteUserRequest deleteUserRequest; + deleteUserRequest.SetUserPoolId(userPoolId); + deleteUserRequest.SetUsername(username); + auto deleteUserOutcome = client->AdminDeleteUser(deleteUserRequest); + if (!deleteUserOutcome.IsSuccess()) { + AWS_LOGSTREAM_ERROR(ALLOCATION_TAG, "Failed to delete user: " << deleteUserOutcome.GetError().GetMessage()); + } + else + { + AWS_LOGSTREAM_DEBUG(ALLOCATION_TAG, "Deleted test user: " << username); + } + return deleteUserOutcome.IsSuccess(); + } + + + std::pair createPoolClient(const Aws::String& userPoolId, const Aws::String& clientName) { - // Set up the request for creating a new User Pool Client + if(userPoolId.empty() || clientName.empty()) + { + return {}; + } + Aws::CognitoIdentityProvider::Model::CreateUserPoolClientRequest request; - request.SetUserPoolId("test-pool-id"); - request.SetClientName("testClient"); + request.SetUserPoolId(userPoolId); + request.SetClientName(clientName); - request.SetGenerateSecret(true); // If you need a secret for your client - Aws::Vector authFlows{Aws::CognitoIdentityProvider::Model::ExplicitAuthFlowsType::ALLOW_USER_SRP_AUTH}; + request.SetGenerateSecret(true); + Aws::Vector authFlows{Aws::CognitoIdentityProvider::Model::ExplicitAuthFlowsType::ALLOW_USER_SRP_AUTH, Aws::CognitoIdentityProvider::Model::ExplicitAuthFlowsType::ALLOW_REFRESH_TOKEN_AUTH}; request.SetExplicitAuthFlows(authFlows); - // Make the call to create the user pool client - auto outcome = client->CreateUserPoolClient(request); - ASSERT_TRUE(outcome.IsSuccess()); + Aws::CognitoIdentityProvider::Model::CreateUserPoolClientOutcome outcome = client->CreateUserPoolClient(request); + Aws::String clientId, clientSecret; if (outcome.IsSuccess()) { - std::cout << "User Pool Client created successfully." << std::endl; - std::cout << "Client ID: " << outcome.GetResult().GetUserPoolClient().GetClientId() << std::endl; - if (request.GetGenerateSecret()) - { - std::cout << "Client Secret: " << outcome.GetResult().GetUserPoolClient().GetClientSecret() << std::endl; - } - } - return outcome; + clientId = outcome.GetResult().GetUserPoolClient().GetClientId(); + clientSecret = outcome.GetResult().GetUserPoolClient().GetClientSecret(); + AWS_LOGSTREAM_DEBUG(ALLOCATION_TAG, "User Pool Client created successfully. Client ID: " << clientId ); + } + return {clientId,clientSecret}; } - void deletePoolClient() + bool deletePoolClient(const Aws::String& userPoolId, const Aws::String& clientId) { // Set up the request for deleting the User Pool Client Aws::CognitoIdentityProvider::Model::DeleteUserPoolClientRequest request; - request.SetUserPoolId("test-pool-id"); - request.SetClientId("testClient"); + request.SetUserPoolId(userPoolId); + request.SetClientId(clientId); // Make the call to delete the user pool client auto outcome = client->DeleteUserPoolClient(request); - ASSERT_TRUE(outcome.IsSuccess()); if (outcome.IsSuccess()) { - std::cout << "User Pool Client deleted successfully." << std::endl; + AWS_LOGSTREAM_DEBUG(ALLOCATION_TAG, "User Pool Client deleted successfully."); } + return outcome.IsSuccess(); } - }; - - - - -TEST_F(IdentityProviderOperationTest, testSecret) +Aws::String ComputeSecretHash(const Aws::String &userPoolClientId, const Aws::String &clientSecret, const Aws::String &userName) { - auto outcome = createPoolClient(); + const auto message = userName + userPoolClientId; + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int len = 0; + + HMAC(EVP_sha256(), + clientSecret.c_str(), clientSecret.length(), + (unsigned char*)message.c_str(), message.length(), + hash, &len); + + // Base64 encode the hash + char encoded[128]; + EVP_EncodeBlock((unsigned char*)encoded, hash, len); + return std::string(encoded); +} +// https://github.com/aws/amazon-cognito-identity-js/blob/master/src/AuthenticationHelper.js#L22 +const char* initN = + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"; +// https://github.com/aws/amazon-cognito-identity-js/blob/master/src/AuthenticationHelper.js# +const char* generator = "2"; + + +class SRPClient { + public: + SRPClient(const std::string& N_hex, const std::string& g):N(BN_new()), g(BN_new()), a(nullptr), A(BN_new()), ctx(BN_CTX_new()) + { + //convert the hex string N_hex into a BIGNUM (OpenSSL's representation of large integers) + AWS_FATAL_ASSERT(BN_hex2bn(&N, N_hex.c_str())); + //convert the decimal string g into a BIGNUM + AWS_FATAL_ASSERT(BN_dec2bn(&this->g, g.c_str())); - Aws::String ComputeSecretHash(const Aws::String &userPoolClientId, const Aws::String &userPoolClientSecret, const Aws::String &userName) + generatePrivateKey(256); + } + ~SRPClient() { - const auto secret = userPoolClientSecret; - const auto message = userName + userPoolClientId; - - unsigned char * digest = HMAC(EVP_sha256(), - secret.c_str(), static_cast(secret.length()), - reinterpret_cast(message.c_str()), - static_cast(message.length()), - NULL, NULL); - - char mdString[SHA256_DIGEST_LENGTH * 2 + 1]; - for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) - sprintf(&mdString[i*2], "%02x", (unsigned int)digest[i]); + BN_free(N); + BN_free(g); + BN_free(a); + BN_free(A); + BN_CTX_free(ctx); + } - mdString[64] = '\0'; // null-terminate the string - - return Aws::String(mdString); + + private: + /* + N: A large prime number, a part of the SRP protocol. We use the N used + g: A generator used in the SRP protocol. + a: The client's private key. + A: The client's public key derived from the private key. + ctx: A context structure for OpenSSL's cryptographic operations. + + */ + BIGNUM* N{nullptr}; + BIGNUM* g{nullptr}; + BIGNUM* a{nullptr}; + BIGNUM* A{nullptr}; + BN_CTX* ctx{nullptr}; + + void generatePrivateKey(int bits) + { + a = BN_new(); + AWS_FATAL_ASSERT(BN_rand(a, bits, -1, 0)); } + public: + //Calculate the client’s public key A using the formula A = g^a (mod N) where a is the client’s private key and g is the generator + //We use OpenSSL function here + Aws::String calculateA() const + { + AWS_FATAL_ASSERT(BN_mod_exp(A, g, a, N, ctx)); + char* A_hex = BN_bn2hex(A); + Aws::String A_str(A_hex); + OPENSSL_free(A_hex); + return A_str; + } +}; - Aws::Map authParameters; - authParameters["USERNAME"] = "dummyuser"; // Replace with actual username - // Compute SECRET_HASH if the client has a secret - const Aws::String clientId = outcome.GetResult().GetUserPoolClient().GetClientId(); // Client ID from previous step - const Aws::String clientSecret = outcome.GetResult().GetUserPoolClient().GetClientSecret(); // Client Secret if generated - authParameters["SECRET_HASH"] = ComputeSecretHash(clientId, clientSecret, "dummyuser"); - // Note: SRP_A is part of the SRP protocol, you need to implement or use a library for SRP - // This is a placeholder for a correct SRP implementation: - authParameters["SRP_A"] = "dummy"; // Replace with actual SRP_A value +TEST_F(IdentityProviderOperationTest, testSecret) +{ + SRPClient srpclient(initN, generator); + Aws::Map authParameters; + authParameters["USERNAME"] = m_username; + authParameters["SECRET_HASH"] = ComputeSecretHash(m_clientId, m_clientSecret, m_username); + auto srpa = srpclient.calculateA(); + ASSERT_TRUE(!srpa.empty()); + authParameters["SRP_A"] = srpa; Aws::CognitoIdentityProvider::Model::InitiateAuthRequest authRequest; - authRequest.SetClientId(clientId); // Client ID from when you created the client + authRequest.SetClientId(m_clientId); authRequest.SetAuthFlow(Aws::CognitoIdentityProvider::Model::AuthFlowType::USER_SRP_AUTH); authRequest.SetAuthParameters(authParameters); - Aws::CognitoIdentityProvider::Model::InitiateAuthOutcome authResult = client->InitiateAuth( authRequest ); - EXPECT_TRUE(authResult.IsSuccess()); - - - deletePoolClient(); } } diff --git a/tools/scripts/run_integration_tests.py b/tools/scripts/run_integration_tests.py index 32783ffff01..31357af3a21 100644 --- a/tools/scripts/run_integration_tests.py +++ b/tools/scripts/run_integration_tests.py @@ -54,7 +54,9 @@ def main(): "aws-cpp-sdk-elasticfilesystem-integration-tests", "aws-cpp-sdk-rds-integration-tests", "aws-cpp-sdk-ec2-integration-tests", - "aws-cpp-sdk-timestream-query-integration-tests"] + "aws-cpp-sdk-timestream-query-integration-tests", + "aws-cpp-sdk-cognitoidentityprovider-integration-tests" + ] # check for existence of these binaries before adding them to tests # as they will not always be present