123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <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 LwaSettingsPath[] = "/AWS/LoginWithAmazon";
- constexpr char LwaVerificationUrlResponseKey[] = "verification_uri";
- LWAAuthenticationProvider::LWAAuthenticationProvider()
- {
- m_settings = AZStd::make_unique<LWAProviderSetting>();
- }
- LWAAuthenticationProvider::~LWAAuthenticationProvider()
- {
- m_settings.reset();
- }
- bool LWAAuthenticationProvider::Initialize()
- {
- AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
- if (!settingsRegistry)
- {
- AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to load the setting registry");
- return false;
- }
- if (!settingsRegistry->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), LwaSettingsPath))
- {
- AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to get login with Amazon settings object for path %s", LwaSettingsPath);
- return false;
- }
- return true;
- }
- void LWAAuthenticationProvider::PasswordGrantSingleFactorSignInAsync(const AZStd::string& username, const AZStd::string& password)
- {
- AZ_UNUSED(username);
- AZ_UNUSED(password);
- AZ_Assert(false, "Not supported");
- }
- void LWAAuthenticationProvider::PasswordGrantMultiFactorSignInAsync(const AZStd::string& username, const AZStd::string& password)
- {
- AZ_UNUSED(username);
- AZ_UNUSED(password);
- AZ_Assert(false, "Not supported");
- }
- void LWAAuthenticationProvider::PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& username, const AZStd::string& confirmationCode)
- {
- AZ_UNUSED(username);
- AZ_UNUSED(confirmationCode);
- AZ_Assert(false, "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", OAuthResponseTypeBodyKey, m_settings->m_responseType.c_str()
- , OAuthClientIdBodyKey, m_settings->m_appClientId.c_str(), OAuthScopeBodyKey, OAuthScopeBodyValue);
- AZStd::map<AZStd::string, AZStd::string> headers;
- headers[OAuthContentTypeHeaderKey] = OAuthContentTypeHeaderValue;
- headers[OAuthContentLengthHeaderKey] = 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(OAuthUserCodeResponseKey).c_str();
- m_cachedDeviceCode = jsonView.GetString(OAuthDeviceCodeBodyKey).c_str();
- AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnDeviceCodeGrantSignInSuccess
- , jsonView.GetString(OAuthUserCodeResponseKey).c_str()
- , jsonView.GetString(LwaVerificationUrlResponseKey).c_str()
- , jsonView.GetInteger(OAuthExpiresInResponseKey));
- }
- else
- {
- AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnDeviceCodeGrantSignInFail
- , jsonView.GetString(OAuthErrorResponseKey).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", OAuthUserCodeResponseKey, m_cachedUserCode.c_str()
- , OAuthGrantTypeBodyKey, m_settings->m_grantType.c_str(), OAuthDeviceCodeBodyKey, m_cachedDeviceCode.c_str());
- AZStd::map<AZStd::string, AZStd::string> headers;
- headers[OAuthContentTypeHeaderKey] = OAuthContentTypeHeaderValue;
- headers[OAuthContentLengthHeaderKey] = 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,
- AuthenticationTokens(jsonView.GetString(OAuthAccessTokenResponseKey).c_str(),
- jsonView.GetString(OAuthRefreshTokenResponseKey).c_str(), jsonView.GetString(OAuthAccessTokenResponseKey).c_str(),
- ProviderNameEnum::LoginWithAmazon, jsonView.GetInteger(OAuthExpiresInResponseKey)));
- 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", OAuthClientIdBodyKey, m_settings->m_appClientId.c_str(), OAuthGrantTypeBodyKey,
- OAuthRefreshTokenBodyValue, OAuthRefreshTokenBodyKey, m_authenticationTokens.GetRefreshToken().c_str());
- AZStd::map<AZStd::string, AZStd::string> headers;
- headers[OAuthContentTypeHeaderKey] = OAuthContentTypeHeaderValue;
- headers[OAuthContentLengthHeaderKey] = 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,
- AuthenticationTokens(jsonView.GetString(OAuthAccessTokenResponseKey).c_str(),
- jsonView.GetString(OAuthRefreshTokenResponseKey).c_str(), jsonView.GetString(OAuthAccessTokenResponseKey).c_str(),
- ProviderNameEnum::LoginWithAmazon, jsonView.GetInteger(OAuthExpiresInResponseKey)));
- }
- else
- {
- AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensFail
- , jsonView.GetString("error").c_str());
- }
- }
- );
- }
- void LWAAuthenticationProvider::UpdateTokens(const Aws::Utils::Json::JsonView& jsonView)
- {
- // Storing authentication tokens in memory can be a security concern. The access token and id token are not actually in use by
- // the authentication provider and shouldn't be stored in the member variable.
- m_authenticationTokens = AuthenticationTokens("", jsonView.GetString(OAuthRefreshTokenResponseKey).c_str(),
- "", ProviderNameEnum::LoginWithAmazon
- , jsonView.GetInteger(OAuthExpiresInResponseKey));
- }
- } // namespace AWSClientAuth
|