BearerTokenAuthenticationPolicy to use shared_lock in case no refresh is needed (#5188)
* `BearerTokenAuthenticationPolicy` to use shared_lock in case no refresh is needed * Copy constructor * Update bearer_token_authentication_policy.cpp --------- Co-authored-by: Anton Kolesnyk <antkmsft@users.noreply.github.com>
This commit is contained in:
parent
b997e76e0d
commit
135e746243
@ -13,6 +13,8 @@
|
||||
|
||||
### Other Changes
|
||||
|
||||
- [[#4756]] (https://github.com/Azure/azure-sdk-for-cpp/issues/4756) `BearerTokenAuthenticationPolicy` now uses shared mutex lock for read operations.
|
||||
|
||||
## 1.11.0-beta.2 (2023-11-02)
|
||||
|
||||
### Features Added
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <shared_mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@ -549,7 +550,7 @@ namespace Azure { namespace Core { namespace Http { namespace Policies {
|
||||
Credentials::TokenRequestContext m_tokenRequestContext;
|
||||
|
||||
mutable Credentials::AccessToken m_accessToken;
|
||||
mutable std::mutex m_accessTokenMutex;
|
||||
mutable std::shared_timed_mutex m_accessTokenMutex;
|
||||
mutable Credentials::TokenRequestContext m_accessTokenContext;
|
||||
|
||||
public:
|
||||
@ -581,6 +582,9 @@ namespace Azure { namespace Core { namespace Http { namespace Policies {
|
||||
BearerTokenAuthenticationPolicy(BearerTokenAuthenticationPolicy const& other)
|
||||
: BearerTokenAuthenticationPolicy(other.m_credential, other.m_tokenRequestContext)
|
||||
{
|
||||
std::shared_lock<std::shared_timed_mutex> readLock(other.m_accessTokenMutex);
|
||||
m_accessToken = other.m_accessToken;
|
||||
m_accessTokenContext = other.m_accessTokenContext;
|
||||
}
|
||||
|
||||
void operator=(BearerTokenAuthenticationPolicy const&) = delete;
|
||||
|
||||
@ -61,21 +61,49 @@ bool BearerTokenAuthenticationPolicy::AuthorizeRequestOnChallenge(
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool TokenNeedsRefresh(
|
||||
Azure::Core::Credentials::AccessToken const& cachedToken,
|
||||
Azure::Core::Credentials::TokenRequestContext const& cachedTokenRequestContext,
|
||||
Azure::DateTime const& currentTime,
|
||||
Azure::Core::Credentials::TokenRequestContext const& newTokenRequestContext)
|
||||
{
|
||||
return newTokenRequestContext.TenantId != cachedTokenRequestContext.TenantId
|
||||
|| newTokenRequestContext.Scopes != cachedTokenRequestContext.Scopes
|
||||
|| currentTime > (cachedToken.ExpiresOn - newTokenRequestContext.MinimumExpiration);
|
||||
}
|
||||
|
||||
void ApplyBearerToken(
|
||||
Azure::Core::Http::Request& request,
|
||||
Azure::Core::Credentials::AccessToken const& token)
|
||||
{
|
||||
request.SetHeader("authorization", "Bearer " + token.Token);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void BearerTokenAuthenticationPolicy::AuthenticateAndAuthorizeRequest(
|
||||
Request& request,
|
||||
Credentials::TokenRequestContext const& tokenRequestContext,
|
||||
Context const& context) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_accessTokenMutex);
|
||||
DateTime const currentTime = std::chrono::system_clock::now();
|
||||
|
||||
if (tokenRequestContext.TenantId != m_accessTokenContext.TenantId
|
||||
|| tokenRequestContext.Scopes != m_accessTokenContext.Scopes
|
||||
|| std::chrono::system_clock::now()
|
||||
> (m_accessToken.ExpiresOn - tokenRequestContext.MinimumExpiration))
|
||||
{
|
||||
std::shared_lock<std::shared_timed_mutex> readLock(m_accessTokenMutex);
|
||||
if (!TokenNeedsRefresh(m_accessToken, m_accessTokenContext, currentTime, tokenRequestContext))
|
||||
{
|
||||
ApplyBearerToken(request, m_accessToken);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_lock<std::shared_timed_mutex> writeLock(m_accessTokenMutex);
|
||||
// Check if token needs refresh for the second time in case another thread has just updated it.
|
||||
if (TokenNeedsRefresh(m_accessToken, m_accessTokenContext, currentTime, tokenRequestContext))
|
||||
{
|
||||
m_accessToken = m_credential->GetToken(tokenRequestContext, context);
|
||||
m_accessTokenContext = tokenRequestContext;
|
||||
}
|
||||
|
||||
request.SetHeader("authorization", "Bearer " + m_accessToken.Token);
|
||||
ApplyBearerToken(request, m_accessToken);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user