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.
oauth1.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 1.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_OAUTH1_H
28 #define _CASA_OAUTH1_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 oauth1
44 {
45 namespace details
46 {
47 
48 class oauth1_handler;
49 
50 // State currently used by oauth1_config to authenticate request.
51 // The state varies for every request (due to timestamp and nonce).
52 // The state also contains extra transmitted protocol parameters during
53 // authorization flow (i.e. 'oauth_callback' or 'oauth_verifier').
55 {
56 public:
57  oauth1_state(utility::string_t timestamp, utility::string_t nonce,
58  utility::string_t extra_key=utility::string_t(),
59  utility::string_t extra_value=utility::string_t()) :
60  m_timestamp(std::move(timestamp)),
61  m_nonce(std::move(nonce)),
62  m_extra_key(std::move(extra_key)),
63  m_extra_value(std::move(extra_value))
64  {}
65 
66  const utility::string_t& timestamp() const { return m_timestamp; }
67  void set_timestamp(utility::string_t timestamp) { m_timestamp = std::move(timestamp); }
68 
69  const utility::string_t& nonce() const { return m_nonce; }
70  void set_nonce(utility::string_t nonce) { m_nonce = std::move(nonce); }
71 
72  const utility::string_t& extra_key() const { return m_extra_key; }
73  void set_extra_key(utility::string_t key) { m_extra_key = std::move(key); }
74 
75  const utility::string_t& extra_value() const { return m_extra_value; }
76  void set_extra_value(utility::string_t value) { m_extra_value = std::move(value); }
77 
78 private:
79  utility::string_t m_timestamp;
80  utility::string_t m_nonce;
81  utility::string_t m_extra_key;
82  utility::string_t m_extra_value;
83 };
84 
85 // Constant strings for OAuth 1.0.
86 typedef utility::string_t oauth1_string;
88 {
89 public:
90 #define _OAUTH1_STRINGS
91 #define DAT(a_, b_) _ASYNCRTIMP static const oauth1_string a_;
92 #include "cpprest/details/http_constants.dat"
93 #undef _OAUTH1_STRINGS
94 #undef DAT
95 };
96 
97 } // namespace web::http::oauth1::details
98 
100 namespace experimental
101 {
102 
106 typedef utility::string_t oauth1_method;
108 {
109 public:
110 #define _OAUTH1_METHODS
111 #define DAT(a,b) _ASYNCRTIMP static const oauth1_method a;
112 #include "cpprest/details/http_constants.dat"
113 #undef _OAUTH1_METHODS
114 #undef DAT
115 };
116 
120 class oauth1_exception : public std::exception
121 {
122 public:
123  oauth1_exception(utility::string_t msg) : m_msg(utility::conversions::to_utf8string(std::move(msg))) {}
124  ~oauth1_exception() CPPREST_NOEXCEPT {}
125  const char* what() const CPPREST_NOEXCEPT { return m_msg.c_str(); }
126 
127 private:
128  std::string m_msg;
129 };
130 
135 {
136 public:
137 
142 
148  oauth1_token(utility::string_t access_token, utility::string_t secret) :
149  m_token(std::move(access_token)),
150  m_secret(std::move(secret))
151  {}
152 
158  bool is_valid_access_token() const { return !(access_token().empty() || secret().empty()); }
159 
164  const utility::string_t& access_token() const { return m_token; }
165 
170  void set_access_token(utility::string_t &&access_token) { m_token = std::move(access_token); }
171 
176  void set_access_token(const utility::string_t &access_token) { m_token = access_token; }
177 
182  const utility::string_t& secret() const { return m_secret; }
183 
188  void set_secret(utility::string_t &&secret) { m_secret = std::move(secret); }
189 
194  void set_secret(const utility::string_t &secret) { m_secret = secret; }
195 
200  const std::map<utility::string_t, utility::string_t> &additional_parameters() const { return m_additional_parameters; }
201 
207  void set_additional_parameter(utility::string_t &&paramName, utility::string_t &&paramValue)
208  {
209  m_additional_parameters[std::move(paramName)] = std::move(paramValue);
210  }
211 
217  void set_additional_parameter(const utility::string_t &paramName, const utility::string_t &paramValue)
218  {
219  m_additional_parameters[paramName] = paramValue;
220  }
221 
225  void clear_additional_parameters() { m_additional_parameters.clear(); }
226 
227 private:
228  friend class oauth1_config;
229 
230  utility::string_t m_token;
231  utility::string_t m_secret;
232  std::map<utility::string_t, utility::string_t> m_additional_parameters;
233 };
234 
239 {
240 public:
241  oauth1_config(utility::string_t consumer_key, utility::string_t consumer_secret,
242  utility::string_t temp_endpoint, utility::string_t auth_endpoint,
243  utility::string_t token_endpoint, utility::string_t callback_uri,
244  oauth1_method method, utility::string_t realm=utility::string_t()) :
245  m_consumer_key(std::move(consumer_key)),
246  m_consumer_secret(std::move(consumer_secret)),
247  m_temp_endpoint(std::move(temp_endpoint)),
248  m_auth_endpoint(std::move(auth_endpoint)),
249  m_token_endpoint(std::move(token_endpoint)),
250  m_callback_uri(std::move(callback_uri)),
251  m_realm(std::move(realm)),
252  m_method(std::move(method)),
253  m_is_authorization_completed(false)
254  {}
255 
264 
277  _ASYNCRTIMP pplx::task<void> token_from_redirected_uri(const web::http::uri& redirected_uri);
278 
287  pplx::task<void> token_from_verifier(utility::string_t verifier)
288  {
289  return _request_token(_generate_auth_state(details::oauth1_strings::verifier, std::move(verifier)), false);
290  }
291 
297  pplx::task<void> refresh_token(const utility::string_t &key)
298  {
299  return _request_token(_generate_auth_state(key, m_token.additional_parameters().at(key)), false);
300  }
301 
306  const utility::string_t& consumer_key() const { return m_consumer_key; }
311  void set_consumer_key(utility::string_t key) { m_consumer_key = std::move(key); }
312 
317  const utility::string_t& consumer_secret() const { return m_consumer_secret; }
322  void set_consumer_secret(utility::string_t secret) { m_consumer_secret = std::move(secret); }
323 
328  const utility::string_t& temp_endpoint() const { return m_temp_endpoint; }
333  void set_temp_endpoint(utility::string_t temp_endpoint) { m_temp_endpoint = std::move(temp_endpoint); }
334 
339  const utility::string_t& auth_endpoint() const { return m_auth_endpoint; }
344  void set_auth_endpoint(utility::string_t auth_endpoint) { m_auth_endpoint = std::move(auth_endpoint); }
345 
350  const utility::string_t& token_endpoint() const { return m_token_endpoint; }
355  void set_token_endpoint(utility::string_t token_endpoint) { m_token_endpoint = std::move(token_endpoint); }
356 
361  const utility::string_t& callback_uri() const { return m_callback_uri; }
366  void set_callback_uri(utility::string_t callback_uri) { m_callback_uri = std::move(callback_uri); }
367 
372  _ASYNCRTIMP const oauth1_token& token() const;
373 
379  {
380  m_token = std::move(token);
381  m_is_authorization_completed = true;
382  }
383 
388  const oauth1_method& method() const { return m_method; }
393  void set_method(oauth1_method method) { m_method = std::move(method); }
394 
399  const utility::string_t& realm() const { return m_realm; }
404  void set_realm(utility::string_t realm) { m_realm = std::move(realm); }
405 
414  bool is_enabled() const { return token().is_valid_access_token() && !(consumer_key().empty() || consumer_secret().empty()); }
415 
416  // Builds signature base string according to:
417  // http://tools.ietf.org/html/rfc5849#section-3.4.1.1
418  _ASYNCRTIMP utility::string_t _build_signature_base_string(http_request request, details::oauth1_state state) const;
419 
420  // Builds HMAC-SHA1 signature according to:
421  // http://tools.ietf.org/html/rfc5849#section-3.4.2
422  utility::string_t _build_hmac_sha1_signature(http_request request, details::oauth1_state state) const
423  {
424  auto text(_build_signature_base_string(std::move(request), std::move(state)));
425  auto digest(_hmac_sha1(_build_key(), std::move(text)));
426  auto signature(utility::conversions::to_base64(std::move(digest)));
427  return signature;
428  }
429 
430  // Builds PLAINTEXT signature according to:
431  // http://tools.ietf.org/html/rfc5849#section-3.4.4
432  utility::string_t _build_plaintext_signature() const
433  {
434  return _build_key();
435  }
436 
437  details::oauth1_state _generate_auth_state(utility::string_t extra_key, utility::string_t extra_value)
438  {
439  return details::oauth1_state(_generate_timestamp(), _generate_nonce(), std::move(extra_key), std::move(extra_value));
440  }
441 
442  details::oauth1_state _generate_auth_state()
443  {
444  return details::oauth1_state(_generate_timestamp(), _generate_nonce());
445  }
446 
451  const std::map<utility::string_t, utility::string_t>& parameters() const { return m_parameters_to_sign; }
452 
458  void add_parameter(const utility::string_t &key, const utility::string_t &value) { m_parameters_to_sign[key] = value; }
459 
465  void add_parameter(utility::string_t &&key, utility::string_t &&value) { m_parameters_to_sign[std::move(key)] = std::move(value); }
466 
471  void set_parameters(const std::map<utility::string_t, utility::string_t> &parameters)
472  {
473  m_parameters_to_sign.clear();
474  m_parameters_to_sign = parameters;
475  }
476 
480  void clear_parameters() { m_parameters_to_sign.clear(); }
481 
482 private:
485 
486  oauth1_config() :
487  m_is_authorization_completed(false)
488  {}
489 
490  utility::string_t _generate_nonce()
491  {
492  return m_nonce_generator.generate();
493  }
494 
495  static utility::string_t _generate_timestamp()
496  {
497  return utility::conversions::print_string(utility::datetime::utc_timestamp(), std::locale::classic());
498  }
499 
500  _ASYNCRTIMP static std::vector<unsigned char> __cdecl _hmac_sha1(const utility::string_t& key, const utility::string_t& data);
501 
502  static utility::string_t _build_base_string_uri(const uri& u);
503 
504  utility::string_t _build_normalized_parameters(web::http::uri u, const details::oauth1_state& state) const;
505 
506  utility::string_t _build_signature(http_request request, details::oauth1_state state) const;
507 
508  utility::string_t _build_key() const
509  {
510  return uri::encode_data_string(consumer_secret()) + _XPLATSTR("&") + uri::encode_data_string(m_token.secret());
511  }
512 
513  void _authenticate_request(http_request &req)
514  {
515  _authenticate_request(req, _generate_auth_state());
516  }
517 
518  _ASYNCRTIMP void _authenticate_request(http_request &req, details::oauth1_state state);
519 
520  _ASYNCRTIMP pplx::task<void> _request_token(details::oauth1_state state, bool is_temp_token_request);
521 
522  utility::string_t m_consumer_key;
523  utility::string_t m_consumer_secret;
524  oauth1_token m_token;
525 
526  utility::string_t m_temp_endpoint;
527  utility::string_t m_auth_endpoint;
528  utility::string_t m_token_endpoint;
529  utility::string_t m_callback_uri;
530  utility::string_t m_realm;
531  oauth1_method m_method;
532 
533  std::map<utility::string_t, utility::string_t> m_parameters_to_sign;
534 
535  utility::nonce_generator m_nonce_generator;
536  bool m_is_authorization_completed;
537 };
538 
539 } // namespace web::http::oauth1::experimental
540 
541 namespace details
542 {
543 
545 {
546 public:
547  oauth1_handler(std::shared_ptr<experimental::oauth1_config> cfg) :
548  m_config(std::move(cfg))
549  {}
550 
552  {
553  if (m_config)
554  {
555  m_config->_authenticate_request(request);
556  }
557  return next_stage()->propagate(request);
558  }
559 
560 private:
561  std::shared_ptr<experimental::oauth1_config> m_config;
562 };
563 
564 }}}}
565 
566 #endif
void clear_parameters()
Clears all parameters.
Definition: oauth1.h:480
const utility::string_t & temp_endpoint() const
Get temporary token endpoint URI string.
Definition: oauth1.h:328
oauth1_token()
Constructs an initially empty invalid access token.
Definition: oauth1.h:141
void add_parameter(const utility::string_t &key, const utility::string_t &value)
Adds a key value parameter.
Definition: oauth1.h:458
static interval_type utc_timestamp()
Returns seconds since Unix/POSIX time epoch at 01-01-1970 00:00:00. If time is before epoch...
Definition: asyncrt_utils.h:394
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
const utility::string_t & token_endpoint() const
Get token endpoint URI string.
Definition: oauth1.h:350
void clear_additional_parameters()
Clears all additional parameters.
Definition: oauth1.h:225
_ASYNCRTIMP utility::string_t __cdecl to_base64(const std::vector< unsigned char > &data)
Encode the given byte array into a base64 string
void set_auth_endpoint(utility::string_t auth_endpoint)
Set authorization endpoint URI string.
Definition: oauth1.h:344
Exception type for OAuth 1.0 errors.
Definition: oauth1.h:120
pplx::task< void > token_from_verifier(utility::string_t verifier)
Creates a task with HTTP request to fetch an access token from the token endpoint. The request exchanges a verifier code to an access token. If successful, the resulting token is set as active via set_token(). See: http://tools.ietf.org/html/rfc5849#section-2.3
Definition: oauth1.h:287
The web namespace contains functionality common to multiple protocols like HTTP and WebSockets...
Definition: base_uri.h:37
const std::map< utility::string_t, utility::string_t > & additional_parameters() const
Retrieves any additional parameters.
Definition: oauth1.h:200
void set_secret(utility::string_t &&secret)
Set token secret.
Definition: oauth1.h:188
const utility::string_t & consumer_secret() const
Get consumer secret used in authorization and authentication.
Definition: oauth1.h:317
const oauth1_method & method() const
Get signature method.
Definition: oauth1.h:388
HTTP client configuration class, used to set the possible configuration options used to create an htt...
Definition: http_client.h:90
bool is_valid_access_token() const
Get access token validity state. If true, token is a valid access token.
Definition: oauth1.h:158
const utility::string_t & callback_uri() const
Get callback URI string.
Definition: oauth1.h:361
void set_token_endpoint(utility::string_t token_endpoint)
Set token endpoint URI string.
Definition: oauth1.h:355
const utility::string_t & consumer_key() const
Get consumer key used in authorization and authentication.
Definition: oauth1.h:306
void set_additional_parameter(const utility::string_t &paramName, const utility::string_t &paramValue)
Sets a specific parameter additional parameter.
Definition: oauth1.h:217
void set_method(oauth1_method method)
Set signature method.
Definition: oauth1.h:393
utility::string_t method
Predefined method strings for the standard HTTP methods mentioned in the HTTP 1.1 specification...
Definition: http_msg.h:62
void set_consumer_key(utility::string_t key)
Set consumer key used in authorization and authentication.
Definition: oauth1.h:311
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...
void set_secret(const utility::string_t &secret)
Set token secret.
Definition: oauth1.h:194
const std::shared_ptr< http_pipeline_stage > & next_stage() const
Gets the next stage in the pipeline.
Definition: http_msg.h:1327
_ASYNCRTIMP utility::string_t generate()
Generate a nonce string containing random alphanumeric characters (A-Za-z0-9). Length of the generate...
OAuth 1.0 configuration class.
Definition: oauth1.h:238
const utility::string_t & realm() const
Get authentication realm.
Definition: oauth1.h:399
void set_token(oauth1_token token)
Set token.
Definition: oauth1.h:378
virtual pplx::task< http_response > propagate(http_request request) override
Runs this stage against the given request and passes onto the next stage.
Definition: oauth1.h:551
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: pplxtasks.h:176
const utility::string_t & access_token() const
Get access token.
Definition: oauth1.h:164
void add_parameter(utility::string_t &&key, utility::string_t &&value)
Adds a key value parameter.
Definition: oauth1.h:465
void set_additional_parameter(utility::string_t &&paramName, utility::string_t &&paramValue)
Sets a specific parameter additional parameter.
Definition: oauth1.h:207
void set_access_token(const utility::string_t &access_token)
Set access token.
Definition: oauth1.h:176
Nonce string generator class.
Definition: asyncrt_utils.h:555
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: pplxtasks.h:4173
_ASYNCRTIMP pplx::task< void > token_from_redirected_uri(const web::http::uri &redirected_uri)
Fetch an access token based on redirected URI. The URI is expected to contain 'oauth_verifier' parame...
Represents an HTTP request.
Definition: http_msg.h:771
const utility::string_t & auth_endpoint() const
Get authorization endpoint URI string.
Definition: oauth1.h:339
OAuth 1.0 token and associated information.
Definition: oauth1.h:134
pplx::task< void > refresh_token(const utility::string_t &key)
Creates a task with HTTP request to fetch an access token from the token endpoint. If successful, the resulting token is set as active via set_token().
Definition: oauth1.h:297
const utility::string_t & secret() const
Get token secret.
Definition: oauth1.h:182
const std::map< utility::string_t, utility::string_t > & parameters() const
Gets map of parameters to sign.
Definition: oauth1.h:451
_ASYNCRTIMP const oauth1_token & token() const
Get token.
void set_temp_endpoint(utility::string_t temp_endpoint)
Set temporary token endpoint URI string.
Definition: oauth1.h:333
void set_callback_uri(utility::string_t callback_uri)
Set callback URI string.
Definition: oauth1.h:366
bool is_enabled() const
Returns enabled state of the configuration. The oauth1_handler will perform OAuth 1...
Definition: oauth1.h:414
void set_realm(utility::string_t realm)
Set authentication realm.
Definition: oauth1.h:404
void set_access_token(utility::string_t &&access_token)
Set access token.
Definition: oauth1.h:170
void set_consumer_secret(utility::string_t secret)
Set consumer secret used in authorization and authentication.
Definition: oauth1.h:322
oauth1_token(utility::string_t access_token, utility::string_t secret)
Constructs a OAuth1 token from a given access token and secret.
Definition: oauth1.h:148
_ASYNCRTIMP pplx::task< utility::string_t > build_authorization_uri()
Builds an authorization URI to be loaded in a web browser/view. The URI is built with auth_endpoint()...
void set_parameters(const std::map< utility::string_t, utility::string_t > &parameters)
Sets entire map or parameters replacing all previously values.
Definition: oauth1.h:471
_ASYNCRTIMP std::string __cdecl to_utf8string(std::string value)
Converts to a UTF-8 string.
utility::string_t oauth1_method
Constant strings for OAuth 1.0 signature methods.
Definition: oauth1.h:106