Add credential classes (#42)

This commit is contained in:
Anton Kolesnyk 2020-04-01 15:51:24 -07:00 committed by GitHub
parent a6bb11ed01
commit 9631e5978a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 300 additions and 1 deletions

View File

@ -9,6 +9,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
add_library (
azure-core
src/credentials/credentials
src/http/http
src/http/request
)

View File

@ -0,0 +1,104 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#pragma once
#include <chrono>
#include <mutex>
#include <string>
namespace azure
{
namespace core
{
namespace credentials
{
class Credential
{
virtual void SetScopes(std::string const& scopes) { (void)scopes; }
public:
class Internal;
virtual ~Credential() noexcept = default;
protected:
Credential() = default;
Credential(Credential const& other) = default;
Credential& operator=(Credential const& other) = default;
};
class TokenCredential : public Credential
{
struct Token
{
public:
std::string Scopes;
std::string TokenString;
std::chrono::system_clock::time_point ExpiresAt;
};
Token m_token;
mutable std::mutex m_tokenMutex;
void SetScopes(std::string const& scopes) override;
Token GetToken() const;
void SetToken(
std::string const& tokenString,
std::chrono::system_clock::time_point const& expiresAt);
void SetToken(Token const& token);
public:
class Internal;
protected:
TokenCredential() = default;
TokenCredential(TokenCredential const& other) : Credential(other), m_token(other.GetToken()) {}
TokenCredential& operator=(TokenCredential const& other)
{
this->SetToken(other.GetToken());
return *this;
}
};
class ClientSecretCredential : public TokenCredential
{
std::string m_tenantId;
std::string m_clientId;
std::string m_clientSecret;
public:
class Internal;
ClientSecretCredential(
std::string const& tenantId,
std::string const& clientId,
std::string const& clientSecret)
: m_tenantId(tenantId), m_clientId(clientId), m_clientSecret(clientSecret)
{
}
ClientSecretCredential(ClientSecretCredential const& other)
: TokenCredential(other), m_tenantId(other.m_tenantId), m_clientId(other.m_clientId),
m_clientSecret(other.m_clientSecret)
{
}
ClientSecretCredential& operator=(ClientSecretCredential const& other)
{
this->m_tenantId = other.m_tenantId;
this->m_clientId = other.m_clientId;
this->m_clientSecret = other.m_clientSecret;
return *this;
}
};
} // namespace credentials
} // namespace core
} // namespace azure

View File

@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#pragma once
#include <credentials/credentials.hpp>
namespace azure
{
namespace core
{
namespace credentials
{
class Credential::Internal
{
public:
static void SetScopes(Credential& credential, std::string const& scopes)
{
credential.SetScopes(scopes);
}
};
class TokenCredential::Internal
{
public:
static Token GetToken(TokenCredential const& credential)
{
return credential.GetToken();
}
static void SetToken(
TokenCredential& credential,
std::string const& token,
std::chrono::system_clock::time_point const& expiration)
{
credential.SetToken(token, expiration);
}
};
class ClientSecretCredential::Internal
{
public:
static std::string const& GetTenantId(ClientSecretCredential const& credential)
{
return credential.m_tenantId;
}
static std::string const& GetClientId(ClientSecretCredential const& credential)
{
return credential.m_clientId;
}
static std::string const& GetClientSecret(ClientSecretCredential const& credential)
{
return credential.m_clientSecret;
}
};
} // namespace credentials
} // namespace core
} // namespace azure

View File

@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include <credentials/credentials.hpp>
using namespace azure::core::credentials;
void TokenCredential::SetScopes(std::string const& scopes)
{
std::lock_guard<std::mutex> const lock(this->m_tokenMutex);
if (this->m_token.Scopes != scopes)
{
this->m_token = { scopes, {}, {} };
}
}
TokenCredential::Token TokenCredential::GetToken() const
{
std::lock_guard<std::mutex> const lock(this->m_tokenMutex);
return this->m_token;
}
void TokenCredential::SetToken(
std::string const& tokenString,
std::chrono::system_clock::time_point const& expiresAt)
{
this->SetToken({ this->m_token.Scopes, tokenString, expiresAt });
}
void TokenCredential::SetToken(Token const& token)
{
std::lock_guard<std::mutex> const lock(this->m_tokenMutex);
this->m_token = token;
}

View File

@ -3,6 +3,7 @@
#include <http/http.hpp>
#include <http/request.hpp>
#include <internal/credentials_internal.hpp>
#include "gtest/gtest.h"
@ -148,4 +149,101 @@ TEST(Http_Request, add_path)
[](std::string a, std::string b) { return a == b; },
req.getEncodedUrl(),
url + "/path/path2/path3?query=value");
}
}
TEST(Credential, ClientSecretCredential)
{
// Client Secret credential properties
credentials::ClientSecretCredential clientSecretCredential(
"tenantId", "clientId", "clientSecret");
EXPECT_EQ(
credentials::ClientSecretCredential::Internal::GetTenantId(clientSecretCredential),
"tenantId");
EXPECT_EQ(
credentials::ClientSecretCredential::Internal::GetClientId(clientSecretCredential),
"clientId");
EXPECT_EQ(
credentials::ClientSecretCredential::Internal::GetClientSecret(clientSecretCredential),
"clientSecret");
// Token credential
{
auto const emptyString = std::string();
auto const defaultTime = std::chrono::system_clock::time_point();
{
// Default values
{
auto const initialToken
= credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
EXPECT_EQ(initialToken.TokenString, emptyString);
EXPECT_EQ(initialToken.Scopes, emptyString);
EXPECT_EQ(initialToken.ExpiresAt, defaultTime);
}
{
// Set scopes
std::string const scopes = "scope";
{
credentials::Credential::Internal::SetScopes(clientSecretCredential, scopes);
auto const scopedToken
= credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
EXPECT_EQ(scopedToken.TokenString, emptyString);
EXPECT_EQ(scopedToken.Scopes, scopes);
EXPECT_EQ(scopedToken.ExpiresAt, defaultTime);
}
// Set token
{
std::string const token = "token";
auto const recentTime = std::chrono::system_clock::now();
{
credentials::TokenCredential::Internal::SetToken(
clientSecretCredential, token, recentTime);
auto const refreshedToken
= credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
EXPECT_EQ(refreshedToken.TokenString, token);
EXPECT_EQ(refreshedToken.Scopes, scopes);
EXPECT_EQ(refreshedToken.ExpiresAt, recentTime);
}
// Setting the very same scopes set earlier does not reset token
{
credentials::Credential::Internal::SetScopes(
clientSecretCredential, std::string(scopes));
auto const rescopedToken
= credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
EXPECT_EQ(rescopedToken.TokenString, token);
EXPECT_EQ(rescopedToken.Scopes, scopes);
EXPECT_EQ(rescopedToken.ExpiresAt, recentTime);
}
}
}
// Updating scopes does reset the token
{
std::string const another_scopes = "another_scopes";
credentials::Credential::Internal::SetScopes(
clientSecretCredential, std::string(another_scopes));
auto const resetToken
= credentials::TokenCredential::Internal::GetToken(clientSecretCredential);
EXPECT_EQ(resetToken.TokenString, emptyString);
EXPECT_EQ(resetToken.Scopes, another_scopes);
EXPECT_EQ(resetToken.ExpiresAt, defaultTime);
}
}
}
}