GoogleAuthenticationProvider.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/std/smart_ptr/make_shared.h>
  9. #include <Authentication/GoogleAuthenticationProvider.h>
  10. #include <Authentication/AuthenticationProviderBus.h>
  11. #include <Authentication/OAuthConstants.h>
  12. #include <HttpRequestor/HttpRequestorBus.h>
  13. #include <HttpRequestor/HttpTypes.h>
  14. #include <aws/core/http/HttpResponse.h>
  15. namespace AWSClientAuth
  16. {
  17. constexpr char GoogleSettingsPath[] = "/AWS/Google";
  18. constexpr char GoogleVerificationUrlResponseKey[] = "verification_url";
  19. GoogleAuthenticationProvider::GoogleAuthenticationProvider()
  20. {
  21. m_settings = AZStd::make_unique<GoogleProviderSetting>();
  22. }
  23. GoogleAuthenticationProvider::~GoogleAuthenticationProvider()
  24. {
  25. m_settings.reset();
  26. }
  27. bool GoogleAuthenticationProvider::Initialize()
  28. {
  29. AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
  30. if (!settingsRegistry)
  31. {
  32. AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to load the setting registry");
  33. return false;
  34. }
  35. if (!settingsRegistry->GetObject(m_settings.get(), azrtti_typeid(m_settings.get()), GoogleSettingsPath))
  36. {
  37. AZ_Warning("AWSCognitoAuthenticationProvider", false, "Failed to get Google settings object for path %s", GoogleSettingsPath);
  38. return false;
  39. }
  40. return true;
  41. }
  42. void GoogleAuthenticationProvider::PasswordGrantSingleFactorSignInAsync(const AZStd::string& username, const AZStd::string& password)
  43. {
  44. AZ_UNUSED(username);
  45. AZ_UNUSED(password);
  46. AZ_Assert(false, "Not supported");
  47. }
  48. void GoogleAuthenticationProvider::PasswordGrantMultiFactorSignInAsync(const AZStd::string& username, const AZStd::string& password)
  49. {
  50. AZ_UNUSED(username);
  51. AZ_UNUSED(password);
  52. AZ_Assert(false, "Not supported");
  53. }
  54. void GoogleAuthenticationProvider::PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& username, const AZStd::string& confirmationCode)
  55. {
  56. AZ_UNUSED(username);
  57. AZ_UNUSED(confirmationCode);
  58. AZ_Assert(false, "Not supported");
  59. }
  60. // Call Google authentication provider device code end point.
  61. // Refer https://developers.google.com/identity/protocols/oauth2/limited-input-device#step-1:-request-device-and-user-codes.
  62. void GoogleAuthenticationProvider::DeviceCodeGrantSignInAsync()
  63. {
  64. AZStd::string body = AZStd::string::format("%s=%s&%s=%s", OAuthClientIdBodyKey, m_settings->m_appClientId.c_str()
  65. , OAuthScopeBodyKey, OAuthScopeBodyValue);
  66. // Set headers and body for device sign in http requests.
  67. AZStd::map<AZStd::string, AZStd::string> headers;
  68. headers[OAuthContentTypeHeaderKey] = OAuthContentTypeHeaderValue;
  69. headers[OAuthContentLengthHeaderKey] = AZStd::to_string(body.length());
  70. HttpRequestor::HttpRequestorRequestBus::Broadcast(&HttpRequestor::HttpRequestorRequests::AddRequestWithHeadersAndBody, m_settings->m_oAuthCodeURL
  71. , Aws::Http::HttpMethod::HTTP_POST, headers, body
  72. , [this](const Aws::Utils::Json::JsonView& jsonView, Aws::Http::HttpResponseCode responseCode)
  73. {
  74. if (responseCode == Aws::Http::HttpResponseCode::OK)
  75. {
  76. m_cachedDeviceCode = jsonView.GetString(OAuthDeviceCodeBodyKey).c_str();
  77. AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnDeviceCodeGrantSignInSuccess
  78. , jsonView.GetString(OAuthUserCodeResponseKey).c_str(), jsonView.GetString(GoogleVerificationUrlResponseKey).c_str()
  79. , jsonView.GetInteger(OAuthExpiresInResponseKey));
  80. }
  81. else
  82. {
  83. AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnDeviceCodeGrantSignInFail
  84. , jsonView.GetString(OAuthErrorResponseKey).c_str());
  85. }
  86. }
  87. );
  88. }
  89. // Call Google authentication provider OAuth tokens endpoint
  90. // Refer https://developers.google.com/identity/protocols/oauth2/limited-input-device#step-4:-poll-googles-authorization-server.
  91. void GoogleAuthenticationProvider::DeviceCodeGrantConfirmSignInAsync()
  92. {
  93. // Set headers and body for device confirm sign in http requests.
  94. AZStd::map<AZStd::string, AZStd::string> headers;
  95. AZStd::string body = AZStd::string::format("%s=%s&%s=%s&%s=%s&%s=%s", OAuthClientIdBodyKey, m_settings->m_appClientId.c_str()
  96. , OAuthClientSecretBodyKey, m_settings->m_clientSecret.c_str(), OAuthDeviceCodeBodyKey, m_cachedDeviceCode.c_str()
  97. , OAuthGrantTypeBodyKey, m_settings->m_grantType.c_str());
  98. headers[OAuthContentTypeHeaderKey] = OAuthContentTypeHeaderValue;
  99. headers[OAuthContentLengthHeaderKey] = AZStd::to_string(body.length());
  100. HttpRequestor::HttpRequestorRequestBus::Broadcast(&HttpRequestor::HttpRequestorRequests::AddRequestWithHeadersAndBody, m_settings->m_oAuthTokensURL
  101. , Aws::Http::HttpMethod::HTTP_POST, headers, body
  102. , [this](const Aws::Utils::Json::JsonView& jsonView, Aws::Http::HttpResponseCode responseCode)
  103. {
  104. if (responseCode == Aws::Http::HttpResponseCode::OK)
  105. {
  106. UpdateTokens(jsonView);
  107. AuthenticationProviderNotificationBus::Broadcast(
  108. &AuthenticationProviderNotifications::OnDeviceCodeGrantConfirmSignInSuccess,
  109. AuthenticationTokens(jsonView.GetString(OAuthAccessTokenResponseKey).c_str(),
  110. jsonView.GetString(OAuthRefreshTokenResponseKey).c_str(), jsonView.GetString(OAuthIdTokenResponseKey).c_str(),
  111. ProviderNameEnum::Google, jsonView.GetInteger(OAuthExpiresInResponseKey)));
  112. }
  113. else
  114. {
  115. AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnDeviceCodeGrantConfirmSignInFail
  116. , jsonView.GetString(OAuthErrorResponseKey).c_str());
  117. }
  118. }
  119. );
  120. }
  121. // Call Google authentication provider OAuth tokens endpoint
  122. // Refer https://developers.google.com/identity/protocols/oauth2/limited-input-device#offline.
  123. void GoogleAuthenticationProvider::RefreshTokensAsync()
  124. {
  125. AZStd::map<AZStd::string, AZStd::string> headers;
  126. AZStd::string body = AZStd::string::format("%s=%s&%s=%s&%s=%s&%s=%s", OAuthClientIdBodyKey, m_settings->m_appClientId.c_str()
  127. , OAuthClientSecretBodyKey, m_settings->m_clientSecret.c_str()
  128. , OAuthGrantTypeBodyKey, OAuthRefreshTokenBodyValue, OAuthRefreshTokenBodyKey, m_authenticationTokens.GetRefreshToken().c_str());
  129. headers[OAuthContentTypeHeaderKey] = OAuthContentTypeHeaderValue;
  130. headers[OAuthContentLengthHeaderKey] = AZStd::to_string(body.length());
  131. HttpRequestor::HttpRequestorRequestBus::Broadcast(&HttpRequestor::HttpRequestorRequests::AddRequestWithHeadersAndBody, m_settings->m_oAuthTokensURL
  132. , Aws::Http::HttpMethod::HTTP_POST, headers, body
  133. , [this](const Aws::Utils::Json::JsonView& jsonView, Aws::Http::HttpResponseCode responseCode)
  134. {
  135. if (responseCode == Aws::Http::HttpResponseCode::OK)
  136. {
  137. UpdateTokens(jsonView);
  138. AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensSuccess,
  139. AuthenticationTokens(jsonView.GetString(OAuthAccessTokenResponseKey).c_str(),
  140. jsonView.GetString(OAuthRefreshTokenResponseKey).c_str() ,jsonView.GetString(OAuthIdTokenResponseKey).c_str(),
  141. ProviderNameEnum::Google, jsonView.GetInteger(OAuthExpiresInResponseKey)));
  142. }
  143. else
  144. {
  145. AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensFail
  146. , jsonView.GetString(OAuthErrorResponseKey).c_str());
  147. }
  148. }
  149. );
  150. }
  151. void GoogleAuthenticationProvider::UpdateTokens(const Aws::Utils::Json::JsonView& jsonView)
  152. {
  153. // Storing authentication tokens in memory can be a security concern. The access token and id token are not actually in use by
  154. // the authentication provider and shouldn't be stored in the member variable.
  155. m_authenticationTokens = AuthenticationTokens("",
  156. jsonView.GetString(OAuthRefreshTokenResponseKey).c_str() ,"", ProviderNameEnum::Google
  157. , jsonView.GetInteger(OAuthExpiresInResponseKey));
  158. }
  159. } // namespace AWSClientAuth