C++ Rest SDK
The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.
oauth2.h
1 /***
2 * ==++==
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * ==--==
17 * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
18 *
19 * HTTP Library: Oauth 2.0
20 *
21 * For the latest on this and related APIs, please see http://casablanca.codeplex.com.
22 *
23 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
24 ****/
25 #pragma once
26 
27 #ifndef _CASA_OAUTH2_H
28 #define _CASA_OAUTH2_H
29 
30 #include "cpprest/http_msg.h"
31 
32 namespace web
33 {
34 namespace http
35 {
36 namespace client
37 {
38  // Forward declaration to avoid circular include dependency.
39  class http_client_config;
40 }
41 
43 namespace oauth2
44 {
45 namespace details
46 {
47 
48 class oauth2_handler;
49 
50 // Constant strings for OAuth 2.0.
51 typedef utility::string_t oauth2_string;
53 {
54 public:
55 #define _OAUTH2_STRINGS
56 #define DAT(a_, b_) _ASYNCRTIMP static const oauth2_string a_;
57 #include "cpprest/details/http_constants.dat"
58 #undef _OAUTH2_STRINGS
59 #undef DAT
60 };
61 
62 } // namespace web::http::oauth2::details
63 
65 namespace experimental
66 {
67 
71 class oauth2_exception : public std::exception
72 {
73 public:
74  oauth2_exception(utility::string_t msg) : m_msg(utility::conversions::to_utf8string(std::move(msg))) {}
75  ~oauth2_exception() CPPREST_NOEXCEPT {}
76  const char* what() const CPPREST_NOEXCEPT { return m_msg.c_str(); }
77 
78 private:
79  std::string m_msg;
80 };
81 
86 {
87 public:
88 
92  enum { undefined_expiration = -1 };
93 
94  oauth2_token(utility::string_t access_token=utility::string_t()) :
95  m_access_token(std::move(access_token)),
96  m_expires_in(undefined_expiration)
97  {}
98 
104  bool is_valid_access_token() const { return !access_token().empty(); }
105 
110  const utility::string_t& access_token() const { return m_access_token; }
115  void set_access_token(utility::string_t access_token) { m_access_token = std::move(access_token); }
116 
121  const utility::string_t& refresh_token() const { return m_refresh_token; }
126  void set_refresh_token(utility::string_t refresh_token) { m_refresh_token = std::move(refresh_token); }
127 
132  const utility::string_t& token_type() const { return m_token_type; }
137  void set_token_type(utility::string_t token_type) { m_token_type = std::move(token_type); }
138 
143  const utility::string_t& scope() const { return m_scope; }
148  void set_scope(utility::string_t scope) { m_scope = std::move(scope); }
149 
158  int64_t expires_in() const { return m_expires_in; }
163  void set_expires_in(int64_t expires_in) { m_expires_in = expires_in; }
164 
165 private:
166  utility::string_t m_access_token;
167  utility::string_t m_refresh_token;
168  utility::string_t m_token_type;
169  utility::string_t m_scope;
170  int64_t m_expires_in;
171 };
172 
213 {
214 public:
215 
216  oauth2_config(utility::string_t client_key, utility::string_t client_secret,
217  utility::string_t auth_endpoint, utility::string_t token_endpoint,
218  utility::string_t redirect_uri, utility::string_t scope=utility::string_t()) :
219  m_client_key(std::move(client_key)),
220  m_client_secret(std::move(client_secret)),
221  m_auth_endpoint(std::move(auth_endpoint)),
222  m_token_endpoint(std::move(token_endpoint)),
223  m_redirect_uri(std::move(redirect_uri)),
224  m_scope(std::move(scope)),
225  m_implicit_grant(false),
226  m_bearer_auth(true),
227  m_http_basic_auth(true),
228  m_access_token_key(details::oauth2_strings::access_token)
229  {}
230 
241  _ASYNCRTIMP utility::string_t build_authorization_uri(bool generate_state);
242 
256  _ASYNCRTIMP pplx::task<void> token_from_redirected_uri(const web::http::uri& redirected_uri);
257 
267  pplx::task<void> token_from_code(utility::string_t authorization_code)
268  {
269  uri_builder ub;
270  ub.append_query(details::oauth2_strings::grant_type, details::oauth2_strings::authorization_code, false);
271  ub.append_query(details::oauth2_strings::code, uri::encode_data_string(std::move(authorization_code)), false);
272  ub.append_query(details::oauth2_strings::redirect_uri, uri::encode_data_string(redirect_uri()), false);
273  return _request_token(ub);
274  }
275 
285  {
286  uri_builder ub;
287  ub.append_query(details::oauth2_strings::grant_type, details::oauth2_strings::refresh_token, false);
288  ub.append_query(details::oauth2_strings::refresh_token, uri::encode_data_string(token().refresh_token()), false);
289  return _request_token(ub);
290  }
291 
299  bool is_enabled() const { return token().is_valid_access_token(); }
300 
305  const utility::string_t& client_key() const { return m_client_key; }
310  void set_client_key(utility::string_t client_key) { m_client_key = std::move(client_key); }
311 
316  const utility::string_t& client_secret() const { return m_client_secret; }
321  void set_client_secret(utility::string_t client_secret) { m_client_secret = std::move(client_secret); }
322 
327  const utility::string_t& auth_endpoint() const { return m_auth_endpoint; }
332  void set_auth_endpoint(utility::string_t auth_endpoint) { m_auth_endpoint = std::move(auth_endpoint); }
333 
338  const utility::string_t& token_endpoint() const { return m_token_endpoint; }
343  void set_token_endpoint(utility::string_t token_endpoint) { m_token_endpoint = std::move(token_endpoint); }
344 
349  const utility::string_t& redirect_uri() const { return m_redirect_uri; }
354  void set_redirect_uri(utility::string_t redirect_uri) { m_redirect_uri = std::move(redirect_uri); }
355 
360  const utility::string_t& scope() const { return m_scope; }
365  void set_scope(utility::string_t scope) { m_scope = std::move(scope); }
366 
371  const utility::string_t& state() { return m_state; }
381  void set_state(utility::string_t state) { m_state = std::move(state); }
382 
387  const oauth2_token& token() const { return m_token; }
392  void set_token(oauth2_token token) { m_token = std::move(token); }
393 
398  bool implicit_grant() const { return m_implicit_grant; }
406  void set_implicit_grant(bool implicit_grant) { m_implicit_grant = implicit_grant; }
407 
412  bool bearer_auth() const { return m_bearer_auth; }
421  void set_bearer_auth(bool bearer_auth) { m_bearer_auth = bearer_auth; }
422 
427  bool http_basic_auth() const { return m_http_basic_auth; }
436  void set_http_basic_auth(bool http_basic_auth) { m_http_basic_auth = http_basic_auth; }
437 
442  const utility::string_t& access_token_key() const { return m_access_token_key; }
448  void set_access_token_key(utility::string_t access_token_key) { m_access_token_key = std::move(access_token_key); }
449 
454  const web_proxy& proxy() const
455  {
456  return m_proxy;
457  }
458 
463  void set_proxy(const web_proxy& proxy)
464  {
465  m_proxy = proxy;
466  }
467 
468 private:
471 
472  oauth2_config() :
473  m_implicit_grant(false),
474  m_bearer_auth(true),
475  m_http_basic_auth(true)
476  {}
477 
478  _ASYNCRTIMP pplx::task<void> _request_token(uri_builder& request_body);
479 
480  oauth2_token _parse_token_from_json(const json::value& token_json);
481 
482  void _authenticate_request(http_request &req) const
483  {
484  if (bearer_auth())
485  {
486  req.headers().add(header_names::authorization, _XPLATSTR("Bearer ") + token().access_token());
487  }
488  else
489  {
490  uri_builder ub(req.request_uri());
491  ub.append_query(access_token_key(), token().access_token());
492  req.set_request_uri(ub.to_uri());
493  }
494  }
495 
496  utility::string_t m_client_key;
497  utility::string_t m_client_secret;
498  utility::string_t m_auth_endpoint;
499  utility::string_t m_token_endpoint;
500  utility::string_t m_redirect_uri;
501  utility::string_t m_scope;
502  utility::string_t m_state;
503 
504  web::web_proxy m_proxy;
505 
506  bool m_implicit_grant;
507  bool m_bearer_auth;
508  bool m_http_basic_auth;
509  utility::string_t m_access_token_key;
510 
511  oauth2_token m_token;
512 
513  utility::nonce_generator m_state_generator;
514 };
515 
516 } // namespace web::http::oauth2::experimental
517 
518 namespace details
519 {
520 
522 {
523 public:
524  oauth2_handler(std::shared_ptr<experimental::oauth2_config> cfg) :
525  m_config(std::move(cfg))
526  {}
527 
529  {
530  if (m_config)
531  {
532  m_config->_authenticate_request(request);
533  }
534  return next_stage()->propagate(request);
535  }
536 
537 private:
538  std::shared_ptr<experimental::oauth2_config> m_config;
539 };
540 
541 }}}}
542 
543 #endif
void set_request_uri(const uri &uri)
Set the underling URI of the request message.
Definition: http_msg.h:814
pplx::task< void > token_from_code(utility::string_t authorization_code)
Fetches an access token (and possibly a refresh token) from the token endpoint. The task creates an H...
Definition: oauth2.h:267
OAuth 2.0 configuration.
Definition: oauth2.h:212
void set_token(oauth2_token token)
Set token.
Definition: oauth2.h:392
void set_http_basic_auth(bool http_basic_auth)
Set HTTP Basic authentication setting for token endpoint. This setting must be selected based on what...
Definition: oauth2.h:436
void set_auth_endpoint(utility::string_t auth_endpoint)
Set authorization endpoint URI string.
Definition: oauth2.h:332
HTTP client handler class, used to represent an HTTP pipeline stage.
Definition: http_msg.h:1302
A flexible, protocol independent URI implementation.
Definition: base_uri.h:151
void set_token_endpoint(utility::string_t token_endpoint)
Set token endpoint URI string.
Definition: oauth2.h:343
http_headers & headers()
Gets a reference to the headers of the response message.
Definition: http_msg.h:843
bool bearer_auth() const
Get bearer token authentication setting.
Definition: oauth2.h:412
const utility::string_t & token_endpoint() const
Get token endpoint URI string.
Definition: oauth2.h:338
void set_access_token_key(utility::string_t access_token_key)
Set access token key. If the service requires a "non-standard" key you must set it here...
Definition: oauth2.h:448
void set_access_token(utility::string_t access_token)
Set access token.
Definition: oauth2.h:115
void set_token_type(utility::string_t token_type)
Set token type.
Definition: oauth2.h:137
OAuth 2.0 token and associated information.
Definition: oauth2.h:85
The web namespace contains functionality common to multiple protocols like HTTP and WebSockets...
Definition: base_uri.h:37
void set_proxy(const web_proxy &proxy)
Set the web proxy object that will be used by token_from_code and token_from_refresh ...
Definition: oauth2.h:463
void set_client_secret(utility::string_t client_secret)
Set client secret.
Definition: oauth2.h:321
const utility::string_t & auth_endpoint() const
Get authorization endpoint URI string.
Definition: oauth2.h:327
void set_state(utility::string_t state)
Set client state string for authorization for token. The state string is used in authorization for se...
Definition: oauth2.h:381
const utility::string_t & redirect_uri() const
Get redirect URI string.
Definition: oauth2.h:349
HTTP client configuration class, used to set the possible configuration options used to create an htt...
Definition: http_client.h:90
const oauth2_token & token() const
Get token.
Definition: oauth2.h:387
const utility::string_t & access_token_key() const
Get access token key.
Definition: oauth2.h:442
const utility::string_t & scope() const
Get token scope.
Definition: oauth2.h:143
void add(const key_type &name, const _t1 &value)
Adds a header field using the '<<' operator.
Definition: http_headers.h:158
void set_expires_in(int64_t expires_in)
Set lifetime of access token (in seconds).
Definition: oauth2.h:163
const web_proxy & proxy() const
Get the web proxy object
Definition: oauth2.h:454
const utility::string_t & access_token() const
Get access token.
Definition: oauth2.h:110
bool is_valid_access_token() const
Get access token validity state. If true, access token is a valid.
Definition: oauth2.h:104
const utility::string_t & client_secret() const
Get client secret.
Definition: oauth2.h:316
static _ASYNCRTIMP utility::string_t __cdecl encode_data_string(const utility::string_t &utf8data)
Encodes a string by converting all characters except for RFC 3986 unreserved characters to their hexa...
web_proxy represents the concept of the web proxy, which can be auto-discovered, disabled, or specified explicitly by the user.
Definition: web_utilities.h:157
bool http_basic_auth() const
Get HTTP Basic authentication setting for token endpoint.
Definition: oauth2.h:427
const std::shared_ptr< http_pipeline_stage > & next_stage() const
Gets the next stage in the pipeline.
Definition: http_msg.h:1327
const uri & request_uri() const
Get the underling URI of the request message.
Definition: http_msg.h:808
const utility::string_t & client_key() const
Get client key.
Definition: oauth2.h:305
int64_t expires_in() const
Get the lifetime of the access token in seconds. For example, 3600 means the access token will expire...
Definition: oauth2.h:158
void set_refresh_token(utility::string_t refresh_token)
Set refresh token.
Definition: oauth2.h:126
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: pplxtasks.h:176
_ASYNCRTIMP pplx::task< void > token_from_redirected_uri(const web::http::uri &redirected_uri)
Fetch an access token (and possibly a refresh token) based on redirected URI. Behavior depends on the...
void set_client_key(utility::string_t client_key)
Set client key.
Definition: oauth2.h:310
virtual pplx::task< http_response > propagate(http_request request) override
Runs this stage against the given request and passes onto the next stage.
Definition: oauth2.h:528
void set_scope(utility::string_t scope)
Set scope for authorization for token.
Definition: oauth2.h:365
void set_scope(utility::string_t scope)
Set token scope.
Definition: oauth2.h:148
A JSON value represented as a C++ class.
Definition: json.h:83
Nonce string generator class.
Definition: asyncrt_utils.h:555
const utility::string_t & token_type() const
Get token type.
Definition: oauth2.h:132
_ASYNCRTIMP utility::string_t build_authorization_uri(bool generate_state)
Builds an authorization URI to be loaded in the web browser/view. The URI is built with auth_endpoint...
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: pplxtasks.h:4173
void set_implicit_grant(bool implicit_grant)
Set implicit grant setting for authorization. False means authorization code grant is used for author...
Definition: oauth2.h:406
Represents an HTTP request.
Definition: http_msg.h:771
bool is_enabled() const
Returns enabled state of the configuration. The oauth2_handler will perform OAuth 2...
Definition: oauth2.h:299
bool implicit_grant() const
Get implicit grant setting for authorization.
Definition: oauth2.h:398
void set_bearer_auth(bool bearer_auth)
Set bearer token authentication setting. This must be selected based on what the service accepts...
Definition: oauth2.h:421
void set_redirect_uri(utility::string_t redirect_uri)
Set redirect URI string.
Definition: oauth2.h:354
Builder for constructing URIs incrementally.
Definition: uri_builder.h:40
_ASYNCRTIMP uri_builder & append_query(const utility::string_t &query, bool do_encoding=false)
Appends another query to the query of this uri_builder.
const utility::string_t & state()
Get client state string used in authorization.
Definition: oauth2.h:371
const utility::string_t & refresh_token() const
Get refresh token.
Definition: oauth2.h:121
pplx::task< void > token_from_refresh()
Fetches a new access token (and possibly a new refresh token) using the refresh token. The task creates a HTTP request to the token_endpoint(). If successful, resulting access token is set as active via set_token(). See: http://tools.ietf.org/html/rfc6749#section-6 This also sets a new refresh token if one was returned.
Definition: oauth2.h:284
const utility::string_t & scope() const
Get scope used in authorization for token.
Definition: oauth2.h:360
_ASYNCRTIMP std::string __cdecl to_utf8string(std::string value)
Converts to a UTF-8 string.
Exception type for OAuth 2.0 errors.
Definition: oauth2.h:71