Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
From 708a5df2bb328705622c42f84b4167ea2c7c98c9 Mon Sep 17 00:00:00 2001
From: Ivan Cherniukh <ivan.cherniukh@gmail.com>
Date: Wed, 9 Sep 2020 09:09:04 -0700
Subject: [PATCH] Add support for oauth2 using only client credentials

---
.../cpprest/details/http_constants.dat | 1 +
Release/include/cpprest/oauth2.h | 15 ++++
.../functional/http/client/oauth2_tests.cpp | 68 +++++++++++++++++++
3 files changed, 84 insertions(+)

diff --git a/Release/include/cpprest/details/http_constants.dat b/Release/include/cpprest/details/http_constants.dat
index c3b1a53c..3deb24a1 100644
--- a/Release/include/cpprest/details/http_constants.dat
+++ b/Release/include/cpprest/details/http_constants.dat
@@ -190,6 +190,7 @@ DAT(expires_in, "expires_in")
DAT(grant_type, "grant_type")
DAT(redirect_uri, "redirect_uri")
DAT(refresh_token, "refresh_token")
+DAT(client_credentials, "client_credentials")
DAT(response_type, "response_type")
DAT(scope, "scope")
DAT(state, "state")
diff --git a/Release/include/cpprest/oauth2.h b/Release/include/cpprest/oauth2.h
index 693ebbe3..68a7c7b9 100644
--- a/Release/include/cpprest/oauth2.h
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a public API change?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This particular change to http_constants.dat is part of a private header (include/cpprest/details), so no. This adds a const std::string to a private helper class, as below (note the details namespace):

/// oAuth 2.0 library.
namespace oauth2
{
namespace details
{
class oauth2_handler;

// Constant strings for OAuth 2.0.
typedef utility::string_t oauth2_string;
class oauth2_strings
{
public:
#define _OAUTH2_STRINGS
#define DAT(a_, b_) _ASYNCRTIMP static const oauth2_string a_;
#include "cpprest/details/http_constants.dat"
#undef _OAUTH2_STRINGS
#undef DAT
};

} // namespace details

To add some more color, the added constant client_credentials is used in the impl of a newly added public function token_from_client_credentials() to add a uri parameter requiring a specific name for the oauth2 protocol. Since this is a new function that must be called explicitly, there should be no way for it to cause back-compat issues.

+++ b/Release/include/cpprest/oauth2.h
@@ -284,6 +284,21 @@ public:
return _request_token(ub);
}

+ /// <summary>
+ /// Fetches an access token from the token endpoint using client credentials grant type.
+ /// The task creates an HTTP request to the token_endpoint() using
+ /// client authentication as the authorization grant.
+ /// See: http://tools.ietf.org/html/rfc6749#section-4.4
+ /// </summary>
+ /// <returns>Task that fetches token(s) using client credentials.</returns>
+ pplx::task<void> token_from_client_credentials()
+ {
+ uri_builder ub;
+ ub.append_query(
+ details::oauth2_strings::grant_type, details::oauth2_strings::client_credentials, false);
+ return _request_token(ub);
+ }
+
/// <summary>
/// Returns enabled state of the configuration.
/// The oauth2_handler will perform OAuth 2.0 authentication only if
diff --git a/Release/tests/functional/http/client/oauth2_tests.cpp b/Release/tests/functional/http/client/oauth2_tests.cpp
index e1f54085..08bb12a6 100644
--- a/Release/tests/functional/http/client/oauth2_tests.cpp
+++ b/Release/tests/functional/http/client/oauth2_tests.cpp
@@ -291,6 +291,74 @@ SUITE(oauth2_tests)
VERIFY_ARE_EQUAL(U("done"), m_oauth2_config.token().access_token());
}

+ TEST_FIXTURE(oauth2_test_setup, oauth2_token_from_client_credentials)
+ {
+ VERIFY_IS_FALSE(m_oauth2_config.is_enabled());
+
+ m_oauth2_config.set_user_agent(U("test_user_agent"));
+
+ // Fetch using HTTP Basic authentication.
+ {
+ m_scoped.server()->next_request().then([](test_request* request) {
+ VERIFY_ARE_EQUAL(request->m_method, methods::POST);
+
+ VERIFY_IS_TRUE(is_application_x_www_form_urlencoded(request));
+
+ VERIFY_ARE_EQUAL(
+ U("Basic MTIzQUJDOjQ1NkRFRg=="),
+ request->m_headers[header_names::authorization]);
+
+ VERIFY_ARE_EQUAL(
+ to_body_data(U("grant_type=client_credentials")),
+ request->m_body);
+
+ VERIFY_ARE_EQUAL(
+ U("test_user_agent"),
+ get_request_user_agent(request));
+
+ std::map<utility::string_t, utility::string_t> headers;
+ headers[header_names::content_type] = mime_types::application_json;
+ request->reply(
+ status_codes::OK, U(""), headers, "{\"access_token\":\"xyzzy123\",\"token_type\":\"bearer\"}");
+ });
+
+ m_oauth2_config.token_from_client_credentials().wait();
+ VERIFY_ARE_EQUAL(U("xyzzy123"), m_oauth2_config.token().access_token());
+ VERIFY_IS_TRUE(m_oauth2_config.is_enabled());
+ }
+
+ // Fetch using client key & secret in request body (x-www-form-urlencoded).
+ {
+ m_scoped.server()->next_request().then([](test_request* request) {
+ VERIFY_IS_TRUE(is_application_x_www_form_urlencoded(request));
+
+ VERIFY_ARE_EQUAL(U(""), request->m_headers[header_names::authorization]);
+
+ VERIFY_ARE_EQUAL(
+ to_body_data(U("grant_type=client_credentials&client_id=123ABC&client_secret=456DEF")),
+ request->m_body);
+
+ VERIFY_ARE_EQUAL(U("test_user_agent"), get_request_user_agent(request));
+
+ std::map<utility::string_t, utility::string_t> headers;
+ headers[header_names::content_type] = mime_types::application_json;
+ request->reply(
+ status_codes::OK, U(""), headers, "{\"access_token\":\"xyzzy123\",\"token_type\":\"bearer\"}");
+ });
+
+ m_oauth2_config.set_token(oauth2_token()); // Clear token.
+ VERIFY_IS_FALSE(m_oauth2_config.is_enabled());
+
+ m_oauth2_config.set_http_basic_auth(false);
+ m_oauth2_config.token_from_client_credentials().wait();
+
+ VERIFY_ARE_EQUAL(
+ U("xyzzy123"),
+ m_oauth2_config.token().access_token());
+ VERIFY_IS_TRUE(m_oauth2_config.is_enabled());
+ }
+ }
+
TEST_FIXTURE(oauth2_test_setup, oauth2_bearer_token)
{
m_oauth2_config.set_token(oauth2_token(U("12345678")));
--
2.23.3

27 changes: 15 additions & 12 deletions SPECS/cpprest/cpprest.spec
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
%define major 2
%define minor 10

Summary: C++ REST library
Name: cpprest
Version: 2.10.14
Release: 6%{?dist}
Summary: C++ REST library
Group: Applications/File
Release: 7%{?dist}
License: MIT
Url: https://github.com/Microsoft/cpprestsdk
Vendor: Microsoft Corporation
Distribution: Mariner
Group: Applications/File
URL: https://github.com/Microsoft/cpprestsdk
#Source0: https://github.com/Microsoft/cpprestsdk/archive/v%{version}.tar.gz
Source0: %{name}-%{version}.tar.gz
# Disable outside, failing and sometimes failing tests
Expand All @@ -16,13 +17,13 @@ Patch1: cpprest-2.10.9-disable-outside-and-failing-tests.patch
Patch2: cpprest-2.10.9-disable-tests-long-timeouts.patch
# Disable test extract_floating_point, which fails on ppc64le and aarch64
Patch3: cpprest-2.10.9-disable-test-extract_floating_point.patch
Vendor: Microsoft Corporation
Distribution: Mariner
# Add support for oauth2 'client_credentials' grant type.
Patch4: cpprest-2.10.14-Add-support-for-oauth2-using-client-credentials.patch
BuildRequires: boost-devel >= 1.55
BuildRequires: cmake >= 3.1
BuildRequires: websocketpp-devel
BuildRequires: brotli-devel
BuildRequires: cmake >= 3.1
BuildRequires: openssl >= 1.0
BuildRequires: websocketpp-devel
BuildRequires: zlib

%description
Expand All @@ -46,10 +47,11 @@ project aims to help C++ developers connect to and interact with services.
Development files.

%prep
%setup -n cpprestsdk-%{version}
%setup -q -n cpprestsdk-%{version}
Copy link
Copy Markdown
Author

@abeltrano abeltrano Dec 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spec-lint checks required this change, and the others where existing lines in this file were moved.

%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
# Remove bundled sources of websocketpp
rm -r Release/libs
# Remove file ThirdPartyNotices.txt, which is associated to websocketpp
Expand All @@ -74,7 +76,6 @@ cd Release/build.release/Binaries
./test_runner *_test.so ||:

%post -p /sbin/ldconfig

%postun -p /sbin/ldconfig

%files
Expand All @@ -89,8 +90,10 @@ cd Release/build.release/Binaries
%{_libdir}/libcpprest.so
%{_libdir}/cmake/cpprestsdk


%changelog
* Mon Dec 14 2020 Andrew Beltrano <anbeltra@microsoft.com> - 2.10.14-7
- Add cpprest-2.10.14-Add-support-for-oauth2-using-client-credentials.patch.

* Tue Dec 08 2020 Andrew Phelps <anphel@microsoft.com> - 2.10.14-6
- Remove -DBUILD_TESTS=OFF to allow running tests

Expand Down