Skip to content

Commit 9790f56

Browse files
committed
Added scope support to authentication
* Added new method AuthenticationClient::SignInClient() which takes new SignInProperties structure as a parameter. * Old AuthenticationClient::SignInClient method deprecated. * Added integration test to cover new scope case. Resolves: OLPEDGE-874 Signed-off-by: Serhii Lozynskyi <[email protected]>
1 parent 8354621 commit 9790f56

File tree

8 files changed

+153
-66
lines changed

8 files changed

+153
-66
lines changed

olp-cpp-sdk-authentication/include/olp/authentication/AuthenticationClient.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#pragma once
2121

22+
#include <boost/optional.hpp>
2223
#include <chrono>
2324
#include <functional>
2425
#include <memory>
@@ -65,6 +66,23 @@ static const std::string kHereAccountProductionUrl =
6566
*/
6667
class AUTHENTICATION_API AuthenticationClient {
6768
public:
69+
/**
70+
* @brief General properties used to sign in using client credentials.
71+
*/
72+
struct SignInProperties {
73+
/**
74+
* @brief scope Optional. Scope that should be assigned to access token.
75+
*/
76+
boost::optional<std::string> scope{boost::none};
77+
78+
/**
79+
* @brief expires_in Optional. Number of seconds before token expires, must
80+
* number zero or more. Ignored if zero or greater than default expiration
81+
* of the application.
82+
*/
83+
std::chrono::seconds expires_in{0};
84+
};
85+
6886
/**
6987
* @brief The password user sign-in properties struct.
7088
*/
@@ -284,11 +302,32 @@ class AUTHENTICATION_API AuthenticationClient {
284302
* application.
285303
* @return CancellationToken that can be used to cancel the request.
286304
*/
305+
OLP_SDK_DEPRECATED(
306+
"Deprecated. Please use version with properties parameter. Will be "
307+
"removed by 03.2020")
287308
client::CancellationToken SignInClient(
288309
const AuthenticationCredentials& credentials,
289310
const SignInClientCallback& callback,
290311
const std::chrono::seconds& expires_in = std::chrono::seconds(0));
291312

313+
/**
314+
* @brief Sign in with HERE account client credentials, requests a client
315+
* access token that identifies the application or service by providing client
316+
* credentials. Client access tokens can not be refreshed, instead request a
317+
* new one using client credentials.
318+
* @param credentials Client access keys issued for the client by the HERE
319+
* Account as part of the onboarding or support process.
320+
* @param properties SignInProperties structure that has scope and expire
321+
* properties.
322+
* @param callback The method to be called when request is completed. In case
323+
* of successful client sign-in request, the returned HTTP status is 200.
324+
* Otherwise, check the response error.
325+
* @return CancellationToken that can be used to cancel the request.
326+
*/
327+
client::CancellationToken SignInClient(AuthenticationCredentials credentials,
328+
SignInProperties properties,
329+
SignInClientCallback callback);
330+
292331
/**
293332
* @brief Sign in by providing the user email and password previously
294333
* registered using the sign-up API, requests a user access token. User access

olp-cpp-sdk-authentication/include/olp/authentication/SignInResult.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ class AUTHENTICATION_API SignInResult {
9999
*/
100100
const std::string& GetUserIdentifier() const;
101101

102+
/**
103+
* @brief Scope that is assigned to access token.
104+
* @return String containing the scope.
105+
*/
106+
const std::string& GetScope() const;
107+
102108
private:
103109
friend class SignInUserResult;
104110
friend class AuthenticationClient;

olp-cpp-sdk-authentication/src/AuthenticationClient.cpp

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ constexpr auto kDateOfBirth = "dob";
8282
constexpr auto kEmail = "email";
8383
constexpr auto kFirstName = "firstname";
8484
constexpr auto kGrantType = "grantType";
85+
constexpr auto kScope = "scope";
8586
constexpr auto kInviteToken = "inviteToken";
8687
constexpr auto kLanguage = "language";
8788
constexpr auto kLastName = "lastname";
@@ -165,9 +166,8 @@ class AuthenticationClient::Impl final {
165166
* @return CancellationToken that can be used to cancel the request.
166167
*/
167168
client::CancellationToken SignInClient(
168-
const AuthenticationCredentials& credentials,
169-
const std::chrono::seconds& expires_in,
170-
const AuthenticationClient::SignInClientCallback& callback);
169+
AuthenticationCredentials credentials, SignInProperties properties,
170+
AuthenticationClient::SignInClientCallback callback);
171171

172172
client::CancellationToken SignInHereUser(
173173
const AuthenticationCredentials& credentials,
@@ -212,7 +212,7 @@ class AuthenticationClient::Impl final {
212212
std::string generateBearerHeader(const std::string& bearer_token);
213213

214214
http::NetworkRequest::RequestBodyType generateClientBody(
215-
unsigned int expires_in);
215+
const SignInProperties& properties);
216216
http::NetworkRequest::RequestBodyType generateUserBody(
217217
const AuthenticationClient::UserProperties& properties);
218218
http::NetworkRequest::RequestBodyType generateFederatedBody(
@@ -279,9 +279,8 @@ AuthenticationClient::Impl::Impl(const std::string& authentication_server_url,
279279
network_settings_() {}
280280

281281
client::CancellationToken AuthenticationClient::Impl::SignInClient(
282-
const AuthenticationCredentials& credentials,
283-
const std::chrono::seconds& expires_in,
284-
const AuthenticationClient::SignInClientCallback& callback) {
282+
AuthenticationCredentials credentials, SignInProperties properties,
283+
AuthenticationClient::SignInClientCallback callback) {
285284
if (!network_) {
286285
ExecuteOrSchedule(task_scheduler_, [callback] {
287286
AuthenticationError result({static_cast<int>(http::ErrorCode::IO_ERROR),
@@ -303,8 +302,7 @@ client::CancellationToken AuthenticationClient::Impl::SignInClient(
303302

304303
std::shared_ptr<std::stringstream> payload =
305304
std::make_shared<std::stringstream>();
306-
request.WithBody(
307-
generateClientBody(static_cast<unsigned int>(expires_in.count())));
305+
request.WithBody(generateClientBody(properties));
308306
auto cache = client_token_cache_;
309307
auto send_outcome = network_->Send(
310308
request, payload,
@@ -724,19 +722,25 @@ std::string AuthenticationClient::Impl::generateBearerHeader(
724722
}
725723

726724
http::NetworkRequest::RequestBodyType
727-
AuthenticationClient::Impl::generateClientBody(unsigned int expires_in) {
725+
AuthenticationClient::Impl::generateClientBody(
726+
const SignInProperties& properties) {
728727
rapidjson::StringBuffer data;
729728
rapidjson::Writer<rapidjson::StringBuffer> writer(data);
730729
writer.StartObject();
731730

732731
writer.Key(kGrantType);
733732
writer.String(kClientGrantType);
734733

734+
auto expires_in = static_cast<unsigned int>(properties.expires_in.count());
735735
if (expires_in > 0) {
736736
writer.Key(Constants::EXPIRES_IN);
737737
writer.Uint(expires_in);
738738
}
739739

740+
if (properties.scope) {
741+
writer.Key(kScope);
742+
writer.String(properties.scope.get().c_str());
743+
}
740744
writer.EndObject();
741745
auto content = data.GetString();
742746
return std::make_shared<std::vector<unsigned char> >(
@@ -764,7 +768,6 @@ AuthenticationClient::Impl::generateUserBody(const UserProperties& properties) {
764768
writer.Key(Constants::EXPIRES_IN);
765769
writer.Uint(properties.expires_in);
766770
}
767-
768771
writer.EndObject();
769772
auto content = data.GetString();
770773
return std::make_shared<std::vector<unsigned char> >(
@@ -842,7 +845,6 @@ AuthenticationClient::Impl::generateRefreshBody(
842845
writer.Key(Constants::EXPIRES_IN);
843846
writer.Uint(properties.expires_in);
844847
}
845-
846848
writer.EndObject();
847849
auto content = data.GetString();
848850
return std::make_shared<std::vector<unsigned char> >(
@@ -942,7 +944,16 @@ client::CancellationToken AuthenticationClient::SignInClient(
942944
const AuthenticationCredentials& credentials,
943945
const SignInClientCallback& callback,
944946
const std::chrono::seconds& expires_in) {
945-
return impl_->SignInClient(credentials, expires_in, callback);
947+
SignInProperties properties;
948+
properties.expires_in = expires_in;
949+
return impl_->SignInClient(credentials, properties, callback);
950+
}
951+
952+
client::CancellationToken AuthenticationClient::SignInClient(
953+
AuthenticationCredentials credentials, SignInProperties properties,
954+
SignInClientCallback callback) {
955+
return impl_->SignInClient(std::move(credentials), std::move(properties),
956+
std::move(callback));
946957
}
947958

948959
client::CancellationToken AuthenticationClient::SignInHereUser(

olp-cpp-sdk-authentication/src/SignInResult.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ const std::string& SignInResult::GetUserIdentifier() const {
5858
return impl_->GetUserIdentifier();
5959
}
6060

61+
const std::string& SignInResult::GetScope() const { return impl_->GetScope(); }
62+
6163
SignInResult::SignInResult(std::shared_ptr<SignInResultImpl> impl)
6264
: impl_(impl) {}
6365

olp-cpp-sdk-authentication/src/SignInResultImpl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
namespace {
2626
constexpr auto kTokenType = "tokenType";
2727
constexpr auto kUserId = "userId";
28+
constexpr auto kScope = "scope";
2829
} // namespace
2930

3031
namespace olp {
@@ -60,6 +61,8 @@ SignInResultImpl::SignInResultImpl(
6061
(*json_document)[Constants::EXPIRES_IN].GetUint();
6162
if (json_document->HasMember(kUserId))
6263
user_identifier_ = (*json_document)[kUserId].GetString();
64+
if (json_document->HasMember(kScope))
65+
scope_ = (*json_document)[kScope].GetString();
6366
}
6467
}
6568
}
@@ -84,6 +87,8 @@ const std::string& SignInResultImpl::GetUserIdentifier() const {
8487
return user_identifier_;
8588
}
8689

90+
const std::string& SignInResultImpl::GetScope() const { return scope_; }
91+
8792
bool SignInResultImpl::IsValid() const { return is_valid_; }
8893

8994
} // namespace authentication

olp-cpp-sdk-authentication/src/SignInResultImpl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ class SignInResultImpl : public BaseResult {
7676
*/
7777
bool IsValid() const override;
7878

79+
const std::string& GetScope() const;
80+
7981
private:
8082
bool is_valid_;
8183

@@ -85,6 +87,7 @@ class SignInResultImpl : public BaseResult {
8587
time_t expiry_time_;
8688
std::string refresh_token_;
8789
std::string user_identifier_;
90+
std::string scope_;
8891
};
8992
} // namespace authentication
9093
} // namespace olp

tests/integration/olp-cpp-sdk-authentication/AuthenticationClientTest.cpp

Lines changed: 54 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ void TestCheckErrorFields(const ErrorFields& errorFields) {
104104

105105
class AuthenticationClientTest : public ::testing::Test {
106106
public:
107-
AuthenticationClientTest() : key_("key"), secret_("secret") {}
107+
AuthenticationClientTest()
108+
: key_("key"), secret_("secret"), scope_("scope") {}
108109
void SetUp() {
109110
client_ = std::make_unique<AuthenticationClient>(
110111
"https://authentication.server.url");
@@ -209,8 +210,58 @@ class AuthenticationClientTest : public ::testing::Test {
209210
std::shared_ptr<olp::thread::TaskScheduler> task_scheduler_;
210211
const std::string key_;
211212
const std::string secret_;
213+
const std::string scope_;
212214
};
213215

216+
TEST_F(AuthenticationClientTest, SignInClientScope) {
217+
AuthenticationCredentials credentials(key_, secret_);
218+
std::promise<AuthenticationClient::SignInClientResponse> request;
219+
auto request_future = request.get_future();
220+
221+
EXPECT_CALL(*network_, Send(_, _, _, _, _))
222+
.WillOnce([&](olp::http::NetworkRequest request,
223+
olp::http::Network::Payload payload,
224+
olp::http::Network::Callback callback,
225+
olp::http::Network::HeaderCallback header_callback,
226+
olp::http::Network::DataCallback data_callback) {
227+
olp::http::RequestId request_id(5);
228+
if (payload) {
229+
*payload << kResponseWithScope;
230+
}
231+
callback(olp::http::NetworkResponse()
232+
.WithRequestId(request_id)
233+
.WithStatus(olp::http::HttpStatusCode::OK));
234+
if (data_callback) {
235+
auto raw = const_cast<char*>(kResponseWithScope.c_str());
236+
data_callback(reinterpret_cast<uint8_t*>(raw), 0,
237+
kResponseWithScope.size());
238+
}
239+
240+
return olp::http::SendOutcome(request_id);
241+
});
242+
243+
AuthenticationClient::SignInProperties properties;
244+
properties.scope = scope_;
245+
std::time_t now = std::time(nullptr);
246+
client_->SignInClient(
247+
credentials, properties,
248+
[&](const AuthenticationClient::SignInClientResponse& response) {
249+
request.set_value(response);
250+
});
251+
request_future.wait();
252+
253+
AuthenticationClient::SignInClientResponse response = request_future.get();
254+
EXPECT_TRUE(response.IsSuccessful());
255+
EXPECT_FALSE(response.GetResult().GetAccessToken().empty());
256+
EXPECT_EQ(kResponseToken, response.GetResult().GetAccessToken());
257+
EXPECT_GE(now + kMaxExpiryTime, response.GetResult().GetExpiryTime());
258+
EXPECT_LT(now + kMinExpiryTime, response.GetResult().GetExpiryTime());
259+
EXPECT_EQ("bearer", response.GetResult().GetTokenType());
260+
EXPECT_TRUE(response.GetResult().GetRefreshToken().empty());
261+
EXPECT_TRUE(response.GetResult().GetUserIdentifier().empty());
262+
EXPECT_EQ(response.GetResult().GetScope(), scope_);
263+
}
264+
214265
TEST_F(AuthenticationClientTest, SignInClientData) {
215266
AuthenticationCredentials credentials("key_", secret_);
216267
std::promise<AuthenticationClient::SignInClientResponse> request;
@@ -263,32 +314,7 @@ TEST_F(AuthenticationClientTest, SignInClientData) {
263314
AuthenticationClient::SignInClientResponse response = request_future.get();
264315
EXPECT_TRUE(response.IsSuccessful());
265316
EXPECT_FALSE(response.GetResult().GetAccessToken().empty());
266-
EXPECT_EQ(
267-
"tyJhbGciOiJSUzUxMiIsImN0eSI6IkpXVCIsImlzcyI6IkhFUkUiLCJhaWQiOiJTcFR5dkQ0"
268-
"RjZ1dWhVY0t3Zj"
269-
"BPRC"
270-
"IsImlhdCI6MTUyMjY5OTY2MywiZXhwIjoxNTIyNzAzMjYzLCJraWQiOiJqMSJ9."
271-
"ZXlKaGJHY2lPaUprYVhJaUxDSmxibU1pT2lKQk1qVTJRMEpETFVoVE5URXlJbjAuLkNuSXBW"
272-
"VG14bFBUTFhqdF"
273-
"l0OD"
274-
"VodVEuTk1aMzRVSndtVnNOX21Zd3pwa1UydVFfMklCbE9QeWw0VEJWQnZXczcwRXdoQWRld0"
275-
"tpR09KOGFHOWtK"
276-
"eTBo"
277-
"YWg2SS03Y01WbXQ4S3ppUHVKOXZqV2U1Q0F4cER0LU0yQUxhQTJnZWlIZXJuaEEwZ1ZRR3pV"
278-
"akw5OEhDdkpEc2"
279-
"YuQX"
280-
"hxNTRPTG9FVDhqV2ZreTgtZHY4ZUR1SzctRnJOWklGSms0RHZGa2F5Yw.bfSc5sXovW0-"
281-
"yGTqWDZtsVvqIxeNl9IGFbtzRBRkHCHEjthZzeRscB6oc707JTpiuRmDKJe6oFU03RocTS99"
282-
"YBlM3p5rP2moad"
283-
"DNmP"
284-
"3Uag4elo6z0ZE_w1BP7So7rMX1k4NymfEATdmyXVnjAhBlTPQqOYIWV-"
285-
"UNCXWCIzLSuwaJ96N1d8XZeiA1jkpsp4CKfcSSm9hgsKNA95SWPnZAHyqOYlO0sDE28osOIj"
286-
"N2UVSUKlO1BDtL"
287-
"iPLt"
288-
"a_dIqvqFUU5aRi_"
289-
"dcYqkJcZh195ojzeAcvDGI6HqS2zUMTdpYUhlwwfpkxGwrFmlAxgx58xKSeVt0sPvtabZBAW"
290-
"8uh2NGg",
291-
response.GetResult().GetAccessToken());
317+
EXPECT_EQ(kResponseToken, response.GetResult().GetAccessToken());
292318
EXPECT_GE(now + kMaxExpiryTime, response.GetResult().GetExpiryTime());
293319
EXPECT_LT(now + kMinExpiryTime, response.GetResult().GetExpiryTime());
294320
EXPECT_EQ("bearer", response.GetResult().GetTokenType());
@@ -308,32 +334,7 @@ TEST_F(AuthenticationClientTest, SignInClientData) {
308334
AuthenticationClient::SignInClientResponse response_2 =
309335
request_future_2.get();
310336
EXPECT_TRUE(response_2.IsSuccessful());
311-
EXPECT_EQ(
312-
"tyJhbGciOiJSUzUxMiIsImN0eSI6IkpXVCIsImlzcyI6IkhFUkUiLCJhaWQiOiJTcFR5dkQ0"
313-
"RjZ1dWhVY0t3Zj"
314-
"BPRC"
315-
"IsImlhdCI6MTUyMjY5OTY2MywiZXhwIjoxNTIyNzAzMjYzLCJraWQiOiJqMSJ9."
316-
"ZXlKaGJHY2lPaUprYVhJaUxDSmxibU1pT2lKQk1qVTJRMEpETFVoVE5URXlJbjAuLkNuSXBW"
317-
"VG14bFBUTFhqdF"
318-
"l0OD"
319-
"VodVEuTk1aMzRVSndtVnNOX21Zd3pwa1UydVFfMklCbE9QeWw0VEJWQnZXczcwRXdoQWRld0"
320-
"tpR09KOGFHOWtK"
321-
"eTBo"
322-
"YWg2SS03Y01WbXQ4S3ppUHVKOXZqV2U1Q0F4cER0LU0yQUxhQTJnZWlIZXJuaEEwZ1ZRR3pV"
323-
"akw5OEhDdkpEc2"
324-
"YuQX"
325-
"hxNTRPTG9FVDhqV2ZreTgtZHY4ZUR1SzctRnJOWklGSms0RHZGa2F5Yw.bfSc5sXovW0-"
326-
"yGTqWDZtsVvqIxeNl9IGFbtzRBRkHCHEjthZzeRscB6oc707JTpiuRmDKJe6oFU03RocTS99"
327-
"YBlM3p5rP2moad"
328-
"DNmP"
329-
"3Uag4elo6z0ZE_w1BP7So7rMX1k4NymfEATdmyXVnjAhBlTPQqOYIWV-"
330-
"UNCXWCIzLSuwaJ96N1d8XZeiA1jkpsp4CKfcSSm9hgsKNA95SWPnZAHyqOYlO0sDE28osOIj"
331-
"N2UVSUKlO1BDtL"
332-
"iPLt"
333-
"a_dIqvqFUU5aRi_"
334-
"dcYqkJcZh195ojzeAcvDGI6HqS2zUMTdpYUhlwwfpkxGwrFmlAxgx58xKSeVt0sPvtabZBAW"
335-
"8uh2NGg",
336-
response_2.GetResult().GetAccessToken());
337+
EXPECT_EQ(kResponseToken, response_2.GetResult().GetAccessToken());
337338
;
338339
EXPECT_GE(now_2 + kMaxExpiryTime, response_2.GetResult().GetExpiryTime());
339340
EXPECT_LT(now_2 + kMinExpiryTime, response_2.GetResult().GetExpiryTime());

0 commit comments

Comments
 (0)