diff options
author | rickcam@chromium.org <rickcam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-19 23:40:35 +0000 |
---|---|---|
committer | rickcam@chromium.org <rickcam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-19 23:40:35 +0000 |
commit | 69c14c30e724c382358018e511a66641386e90c8 (patch) | |
tree | 53b97e96fd8898fe568dcfb22c5decb2ac3a78aa /chrome/common/net/gaia | |
parent | 35ba9a9d325192b74dd3957df992ae6043a2fb44 (diff) | |
download | chromium_src-69c14c30e724c382358018e511a66641386e90c8.zip chromium_src-69c14c30e724c382358018e511a66641386e90c8.tar.gz chromium_src-69c14c30e724c382358018e511a66641386e90c8.tar.bz2 |
Adds the OAuthRequestSigner class to facilitate OAuth integration
BUG=86223
TEST=none
Review URL: http://codereview.chromium.org/7171023
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@89632 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/net/gaia')
-rw-r--r-- | chrome/common/net/gaia/oauth_request_signer.cc | 379 | ||||
-rw-r--r-- | chrome/common/net/gaia/oauth_request_signer.h | 69 | ||||
-rw-r--r-- | chrome/common/net/gaia/oauth_request_signer_unittest.cc | 228 |
3 files changed, 676 insertions, 0 deletions
diff --git a/chrome/common/net/gaia/oauth_request_signer.cc b/chrome/common/net/gaia/oauth_request_signer.cc new file mode 100644 index 0000000..85f1c0d --- /dev/null +++ b/chrome/common/net/gaia/oauth_request_signer.cc @@ -0,0 +1,379 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/net/gaia/oauth_request_signer.h" + +#include <cctype> +#include <cstdlib> +#include <ctime> +#include <map> +#include <string> + +#include "base/base64.h" +#include "base/format_macros.h" +#include "base/logging.h" +#include "base/rand_util.h" +#include "base/stringprintf.h" +#include "base/time.h" +#include "crypto/hmac.h" +#include "googleurl/src/gurl.h" + +namespace { + +static const int kHexBase = 16; +static char kHexDigits[] = "0123456789ABCDEF"; + +static const int kMaxNonceLength = 30; +static const int kMinNonceLength = 15; + +static const char kOAuthConsumerKeyLabel[] = "oauth_consumer_key"; +static const char kOAuthConsumerSecretLabel[] = "oauth_consumer_secret"; +static const char kOAuthNonceCharacters[] = + "abcdefghijklmnopqrstuvwyz" + "ABCDEFGHIJKLMNOPQRSTUVWYZ" + "0123456789_"; +static const char kOAuthNonceLabel[] = "oauth_nonce"; +static const char kOAuthSignatureLabel[] = "oauth_signature"; +static const char kOAuthSignatureMethodLabel[] = "oauth_signature_method"; +static const char kOAuthTimestampLabel[] = "oauth_timestamp"; +static const char kOAuthTokenLabel[] = "oauth_token"; +static const char kOAuthTokenSecretLabel[] = "oauth_token_secret"; +static const char kOAuthVersion[] = "1.0"; +static const char kOAuthVersionLabel[] = "oauth_version"; + +enum ParseQueryState { + START_STATE, + KEYWORD_STATE, + VALUE_STATE, +}; + +const std::string HttpMethodName(OAuthRequestSigner::HttpMethod method) { + switch (method) { + case OAuthRequestSigner::GET_METHOD: + return "GET"; + case OAuthRequestSigner::POST_METHOD: + return "POST"; + } + NOTREACHED(); + return *(new std::string()); +} + +const std::string SignatureMethodName( + OAuthRequestSigner::SignatureMethod method) { + switch (method) { + case OAuthRequestSigner::HMAC_SHA1_SIGNATURE: + return "HMAC-SHA1"; + case OAuthRequestSigner::RSA_SHA1_SIGNATURE: + return "RSA-SHA1"; + case OAuthRequestSigner::PLAINTEXT_SIGNATURE: + return "PLAINTEXT"; + } + NOTREACHED(); + return *(new std::string()); +} + +// The form of percent encoding used for OAuth request signing is very +// specific and strict. See http://oauth.net/core/1.0/#encoding_parameters. +// +// Any character which is in the "unreserved set" must not be encoded. +// All other characters must be encoded. +// +// The unreserved set is comprised of the alphanumeric characters and these +// others: +// - minus (-) +// - period (.) +// - underscore (_) +// - tilde (~) +std::string EncodedOAuthParameter(const std::string& text) { + std::string result = ""; + std::string::const_iterator cursor; + std::string::const_iterator limit; + for (limit = text.end(), cursor = text.begin(); cursor != limit; ++cursor) { + char character = *cursor; + if (isalnum(character)) { + result += character; + } else { + switch (character) { + case '-': + case '.': + case '_': + case '~': + result += character; + break; + default: + unsigned char byte = static_cast<unsigned char>(character); + result = result + '%' + kHexDigits[byte / kHexBase] + + kHexDigits[byte % kHexBase]; + } + } + } + return result; +} + +std::string BuildBaseString(const GURL& request_base_url, + OAuthRequestSigner::HttpMethod http_method, + const std::string base_parameters) { + return StringPrintf("%s&%s&%s", + HttpMethodName(http_method).c_str(), + EncodedOAuthParameter(request_base_url.spec()).c_str(), + EncodedOAuthParameter(base_parameters).c_str()); +} + +std::string BuildBaseStringParameters( + const OAuthRequestSigner::Parameters& parameters) { + std::string result = ""; + OAuthRequestSigner::Parameters::const_iterator cursor; + OAuthRequestSigner::Parameters::const_iterator limit; + bool first = true; + for (cursor = parameters.begin(), limit = parameters.end(); + cursor != limit; + ++cursor) { + if (first) { + first = false; + } else { + result += '&'; + } + result += EncodedOAuthParameter(cursor->first); + result += '='; + result += EncodedOAuthParameter(cursor->second); + } + return result; +} + +std::string GenerateNonce() { + char result[kMaxNonceLength + 1]; + int length = base::RandUint64() % (kMaxNonceLength - kMinNonceLength + 1) + + kMinNonceLength; + result[length] = '\0'; + for (int index = 0; index < length; ++index) + result[index] = kOAuthNonceCharacters[ + base::RandUint64() % (sizeof(kOAuthNonceCharacters) - 1)]; + return result; +} + +std::string GenerateTimestamp() { + return base::StringPrintf( + "%" PRId64, + (base::Time::NowFromSystemTime() - base::Time::UnixEpoch()).InSeconds()); +} + +// Creates a string-to-string, keyword-value map from a parameter/query string +// that uses ampersand (&) to seperate paris and equals (=) to seperate +// keyword from value. +bool ParseQuery(const std::string& query, + OAuthRequestSigner::Parameters* parameters_result) { + std::string::const_iterator cursor; + std::string keyword; + std::string::const_iterator limit; + OAuthRequestSigner::Parameters parameters; + ParseQueryState state; + std::string value; + + state = START_STATE; + for (cursor = query.begin(), limit = query.end(); + cursor != limit; + ++cursor) { + char character = *cursor; + switch (state) { + case KEYWORD_STATE: + switch (character) { + case '&': + parameters[keyword] = value; + keyword = ""; + value = ""; + state = START_STATE; + break; + case '=': + state = VALUE_STATE; + break; + default: + keyword += character; + } + break; + case START_STATE: + switch (character) { + case '&': // Intentionally falling through + case '=': + return false; + default: + keyword += character; + state = KEYWORD_STATE; + } + break; + case VALUE_STATE: + switch (character) { + case '=': + return false; + case '&': + parameters[keyword] = value; + keyword = ""; + value = ""; + state = START_STATE; + break; + default: + value += character; + } + break; + } + } + switch (state) { + case START_STATE: + break; + case KEYWORD_STATE: // Intentionally falling through + case VALUE_STATE: + parameters[keyword] = value; + break; + default: + NOTREACHED(); + } + *parameters_result = parameters; + return true; +} + +// Creates the value for the oauth_signature parameter when the +// oauth_signature_method is HMAC-SHA1. +bool SignHmacSha1(const std::string& text, + const std::string& key, + std::string* signature_return) { + crypto::HMAC hmac(crypto::HMAC::SHA1); + size_t digest_length = hmac.DigestLength(); + unsigned char* digest = new unsigned char [digest_length]; + hmac.Init(key); + return hmac.Sign(text, digest, digest_length) && + base::Base64Encode(std::string(reinterpret_cast<const char*>(digest), + digest_length), + signature_return); +} + +// Creates the value for the oauth_signature parameter when the +// oauth_signature_method is PLAINTEXT. +// +// Not yet implemented, and might never be. +bool SignPlaintext(const std::string& text, + const std::string& key, + std::string* result) { + NOTIMPLEMENTED(); + return false; +} + +// Creates the value for the oauth_signature parameter when the +// oauth_signature_method is RSA-SHA1. +// +// Not yet implemented, and might never be. +bool SignRsaSha1(const std::string& text, + const std::string& key, + std::string* result) { + NOTIMPLEMENTED(); + return false; +} + +} // namespace + +// static +bool OAuthRequestSigner::ParseAndSign(const GURL& request_url_with_parameters, + SignatureMethod signature_method, + HttpMethod http_method, + const std::string& consumer_key, + const std::string& consumer_secret, + const std::string& token_key, + const std::string& token_secret, + std::string* result) { + DCHECK(request_url_with_parameters.is_valid()); + Parameters parameters; + if (request_url_with_parameters.has_query()) { + const std::string& query = request_url_with_parameters.query(); + if (!query.empty()) { + if (!ParseQuery(query, ¶meters)) + return false; + } + } + std::string spec = request_url_with_parameters.spec(); + std::string url_without_parameters = spec; + std::string::size_type question = spec.find("?"); + if (question != std::string::npos) { + url_without_parameters = spec.substr(0,question); + } + return Sign (GURL(url_without_parameters), parameters, signature_method, + http_method, consumer_key, consumer_secret, token_key, + token_secret, result); +} + +// Returns a copy of request_parameters, with parameters that are required by +// OAuth added as needed. +OAuthRequestSigner::Parameters +PrepareParameters(const OAuthRequestSigner::Parameters& request_parameters, + OAuthRequestSigner::SignatureMethod signature_method, + OAuthRequestSigner::HttpMethod http_method, + const std::string& consumer_key, + const std::string& token_key) { + OAuthRequestSigner::Parameters result(request_parameters); + + if (result.find(kOAuthNonceLabel) == result.end()) + result[kOAuthNonceLabel] = GenerateNonce(); + + if (result.find(kOAuthTimestampLabel) == result.end()) + result[kOAuthTimestampLabel] = GenerateTimestamp(); + + result[kOAuthConsumerKeyLabel] = consumer_key; + result[kOAuthSignatureMethodLabel] = SignatureMethodName(signature_method); + result[kOAuthTokenLabel] = token_key; + result[kOAuthVersionLabel] = kOAuthVersion; + + return result; +} + +// static +bool OAuthRequestSigner::Sign( + const GURL& request_base_url, + const Parameters& request_parameters, + SignatureMethod signature_method, + HttpMethod http_method, + const std::string& consumer_key, + const std::string& consumer_secret, + const std::string& token_key, + const std::string& token_secret, + std::string* signed_text_return) { + DCHECK(request_base_url.is_valid()); + Parameters parameters = PrepareParameters(request_parameters, + signature_method, + http_method, + consumer_key, + token_key); + std::string base_parameters = BuildBaseStringParameters(parameters); + std::string base = BuildBaseString(request_base_url, + http_method, + base_parameters); + std::string key = consumer_secret + '&' + token_secret; + bool is_signed = false; + std::string signature; + switch (signature_method) { + case HMAC_SHA1_SIGNATURE: + is_signed = SignHmacSha1(base, key, &signature); + break; + case RSA_SHA1_SIGNATURE: + is_signed = SignRsaSha1(base, key, &signature); + break; + case PLAINTEXT_SIGNATURE: + is_signed = SignPlaintext(base, key, &signature); + break; + default: + NOTREACHED(); + } + if (is_signed) { + std::string signed_text; + switch (http_method) { + case GET_METHOD: + signed_text = request_base_url.spec() + '?'; + // Intentionally falling through + case POST_METHOD: + signed_text += base_parameters + '&' + kOAuthSignatureLabel + '=' + + EncodedOAuthParameter(signature); + break; + default: + NOTREACHED(); + } + *signed_text_return = signed_text; + } + return is_signed; +} diff --git a/chrome/common/net/gaia/oauth_request_signer.h b/chrome/common/net/gaia/oauth_request_signer.h new file mode 100644 index 0000000..ecc386b --- /dev/null +++ b/chrome/common/net/gaia/oauth_request_signer.h @@ -0,0 +1,69 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_COMMON_NET_GAIA_OAUTH_REQUEST_SIGNER_H_ +#define CHROME_COMMON_NET_GAIA_OAUTH_REQUEST_SIGNER_H_ +#pragma once + +#include <map> +#include <string> + +#include "base/basictypes.h" + +class GURL; + +// Implements the OAuth request signing process as described here: +// http://oauth.net/core/1.0/#signing_process +// +// NOTE: Currently the only supported SignatureMethod is HMAC_SHA1_SIGNATURE +class OAuthRequestSigner { + public: + enum SignatureMethod { + HMAC_SHA1_SIGNATURE, + RSA_SHA1_SIGNATURE, + PLAINTEXT_SIGNATURE + }; + + enum HttpMethod { + GET_METHOD, + POST_METHOD + }; + + typedef std::map<std::string,std::string> Parameters; + + // Signs a request specified as URL string, complete with parameters. + // + // If HttpMethod is GET_METHOD, the signed result is the full URL, otherwise + // it is the request parameters, including the oauth_signature field. + static bool ParseAndSign(const GURL& request_url_with_parameters, + SignatureMethod signature_method, + HttpMethod http_method, + const std::string& consumer_key, + const std::string& consumer_secret, + const std::string& token_key, + const std::string& token_secret, + std::string* signed_result); + + // Signs a request specified as the combination of a base URL string, with + // parameters included in a separate map data structure. NOTE: The base URL + // string must not contain a question mark (?) character. If it does, + // you can use ParseAndSign() instead. + // + // If HttpMethod is GET_METHOD, the signed result is the full URL, otherwise + // it is the request parameters, including the oauth_signature field. + static bool Sign(const GURL& request_base_url, + const Parameters& parameters, + SignatureMethod signature_method, + HttpMethod http_method, + const std::string& consumer_key, + const std::string& consumer_secret, + const std::string& token_key, + const std::string& token_secret, + std::string* signed_result); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(OAuthRequestSigner); +}; + +#endif // CHROME_COMMON_NET_GAIA_OAUTH_REQUEST_SIGNER_H_ diff --git a/chrome/common/net/gaia/oauth_request_signer_unittest.cc b/chrome/common/net/gaia/oauth_request_signer_unittest.cc new file mode 100644 index 0000000..eb531f1 --- /dev/null +++ b/chrome/common/net/gaia/oauth_request_signer_unittest.cc @@ -0,0 +1,228 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/net/gaia/oauth_request_signer.h" + +#include "googleurl/src/gurl.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(OAuthRequestSignerTest, SignGet1) { + GURL request_url("https://www.google.com/accounts/o8/GetOAuthToken"); + OAuthRequestSigner::Parameters parameters; + parameters["scope"] = "https://www.google.com/accounts/OAuthLogin"; + parameters["oauth_nonce"] = "2oiE_aHdk5qRTz0L9C8Lq0g"; + parameters["xaouth_display_name"] = "Chromium"; + parameters["oauth_timestamp"] = "1308152953"; + std::string signed_text; + ASSERT_TRUE(OAuthRequestSigner::Sign( + request_url, + parameters, + OAuthRequestSigner::HMAC_SHA1_SIGNATURE, + OAuthRequestSigner::GET_METHOD, + "johndoe", // oauth_consumer_key + "53cR3t", // consumer secret + "4/VGY0MsQadcmO8VnCv9gnhoEooq1v", // oauth_token + "c5e0531ff55dfbb4054e", // token secret + &signed_text)); + ASSERT_EQ("https://www.google.com/accounts/o8/GetOAuthToken" + "?oauth_consumer_key=johndoe" + "&oauth_nonce=2oiE_aHdk5qRTz0L9C8Lq0g" + "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=1308152953" + "&oauth_token=4%2FVGY0MsQadcmO8VnCv9gnhoEooq1v" + "&oauth_version=1.0" + "&scope=https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthLogin" + "&xaouth_display_name=Chromium" + "&oauth_signature=y9GCmlGSvNuTAotxsBMyxb6j%2BE8%3D", + signed_text); +} + +TEST(OAuthRequestSignerTest, SignGet2) { + GURL request_url("https://www.google.com/accounts/OAuthGetAccessToken"); + OAuthRequestSigner::Parameters parameters; + parameters["oauth_timestamp"] = "1308147831"; + parameters["oauth_nonce"] = "4d4hZW9DygWQujP2tz06UN"; + std::string signed_text; + ASSERT_TRUE(OAuthRequestSigner::Sign( + request_url, + parameters, + OAuthRequestSigner::HMAC_SHA1_SIGNATURE, + OAuthRequestSigner::GET_METHOD, + "anonymous", // oauth_consumer_key + "anonymous", // consumer secret + "4/CcC-hgdj1TNnWaX8NTQ76YDXCBEK", // oauth_token + "", // token secret + &signed_text)); + ASSERT_EQ(signed_text, + "https://www.google.com/accounts/OAuthGetAccessToken" + "?oauth_consumer_key=anonymous" + "&oauth_nonce=4d4hZW9DygWQujP2tz06UN" + "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=1308147831" + "&oauth_token=4%2FCcC-hgdj1TNnWaX8NTQ76YDXCBEK" + "&oauth_version=1.0" + "&oauth_signature=2KVN8YCOKgiNIA16EGTcfESvdvA%3D"); +} + +TEST(OAuthRequestSignerTest, ParseAndSignGet1) { + GURL request_url("https://www.google.com/accounts/o8/GetOAuthToken" + "?scope=https://www.google.com/accounts/OAuthLogin" + "&oauth_nonce=2oiE_aHdk5qRTz0L9C8Lq0g" + "&xaouth_display_name=Chromium" + "&oauth_timestamp=1308152953"); + std::string signed_text; + ASSERT_TRUE(OAuthRequestSigner::ParseAndSign( + request_url, + OAuthRequestSigner::HMAC_SHA1_SIGNATURE, + OAuthRequestSigner::GET_METHOD, + "anonymous", // oauth_consumer_key + "anonymous", // consumer secret + "4/CcC-hgdj1TNnWaX8NTQ76YDXCBEK", // oauth_token + "", // token secret + &signed_text)); + ASSERT_EQ("https://www.google.com/accounts/o8/GetOAuthToken" + "?oauth_consumer_key=anonymous" + "&oauth_nonce=2oiE_aHdk5qRTz0L9C8Lq0g" + "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=1308152953" + "&oauth_token=4%2FCcC-hgdj1TNnWaX8NTQ76YDXCBEK" + "&oauth_version=1.0" + "&scope=https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthLogin" + "&xaouth_display_name=Chromium" + "&oauth_signature=S%2B6dcftDfbINlavHuma4NLJ98Ys%3D", + signed_text); +} + +TEST(OAuthRequestSignerTest, ParseAndSignGet2) { + GURL request_url("https://www.google.com/accounts/OAuthGetAccessToken" + "?oauth_timestamp=1308147831" + "&oauth_nonce=4d4hZW9DygWQujP2tz06UN"); + std::string signed_text; + ASSERT_TRUE(OAuthRequestSigner::ParseAndSign( + request_url, + OAuthRequestSigner::HMAC_SHA1_SIGNATURE, + OAuthRequestSigner::GET_METHOD, + "anonymous", // oauth_consumer_key + "anonymous", // consumer secret + "4/CcC-hgdj1TNnWaX8NTQ76YDXCBEK", // oauth_token + "", // token secret + &signed_text)); + ASSERT_EQ(signed_text, + "https://www.google.com/accounts/OAuthGetAccessToken" + "?oauth_consumer_key=anonymous" + "&oauth_nonce=4d4hZW9DygWQujP2tz06UN" + "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=1308147831" + "&oauth_token=4%2FCcC-hgdj1TNnWaX8NTQ76YDXCBEK" + "&oauth_version=1.0" + "&oauth_signature=2KVN8YCOKgiNIA16EGTcfESvdvA%3D"); +} + +TEST(OAuthRequestSignerTest, SignPost1) { + GURL request_url("https://www.google.com/accounts/o8/GetOAuthToken"); + OAuthRequestSigner::Parameters parameters; + parameters["scope"] = "https://www.google.com/accounts/OAuthLogin"; + parameters["oauth_nonce"] = "2oiE_aHdk5qRTz0L9C8Lq0g"; + parameters["xaouth_display_name"] = "Chromium"; + parameters["oauth_timestamp"] = "1308152953"; + std::string signed_text; + ASSERT_TRUE(OAuthRequestSigner::Sign( + request_url, + parameters, + OAuthRequestSigner::HMAC_SHA1_SIGNATURE, + OAuthRequestSigner::POST_METHOD, + "anonymous", // oauth_consumer_key + "anonymous", // consumer secret + "4/X8x0r7bHif_VNCLjUMutxGkzo13d", // oauth_token + "b7120598d47594bd3522", // token secret + &signed_text)); + ASSERT_EQ("oauth_consumer_key=anonymous" + "&oauth_nonce=2oiE_aHdk5qRTz0L9C8Lq0g" + "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=1308152953" + "&oauth_token=4%2FX8x0r7bHif_VNCLjUMutxGkzo13d" + "&oauth_version=1.0" + "&scope=https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthLogin" + "&xaouth_display_name=Chromium" + "&oauth_signature=F%2BINyO4xgon5wUxcdcxWC11Ep7Y%3D", + signed_text); +} + +TEST(OAuthRequestSignerTest, SignPost2) { + GURL request_url("https://www.google.com/accounts/OAuthGetAccessToken"); + OAuthRequestSigner::Parameters parameters; + parameters["oauth_timestamp"] = "1234567890"; + parameters["oauth_nonce"] = "17171717171717171"; + std::string signed_text; + ASSERT_TRUE(OAuthRequestSigner::Sign( + request_url, + parameters, + OAuthRequestSigner::HMAC_SHA1_SIGNATURE, + OAuthRequestSigner::POST_METHOD, + "anonymous", // oauth_consumer_key + "anonymous", // consumer secret + "4/CcC-hgdj1TNnWaX8NTQ76YDXCBEK", // oauth_token + "", // token secret + &signed_text)); + ASSERT_EQ(signed_text, + "oauth_consumer_key=anonymous" + "&oauth_nonce=17171717171717171" + "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=1234567890" + "&oauth_token=4%2FCcC-hgdj1TNnWaX8NTQ76YDXCBEK" + "&oauth_version=1.0" + "&oauth_signature=BIuPHITrcptxSefd8H9Iazo8Pmo%3D"); +} + +TEST(OAuthRequestSignerTest, ParseAndSignPost1) { + GURL request_url("https://www.google.com/accounts/o8/GetOAuthToken" + "?scope=https://www.google.com/accounts/OAuthLogin" + "&oauth_nonce=2oiE_aHdk5qRTz0L9C8Lq0g" + "&xaouth_display_name=Chromium" + "&oauth_timestamp=1308152953"); + std::string signed_text; + ASSERT_TRUE(OAuthRequestSigner::ParseAndSign( + request_url, + OAuthRequestSigner::HMAC_SHA1_SIGNATURE, + OAuthRequestSigner::POST_METHOD, + "anonymous", // oauth_consumer_key + "anonymous", // consumer secret + "4/X8x0r7bHif_VNCLjUMutxGkzo13d", // oauth_token + "b7120598d47594bd3522", // token secret + &signed_text)); + ASSERT_EQ("oauth_consumer_key=anonymous" + "&oauth_nonce=2oiE_aHdk5qRTz0L9C8Lq0g" + "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=1308152953" + "&oauth_token=4%2FX8x0r7bHif_VNCLjUMutxGkzo13d" + "&oauth_version=1.0" + "&scope=https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthLogin" + "&xaouth_display_name=Chromium" + "&oauth_signature=F%2BINyO4xgon5wUxcdcxWC11Ep7Y%3D", + signed_text); +} + +TEST(OAuthRequestSignerTest, ParseAndSignPost2) { + GURL request_url("https://www.google.com/accounts/OAuthGetAccessToken" + "?oauth_timestamp=1234567890" + "&oauth_nonce=17171717171717171"); + std::string signed_text; + ASSERT_TRUE(OAuthRequestSigner::ParseAndSign( + request_url, + OAuthRequestSigner::HMAC_SHA1_SIGNATURE, + OAuthRequestSigner::POST_METHOD, + "anonymous", // oauth_consumer_key + "anonymous", // consumer secret + "4/CcC-hgdj1TNnWaX8NTQ76YDXCBEK", // oauth_token + "", // token secret + &signed_text)); + ASSERT_EQ(signed_text, + "oauth_consumer_key=anonymous" + "&oauth_nonce=17171717171717171" + "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=1234567890" + "&oauth_token=4%2FCcC-hgdj1TNnWaX8NTQ76YDXCBEK" + "&oauth_version=1.0" + "&oauth_signature=BIuPHITrcptxSefd8H9Iazo8Pmo%3D"); +} |