15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/oauth_request_signer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cctype>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstddef>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstdlib>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstring>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctime>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base64.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/hmac.h"
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kHexBase = 16;
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)char kHexDigits[] = "0123456789ABCDEF";
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const size_t kHmacDigestLength = 20;
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kMaxNonceLength = 30;
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kMinNonceLength = 15;
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kOAuthConsumerKeyLabel[] = "oauth_consumer_key";
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kOAuthNonceCharacters[] =
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "abcdefghijklmnopqrstuvwyz"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "ABCDEFGHIJKLMNOPQRSTUVWYZ"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "0123456789_";
3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kOAuthNonceLabel[] = "oauth_nonce";
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kOAuthSignatureLabel[] = "oauth_signature";
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kOAuthSignatureMethodLabel[] = "oauth_signature_method";
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kOAuthTimestampLabel[] = "oauth_timestamp";
4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kOAuthTokenLabel[] = "oauth_token";
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kOAuthVersion[] = "1.0";
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kOAuthVersionLabel[] = "oauth_version";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ParseQueryState {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  START_STATE,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  KEYWORD_STATE,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VALUE_STATE,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string HttpMethodName(OAuthRequestSigner::HttpMethod method) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (method) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OAuthRequestSigner::GET_METHOD:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "GET";
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OAuthRequestSigner::POST_METHOD:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "POST";
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string SignatureMethodName(
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OAuthRequestSigner::SignatureMethod method) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (method) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OAuthRequestSigner::HMAC_SHA1_SIGNATURE:
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "HMAC-SHA1";
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OAuthRequestSigner::RSA_SHA1_SIGNATURE:
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "RSA-SHA1";
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OAuthRequestSigner::PLAINTEXT_SIGNATURE:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "PLAINTEXT";
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string BuildBaseString(const GURL& request_base_url,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            OAuthRequestSigner::HttpMethod http_method,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& base_parameters) {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::StringPrintf("%s&%s&%s",
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            HttpMethodName(http_method).c_str(),
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            OAuthRequestSigner::Encode(
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                request_base_url.spec()).c_str(),
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            OAuthRequestSigner::Encode(
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                base_parameters).c_str());
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string BuildBaseStringParameters(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OAuthRequestSigner::Parameters& parameters) {
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string result;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OAuthRequestSigner::Parameters::const_iterator cursor;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OAuthRequestSigner::Parameters::const_iterator limit;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool first = true;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (cursor = parameters.begin(), limit = parameters.end();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       cursor != limit;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++cursor) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (first)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      first = false;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result += '&';
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result += OAuthRequestSigner::Encode(cursor->first);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result += '=';
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result += OAuthRequestSigner::Encode(cursor->second);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GenerateNonce() {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char result[kMaxNonceLength + 1];
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int length = base::RandUint64() % (kMaxNonceLength - kMinNonceLength + 1) +
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kMinNonceLength;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result[length] = '\0';
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int index = 0; index < length; ++index)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result[index] = kOAuthNonceCharacters[
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::RandUint64() % (sizeof(kOAuthNonceCharacters) - 1)];
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GenerateTimestamp() {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::StringPrintf(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "%" PRId64,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (base::Time::NowFromSystemTime() - base::Time::UnixEpoch()).InSeconds());
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a string-to-string, keyword-value map from a parameter/query string
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that uses ampersand (&) to seperate paris and equals (=) to seperate
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// keyword from value.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseQuery(const std::string& query,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                OAuthRequestSigner::Parameters* parameters_result) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator cursor;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string keyword;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator limit;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OAuthRequestSigner::Parameters parameters;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParseQueryState state;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state = START_STATE;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (cursor = query.begin(), limit = query.end();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       cursor != limit;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++cursor) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char character = *cursor;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case KEYWORD_STATE:
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        switch (character) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          case '&':
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parameters[keyword] = value;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            keyword = "";
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            value = "";
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            state = START_STATE;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          case '=':
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            state = VALUE_STATE;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          default:
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            keyword += character;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case START_STATE:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        switch (character) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          case '&':  // Intentionally falling through
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          case '=':
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          default:
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            keyword += character;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            state = KEYWORD_STATE;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case VALUE_STATE:
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        switch (character) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          case '=':
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          case '&':
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parameters[keyword] = value;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            keyword = "";
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            value = "";
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            state = START_STATE;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          default:
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            value += character;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case START_STATE:
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case KEYWORD_STATE:  // Intentionally falling through
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VALUE_STATE:
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parameters[keyword] = value;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *parameters_result = parameters;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates the value for the oauth_signature parameter when the
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// oauth_signature_method is HMAC-SHA1.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SignHmacSha1(const std::string& text,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const std::string& key,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  std::string* signature_return) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crypto::HMAC hmac(crypto::HMAC::SHA1);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(hmac.DigestLength() == kHmacDigestLength);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char digest[kHmacDigestLength];
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = hmac.Init(key) &&
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      hmac.Sign(text, digest, kHmacDigestLength);
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (result) {
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::Base64Encode(
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        std::string(reinterpret_cast<const char*>(digest), kHmacDigestLength),
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        signature_return);
212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates the value for the oauth_signature parameter when the
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// oauth_signature_method is PLAINTEXT.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Not yet implemented, and might never be.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SignPlaintext(const std::string& text,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const std::string& key,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   std::string* result) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates the value for the oauth_signature parameter when the
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// oauth_signature_method is RSA-SHA1.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Not yet implemented, and might never be.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SignRsaSha1(const std::string& text,
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 const std::string& key,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 std::string* result) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adds parameters that are required by OAuth added as needed to |parameters|.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrepareParameters(OAuthRequestSigner::Parameters* parameters,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       OAuthRequestSigner::SignatureMethod signature_method,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       OAuthRequestSigner::HttpMethod http_method,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::string& consumer_key,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::string& token_key) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parameters->find(kOAuthNonceLabel) == parameters->end())
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*parameters)[kOAuthNonceLabel] = GenerateNonce();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parameters->find(kOAuthTimestampLabel) == parameters->end())
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*parameters)[kOAuthTimestampLabel] = GenerateTimestamp();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*parameters)[kOAuthConsumerKeyLabel] = consumer_key;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*parameters)[kOAuthSignatureMethodLabel] =
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SignatureMethodName(signature_method);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*parameters)[kOAuthTokenLabel] = token_key;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*parameters)[kOAuthVersionLabel] = kOAuthVersion;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implements shared signing logic, generating the signature and storing it in
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |parameters|. Returns true if the signature has been generated succesfully.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SignParameters(const GURL& request_base_url,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    OAuthRequestSigner::SignatureMethod signature_method,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    OAuthRequestSigner::HttpMethod http_method,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& consumer_key,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& consumer_secret,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& token_key,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& token_secret,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    OAuthRequestSigner::Parameters* parameters) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_base_url.is_valid());
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrepareParameters(parameters, signature_method, http_method,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    consumer_key, token_key);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string base_parameters = BuildBaseStringParameters(*parameters);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string base = BuildBaseString(request_base_url, http_method,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base_parameters);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key = consumer_secret + '&' + token_secret;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_signed = false;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string signature;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (signature_method) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OAuthRequestSigner::HMAC_SHA1_SIGNATURE:
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_signed = SignHmacSha1(base, key, &signature);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OAuthRequestSigner::RSA_SHA1_SIGNATURE:
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_signed = SignRsaSha1(base, key, &signature);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OAuthRequestSigner::PLAINTEXT_SIGNATURE:
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_signed = SignPlaintext(base, key, &signature);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_signed)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*parameters)[kOAuthSignatureLabel] = signature;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_signed;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OAuthRequestSigner::Decode(const std::string& text,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                std::string* decoded_text) {
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string accumulator;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator cursor;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator limit;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (limit = text.end(), cursor = text.begin(); cursor != limit; ++cursor) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char character = *cursor;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (character == '%') {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++cursor;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (cursor == limit)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char* first = strchr(kHexDigits, *cursor);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!first)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int high = first - kHexDigits;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(high >= 0 && high < kHexBase);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++cursor;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (cursor == limit)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char* second = strchr(kHexDigits, *cursor);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!second)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int low = second - kHexDigits;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(low >= 0 || low < kHexBase);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char decoded = static_cast<char>(high * kHexBase + low);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!(IsAsciiAlpha(decoded) || IsAsciiDigit(decoded)));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!(decoded && strchr("-._~", decoded)));
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      accumulator += decoded;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      accumulator += character;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *decoded_text = accumulator;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string OAuthRequestSigner::Encode(const std::string& text) {
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string result;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator cursor;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator limit;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (limit = text.end(), cursor = text.begin(); cursor != limit; ++cursor) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char character = *cursor;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsAsciiAlpha(character) || IsAsciiDigit(character)) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result += character;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (character) {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case '-':
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case '.':
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case '_':
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case '~':
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result += character;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          unsigned char byte = static_cast<unsigned char>(character);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result = result + '%' + kHexDigits[byte / kHexBase] +
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kHexDigits[byte % kHexBase];
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OAuthRequestSigner::ParseAndSign(const GURL& request_url_with_parameters,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      SignatureMethod signature_method,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      HttpMethod http_method,
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const std::string& consumer_key,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const std::string& consumer_secret,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const std::string& token_key,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const std::string& token_secret,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string* result) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_url_with_parameters.is_valid());
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Parameters parameters;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_url_with_parameters.has_query()) {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& query = request_url_with_parameters.query();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!query.empty()) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!ParseQuery(query, &parameters))
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string spec = request_url_with_parameters.spec();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_without_parameters = spec;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::size_type question = spec.find("?");
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (question != std::string::npos)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url_without_parameters = spec.substr(0,question);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SignURL(GURL(url_without_parameters), parameters, signature_method,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 http_method, consumer_key, consumer_secret, token_key,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 token_secret, result);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OAuthRequestSigner::SignURL(
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& request_base_url,
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Parameters& request_parameters,
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SignatureMethod signature_method,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpMethod http_method,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& consumer_key,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& consumer_secret,
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& token_key,
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& token_secret,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* signed_text_return) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_base_url.is_valid());
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Parameters parameters(request_parameters);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_signed = SignParameters(request_base_url, signature_method,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  http_method, consumer_key, consumer_secret,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  token_key, token_secret, &parameters);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_signed) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string signed_text;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (http_method) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case GET_METHOD:
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        signed_text = request_base_url.spec() + '?';
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Intentionally falling through
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case POST_METHOD:
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        signed_text += BuildBaseStringParameters(parameters);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *signed_text_return = signed_text;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_signed;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OAuthRequestSigner::SignAuthHeader(
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& request_base_url,
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Parameters& request_parameters,
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SignatureMethod signature_method,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpMethod http_method,
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& consumer_key,
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& consumer_secret,
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& token_key,
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& token_secret,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* signed_text_return) {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_base_url.is_valid());
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Parameters parameters(request_parameters);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_signed = SignParameters(request_base_url, signature_method,
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  http_method, consumer_key, consumer_secret,
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  token_key, token_secret, &parameters);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_signed) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string signed_text = "OAuth ";
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool first = true;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (Parameters::const_iterator param = parameters.begin();
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         param != parameters.end();
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ++param) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (first)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        first = false;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        signed_text += ", ";
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      signed_text +=
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::StringPrintf(
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              "%s=\"%s\"",
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              OAuthRequestSigner::Encode(param->first).c_str(),
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              OAuthRequestSigner::Encode(param->second).c_str());
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *signed_text_return = signed_text;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_signed;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
460