Skip to content

Commit e3efb7e

Browse files
committed
impl(rest): update AuthenticationHeader method to return multiple headers
1 parent 86d7bf2 commit e3efb7e

11 files changed

+67
-45
lines changed

google/cloud/internal/curl_rest_client.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,12 @@ StatusOr<std::unique_ptr<CurlImpl>> CurlRestClient::CreateCurlImpl(
124124
auto impl =
125125
std::make_unique<CurlImpl>(std::move(handle), handle_factory_, options);
126126
if (credentials_) {
127-
auto auth_header =
128-
credentials_->AuthenticationHeader(std::chrono::system_clock::now());
129-
if (!auth_header.ok()) return std::move(auth_header).status();
130-
impl->SetHeader(HttpHeader(auth_header->first, auth_header->second));
127+
auto auth_headers =
128+
credentials_->AuthenticationHeaders(std::chrono::system_clock::now());
129+
if (!auth_headers.ok()) return std::move(auth_headers).status();
130+
for (auto& header : *auth_headers) {
131+
impl->SetHeader(std::move(header));
132+
}
131133
}
132134
impl->SetHeader(HostHeader(options, endpoint_address_));
133135
impl->SetHeaders(context.headers());

google/cloud/internal/oauth2_api_key_credentials.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@ StatusOr<AccessToken> ApiKeyCredentials::GetToken(
2727
return AccessToken{std::string{}, tp};
2828
}
2929

30-
StatusOr<std::pair<std::string, std::string>>
31-
ApiKeyCredentials::AuthenticationHeader(std::chrono::system_clock::time_point) {
32-
return std::make_pair(std::string{"x-goog-api-key"}, api_key_);
30+
StatusOr<std::vector<rest_internal::HttpHeader>>
31+
ApiKeyCredentials::AuthenticationHeaders(
32+
std::chrono::system_clock::time_point) {
33+
std::vector<rest_internal::HttpHeader> headers;
34+
headers.emplace_back("x-goog-api-key", api_key_);
35+
return headers;
3336
}
3437

3538
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END

google/cloud/internal/oauth2_api_key_credentials.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ApiKeyCredentials : public oauth2_internal::Credentials {
3737
StatusOr<AccessToken> GetToken(
3838
std::chrono::system_clock::time_point tp) override;
3939

40-
StatusOr<std::pair<std::string, std::string>> AuthenticationHeader(
40+
StatusOr<std::vector<rest_internal::HttpHeader>> AuthenticationHeaders(
4141
std::chrono::system_clock::time_point) override;
4242

4343
private:

google/cloud/internal/oauth2_api_key_credentials_test.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414

1515
#include "google/cloud/internal/oauth2_api_key_credentials.h"
16+
#include "google/cloud/internal/http_header.h"
1617
#include "google/cloud/testing_util/status_matchers.h"
1718
#include <gmock/gmock.h>
1819
#include <chrono>
@@ -24,6 +25,7 @@ GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
2425
namespace {
2526

2627
using ::google::cloud::testing_util::IsOkAndHolds;
28+
using ::testing::Contains;
2729
using ::testing::IsEmpty;
2830
using ::testing::Pair;
2931

@@ -38,8 +40,9 @@ TEST(ApiKeyCredentials, EmptyToken) {
3840
TEST(ApiKeyCredentials, SetsXGoogApiKeyHeader) {
3941
ApiKeyCredentials creds("api-key");
4042
auto const now = std::chrono::system_clock::now();
41-
EXPECT_THAT(creds.AuthenticationHeader(now),
42-
IsOkAndHolds(Pair("x-goog-api-key", "api-key")));
43+
EXPECT_THAT(creds.AuthenticationHeaders(now),
44+
IsOkAndHolds(Contains(
45+
rest_internal::HttpHeader("x-goog-api-key", "api-key"))));
4346
}
4447

4548
} // namespace

google/cloud/internal/oauth2_credentials.cc

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "google/cloud/internal/make_status.h"
1717
#include "google/cloud/internal/oauth2_universe_domain.h"
1818
#include "absl/strings/str_cat.h"
19+
#include "absl/strings/str_join.h"
1920

2021
namespace google {
2122
namespace cloud {
@@ -46,21 +47,26 @@ StatusOr<std::string> Credentials::project_id(
4647
return project_id();
4748
}
4849

49-
StatusOr<std::pair<std::string, std::string>> Credentials::AuthenticationHeader(
50-
std::chrono::system_clock::time_point tp) {
50+
StatusOr<std::vector<rest_internal::HttpHeader>>
51+
Credentials::AuthenticationHeaders(std::chrono::system_clock::time_point tp) {
52+
std::vector<rest_internal::HttpHeader> headers;
5153
auto token = GetToken(tp);
5254
if (!token) return std::move(token).status();
53-
if (token->token.empty()) return std::make_pair(std::string{}, std::string{});
54-
return std::make_pair(std::string{"Authorization"},
55-
absl::StrCat("Bearer ", token->token));
55+
if (!token->token.empty()) {
56+
headers.emplace_back("Authorization",
57+
absl::StrCat("Bearer ", token->token));
58+
}
59+
return headers;
5660
}
5761

58-
StatusOr<std::string> AuthenticationHeaderJoined(
62+
StatusOr<std::string> AuthenticationHeadersJoined(
5963
Credentials& credentials, std::chrono::system_clock::time_point tp) {
60-
auto header = credentials.AuthenticationHeader(tp);
61-
if (!header) return std::move(header).status();
62-
if (header->first.empty()) return std::string{};
63-
return absl::StrCat(header->first, ": ", header->second);
64+
auto headers = credentials.AuthenticationHeaders(tp);
65+
if (!headers) return std::move(headers).status();
66+
return absl::StrJoin(*headers, ";",
67+
[](std::string* s, rest_internal::HttpHeader const& h) {
68+
*s += std::string{h};
69+
});
6470
}
6571

6672
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END

google/cloud/internal/oauth2_credentials.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_INTERNAL_OAUTH2_CREDENTIALS_H
1717

1818
#include "google/cloud/access_token.h"
19+
#include "google/cloud/internal/http_header.h"
1920
#include "google/cloud/options.h"
2021
#include "google/cloud/status.h"
2122
#include "google/cloud/status_or.h"
@@ -109,33 +110,36 @@ class Credentials {
109110
virtual StatusOr<std::string> project_id(Options const&) const;
110111

111112
/**
112-
* Returns a header pair used for authentication.
113+
* Returns header pairs used for authentication.
113114
*
114115
* In most cases, this is the "Authorization" HTTP header. For API key
115-
* credentials, it is the "X-Goog-Api-Key" header.
116+
* credentials, it is the "X-Goog-Api-Key" header. It may also include the
117+
* "x-allowed-locations" header if applicable.
116118
*
117119
* If unable to obtain a value for the header, which could happen for
118120
* `Credentials` that need to be periodically refreshed, the underlying
119121
* `Status` will indicate failure details from the refresh HTTP request.
120122
* Otherwise, the returned value will contain the header pair to be used in
121123
* HTTP requests.
122124
*/
123-
virtual StatusOr<std::pair<std::string, std::string>> AuthenticationHeader(
124-
std::chrono::system_clock::time_point tp);
125+
virtual StatusOr<std::vector<rest_internal::HttpHeader>>
126+
AuthenticationHeaders(std::chrono::system_clock::time_point tp);
125127
};
126128

127129
/**
128-
* Returns a header pair as a single string to be used for authentication.
130+
* Returns header pairs as a single string to be used for authentication.
129131
*
130132
* In most cases, this is the "Authorization" HTTP header. For API key
131-
* credentials, it is the "X-Goog-Api-Key" header.
133+
* credentials, it is the "X-Goog-Api-Key" header. It may also include the
134+
* "x-allowed-locations" header if applicable.
135+
*
132136
*
133137
* If unable to obtain a value for the header, which could happen for
134138
* `Credentials` that need to be periodically refreshed, the underlying `Status`
135139
* will indicate failure details from the refresh HTTP request. Otherwise, the
136140
* returned value will contain the header pair to be used in HTTP requests.
137141
*/
138-
StatusOr<std::string> AuthenticationHeaderJoined(
142+
StatusOr<std::string> AuthenticationHeadersJoined(
139143
Credentials& credentials, std::chrono::system_clock::time_point tp =
140144
std::chrono::system_clock::now());
141145

google/cloud/internal/oauth2_credentials_test.cc

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ namespace {
2626
using ::google::cloud::internal::UnavailableError;
2727
using ::google::cloud::testing_util::IsOk;
2828
using ::google::cloud::testing_util::IsOkAndHolds;
29+
using ::testing::Contains;
2930
using ::testing::IsEmpty;
3031
using ::testing::Not;
3132
using ::testing::Pair;
@@ -43,8 +44,9 @@ TEST(Credentials, AuthorizationHeaderSuccess) {
4344
auto const expiration = now + std::chrono::seconds(3600);
4445
EXPECT_CALL(mock, GetToken(now))
4546
.WillOnce(Return(AccessToken{"test-token", expiration}));
46-
auto actual = mock.AuthenticationHeader(now);
47-
EXPECT_THAT(actual, IsOkAndHolds(Pair("Authorization", "Bearer test-token")));
47+
auto actual = mock.AuthenticationHeaders(now);
48+
EXPECT_THAT(actual, IsOkAndHolds(Contains(rest_internal::HttpHeader(
49+
"authorization", "Bearer test-token"))));
4850
}
4951

5052
TEST(Credentials, AuthenticationHeaderJoinedSuccess) {
@@ -53,8 +55,8 @@ TEST(Credentials, AuthenticationHeaderJoinedSuccess) {
5355
auto const expiration = now + std::chrono::seconds(3600);
5456
EXPECT_CALL(mock, GetToken(now))
5557
.WillOnce(Return(AccessToken{"test-token", expiration}));
56-
auto actual = AuthenticationHeaderJoined(mock, now);
57-
EXPECT_THAT(actual, IsOkAndHolds("Authorization: Bearer test-token"));
58+
auto actual = AuthenticationHeadersJoined(mock, now);
59+
EXPECT_THAT(actual, IsOkAndHolds("authorization: Bearer test-token"));
5860
}
5961

6062
TEST(Credentials, AuthenticationHeaderJoinedEmpty) {
@@ -63,21 +65,21 @@ TEST(Credentials, AuthenticationHeaderJoinedEmpty) {
6365
auto const expiration = now + std::chrono::seconds(3600);
6466
EXPECT_CALL(mock, GetToken(now))
6567
.WillOnce(Return(AccessToken{"", expiration}));
66-
auto actual = AuthenticationHeaderJoined(mock, now);
68+
auto actual = AuthenticationHeadersJoined(mock, now);
6769
EXPECT_THAT(actual, IsOkAndHolds(IsEmpty()));
6870
}
6971

7072
TEST(Credentials, AuthenticationHeaderError) {
7173
MockCredentials mock;
7274
EXPECT_CALL(mock, GetToken).WillOnce(Return(UnavailableError("try-again")));
73-
auto actual = mock.AuthenticationHeader(std::chrono::system_clock::now());
75+
auto actual = mock.AuthenticationHeaders(std::chrono::system_clock::now());
7476
EXPECT_EQ(actual.status(), UnavailableError("try-again"));
7577
}
7678

7779
TEST(Credentials, AuthenticationHeaderJoinedError) {
7880
MockCredentials mock;
7981
EXPECT_CALL(mock, GetToken).WillOnce(Return(UnavailableError("try-again")));
80-
auto actual = AuthenticationHeaderJoined(mock);
82+
auto actual = AuthenticationHeadersJoined(mock);
8183
EXPECT_EQ(actual.status(), UnavailableError("try-again"));
8284
}
8385

google/cloud/internal/oauth2_minimal_iam_credentials_rest.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,13 @@ MinimalIamCredentialsRestStub::MinimalIamCredentialsRestStub(
4646
StatusOr<google::cloud::AccessToken>
4747
MinimalIamCredentialsRestStub::GenerateAccessToken(
4848
GenerateAccessTokenRequest const& request) {
49-
auto auth_header =
50-
credentials_->AuthenticationHeader(std::chrono::system_clock::now());
51-
if (!auth_header) return std::move(auth_header).status();
52-
49+
auto auth_headers =
50+
credentials_->AuthenticationHeaders(std::chrono::system_clock::now());
51+
if (!auth_headers) return std::move(auth_headers).status();
5352
rest_internal::RestRequest rest_request;
54-
rest_request.AddHeader(rest_internal::HttpHeader(auth_header.value()));
53+
for (auto const& auth_header : *auth_headers) {
54+
rest_request.AddHeader(auth_header);
55+
}
5556
rest_request.AddHeader("Content-Type", "application/json");
5657
rest_request.SetPath(MakeRequestPath(request));
5758
nlohmann::json payload{

google/cloud/internal/unified_rest_credentials_test.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,9 @@ TEST(UnifiedRestCredentialsTest, ApiKey) {
470470
ASSERT_THAT(oauth2_creds, NotNull());
471471

472472
auto header =
473-
oauth2_creds->AuthenticationHeader(std::chrono::system_clock::now());
474-
EXPECT_THAT(header, IsOkAndHolds(Pair("x-goog-api-key", "api-key")));
473+
oauth2_creds->AuthenticationHeaders(std::chrono::system_clock::now());
474+
EXPECT_THAT(header,
475+
IsOkAndHolds(Contains(HttpHeader("x-goog-api-key", "api-key"))));
475476
}
476477

477478
TEST(UnifiedRestCredentialsTest, LoadError) {

google/cloud/storage/client.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class WrapRestCredentials {
5959
: impl_(std::move(impl)) {}
6060

6161
StatusOr<std::string> AuthorizationHeader() {
62-
return oauth2_internal::AuthenticationHeaderJoined(*impl_);
62+
return oauth2_internal::AuthenticationHeadersJoined(*impl_);
6363
}
6464

6565
StatusOr<std::vector<std::uint8_t>> SignBlob(

0 commit comments

Comments
 (0)