Skip to content

Commit d9d7f5e

Browse files
authored
Merge pull request #1496 from icherniukh/oauth2_client_credentials
Support for oauth2 with "client_credentials" grant type
2 parents 122d095 + 8ae5da6 commit d9d7f5e

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

Release/include/cpprest/details/http_constants.dat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ DAT(expires_in, "expires_in")
190190
DAT(grant_type, "grant_type")
191191
DAT(redirect_uri, "redirect_uri")
192192
DAT(refresh_token, "refresh_token")
193+
DAT(client_credentials, "client_credentials")
193194
DAT(response_type, "response_type")
194195
DAT(scope, "scope")
195196
DAT(state, "state")

Release/include/cpprest/oauth2.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,21 @@ class oauth2_config
284284
return _request_token(ub);
285285
}
286286

287+
/// <summary>
288+
/// Fetches an access token from the token endpoint using client credentials grant type.
289+
/// The task creates an HTTP request to the token_endpoint() using
290+
/// client authentication as the authorization grant.
291+
/// See: http://tools.ietf.org/html/rfc6749#section-4.4
292+
/// </summary>
293+
/// <returns>Task that fetches token(s) using client credentials.</returns>
294+
pplx::task<void> token_from_client_credentials()
295+
{
296+
uri_builder ub;
297+
ub.append_query(
298+
details::oauth2_strings::grant_type, details::oauth2_strings::client_credentials, false);
299+
return _request_token(ub);
300+
}
301+
287302
/// <summary>
288303
/// Returns enabled state of the configuration.
289304
/// The oauth2_handler will perform OAuth 2.0 authentication only if

Release/tests/functional/http/client/oauth2_tests.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,74 @@ SUITE(oauth2_tests)
291291
VERIFY_ARE_EQUAL(U("done"), m_oauth2_config.token().access_token());
292292
}
293293

294+
TEST_FIXTURE(oauth2_test_setup, oauth2_token_from_client_credentials)
295+
{
296+
VERIFY_IS_FALSE(m_oauth2_config.is_enabled());
297+
298+
m_oauth2_config.set_user_agent(U("test_user_agent"));
299+
300+
// Fetch using HTTP Basic authentication.
301+
{
302+
m_scoped.server()->next_request().then([](test_request* request) {
303+
VERIFY_ARE_EQUAL(request->m_method, methods::POST);
304+
305+
VERIFY_IS_TRUE(is_application_x_www_form_urlencoded(request));
306+
307+
VERIFY_ARE_EQUAL(
308+
U("Basic MTIzQUJDOjQ1NkRFRg=="),
309+
request->m_headers[header_names::authorization]);
310+
311+
VERIFY_ARE_EQUAL(
312+
to_body_data(U("grant_type=client_credentials")),
313+
request->m_body);
314+
315+
VERIFY_ARE_EQUAL(
316+
U("test_user_agent"),
317+
get_request_user_agent(request));
318+
319+
std::map<utility::string_t, utility::string_t> headers;
320+
headers[header_names::content_type] = mime_types::application_json;
321+
request->reply(
322+
status_codes::OK, U(""), headers, "{\"access_token\":\"xyzzy123\",\"token_type\":\"bearer\"}");
323+
});
324+
325+
m_oauth2_config.token_from_client_credentials().wait();
326+
VERIFY_ARE_EQUAL(U("xyzzy123"), m_oauth2_config.token().access_token());
327+
VERIFY_IS_TRUE(m_oauth2_config.is_enabled());
328+
}
329+
330+
// Fetch using client key & secret in request body (x-www-form-urlencoded).
331+
{
332+
m_scoped.server()->next_request().then([](test_request* request) {
333+
VERIFY_IS_TRUE(is_application_x_www_form_urlencoded(request));
334+
335+
VERIFY_ARE_EQUAL(U(""), request->m_headers[header_names::authorization]);
336+
337+
VERIFY_ARE_EQUAL(
338+
to_body_data(U("grant_type=client_credentials&client_id=123ABC&client_secret=456DEF")),
339+
request->m_body);
340+
341+
VERIFY_ARE_EQUAL(U("test_user_agent"), get_request_user_agent(request));
342+
343+
std::map<utility::string_t, utility::string_t> headers;
344+
headers[header_names::content_type] = mime_types::application_json;
345+
request->reply(
346+
status_codes::OK, U(""), headers, "{\"access_token\":\"xyzzy123\",\"token_type\":\"bearer\"}");
347+
});
348+
349+
m_oauth2_config.set_token(oauth2_token()); // Clear token.
350+
VERIFY_IS_FALSE(m_oauth2_config.is_enabled());
351+
352+
m_oauth2_config.set_http_basic_auth(false);
353+
m_oauth2_config.token_from_client_credentials().wait();
354+
355+
VERIFY_ARE_EQUAL(
356+
U("xyzzy123"),
357+
m_oauth2_config.token().access_token());
358+
VERIFY_IS_TRUE(m_oauth2_config.is_enabled());
359+
}
360+
}
361+
294362
TEST_FIXTURE(oauth2_test_setup, oauth2_bearer_token)
295363
{
296364
m_oauth2_config.set_token(oauth2_token(U("12345678")));

0 commit comments

Comments
 (0)