From fc9bc05353e26d7d169402aeb4d4f248403cb420 Mon Sep 17 00:00:00 2001 From: "ajwong@chromium.org" Date: Wed, 25 May 2011 20:11:22 +0000 Subject: Wire in OAuth2 support into non-sandboxed connections in libjingle. BUG=none TEST=can connect w/o ClientLogin token. Review URL: http://codereview.chromium.org/7008003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86685 0039d316-1c4b-4281-b951-d872f2087c98 --- remoting/base/auth_token_util.cc | 34 +++++++++++++++ remoting/base/auth_token_util.h | 20 +++++++++ remoting/base/auth_token_util_unittest.cc | 36 +++++++++++++++ remoting/base/constants.cc | 5 +-- remoting/base/constants.h | 6 ++- remoting/client/chromoting_client.cc | 3 +- remoting/client/client_config.h | 1 + remoting/client/client_util.cc | 9 ++++ .../client/plugin/chromoting_scriptable_object.cc | 14 ++++-- .../client/plugin/chromoting_scriptable_object.h | 5 ++- remoting/host/chromoting_host.cc | 6 ++- remoting/host/host_config.cc | 3 +- remoting/host/host_config.h | 4 +- remoting/host/host_plugin.cc | 14 ++++-- remoting/host/simple_host_process.cc | 10 +++++ remoting/jingle_glue/jingle_client.cc | 7 ++- remoting/protocol/connection_to_host.cc | 4 +- remoting/protocol/connection_to_host.h | 1 + remoting/protocol/protocol_test_client.cc | 14 +++--- remoting/remoting.gyp | 3 ++ remoting/webapp/me2mom/choice.html | 14 +++++- remoting/webapp/me2mom/remoting.js | 51 +++++++++++++++++----- remoting/webapp/me2mom/remoting_session.html | 6 +-- remoting/webapp/me2mom/remoting_session.js | 3 +- 24 files changed, 229 insertions(+), 44 deletions(-) create mode 100644 remoting/base/auth_token_util.cc create mode 100644 remoting/base/auth_token_util.h create mode 100644 remoting/base/auth_token_util_unittest.cc (limited to 'remoting') diff --git a/remoting/base/auth_token_util.cc b/remoting/base/auth_token_util.cc new file mode 100644 index 0000000..45caa92 --- /dev/null +++ b/remoting/base/auth_token_util.cc @@ -0,0 +1,34 @@ +// 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 "remoting/base/auth_token_util.h" +#include "remoting/base/constants.h" + +namespace remoting { + +void ParseAuthTokenWithService(const std::string& auth_service_with_token, + std::string* auth_token, + std::string* auth_service) { + size_t delimiter_pos = auth_service_with_token.find(':'); + if (delimiter_pos == std::string::npos) { + // Legacy case: there is no delimiter. Assume the whole string is the + // auth_token, and that we're using the default service. + // + // TODO(ajwong): Remove this defaulting once all webclients are migrated. + // BUG:83897 + auth_token->assign(auth_service_with_token); + auth_service->assign(kChromotingTokenDefaultServiceName); + } else { + auth_service->assign(auth_service_with_token.substr(0, delimiter_pos)); + + // Make sure there is *something* after the delimiter before doing substr. + if (delimiter_pos < auth_service_with_token.size()) { + auth_token->assign(auth_service_with_token.substr(delimiter_pos + 1)); + } else { + auth_token->clear(); + } + } +} + +} // namespace remoting diff --git a/remoting/base/auth_token_util.h b/remoting/base/auth_token_util.h new file mode 100644 index 0000000..309a888 --- /dev/null +++ b/remoting/base/auth_token_util.h @@ -0,0 +1,20 @@ +// 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 REMOTING_BASE_AUTH_TOKEN_UTIL_H_ +#define REMOTING_BASE_AUTH_TOKEN_UTIL_H_ + +#include + +namespace remoting { + +// Given a string of the form "auth_service:auth_token" parses it into its +// component pieces. +void ParseAuthTokenWithService(const std::string& auth_service_with_token, + std::string* auth_token, + std::string* auth_service); + +} // namespace remoting + +#endif // REMOTING_BASE_AUTH_TOKEN_UTIL_H_ diff --git a/remoting/base/auth_token_util_unittest.cc b/remoting/base/auth_token_util_unittest.cc new file mode 100644 index 0000000..2732b44 --- /dev/null +++ b/remoting/base/auth_token_util_unittest.cc @@ -0,0 +1,36 @@ +// 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 "remoting/base/auth_token_util.h" +#include "remoting/base/constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace remoting { +namespace { + +TEST(AuthTokenUtilTest, ParseAuthTokenWithService) { + std::string auth_token; + std::string auth_service; + + ParseAuthTokenWithService("service:token", &auth_token, &auth_service); + EXPECT_EQ("token", auth_token); + EXPECT_EQ("service", auth_service); + + // Check for legacy support. + ParseAuthTokenWithService("token2", &auth_token, &auth_service); + EXPECT_EQ("token2", auth_token); + EXPECT_EQ(std::string(kChromotingTokenDefaultServiceName), auth_service); + + ParseAuthTokenWithService("just_service:", &auth_token, &auth_service); + EXPECT_EQ("", auth_token); + EXPECT_EQ("just_service", auth_service); + + ParseAuthTokenWithService("yay:token:has:colons", &auth_token, &auth_service); + EXPECT_EQ("token:has:colons", auth_token); + EXPECT_EQ("yay", auth_service); +} + +} // namespace + +} // namespace remoting diff --git a/remoting/base/constants.cc b/remoting/base/constants.cc index 2a9c0a4..219fe14 100644 --- a/remoting/base/constants.cc +++ b/remoting/base/constants.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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. @@ -8,8 +8,7 @@ namespace remoting { const char kChromotingBotJid[] = "remoting@bot.talk.google.com"; -// TODO(sergeyu): Use chromoting's own service name here instead of sync. -const char kChromotingTokenServiceName[] = "chromiumsync"; +const char kChromotingTokenDefaultServiceName[] = "chromiumsync"; const char kChromotingXmlNamespace[] = "google:remoting"; diff --git a/remoting/base/constants.h b/remoting/base/constants.h index c992f11..d464fa4 100644 --- a/remoting/base/constants.h +++ b/remoting/base/constants.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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. @@ -10,7 +10,9 @@ namespace remoting { extern const char kChromotingBotJid[]; // Service name used for authentication. -extern const char kChromotingTokenServiceName[]; +// TODO(ajwong): Remove this once we've killed off XmppToken usage. +// BUG:83897 +extern const char kChromotingTokenDefaultServiceName[]; // Namespace used for chromoting XMPP stanzas. extern const char kChromotingXmlNamespace[]; diff --git a/remoting/client/chromoting_client.cc b/remoting/client/chromoting_client.cc index a46409b..0faafd9 100644 --- a/remoting/client/chromoting_client.cc +++ b/remoting/client/chromoting_client.cc @@ -48,7 +48,8 @@ void ChromotingClient::Start() { return; } - connection_->Connect(config_.username, config_.auth_token, config_.host_jid, + connection_->Connect(config_.username, config_.auth_token, + config_.auth_service, config_.host_jid, config_.nonce, this, this, this); if (!view_->Initialize()) { diff --git a/remoting/client/client_config.h b/remoting/client/client_config.h index d438667..8b6d165 100644 --- a/remoting/client/client_config.h +++ b/remoting/client/client_config.h @@ -18,6 +18,7 @@ struct ClientConfig { std::string host_jid; std::string username; std::string auth_token; + std::string auth_service; std::string nonce; }; diff --git a/remoting/client/client_util.cc b/remoting/client/client_util.cc index 1f1d16a..4ccdd3d 100644 --- a/remoting/client/client_util.cc +++ b/remoting/client/client_util.cc @@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/string_util.h" +#include "remoting/base/constants.h" #include "remoting/client/client_config.h" using std::string; @@ -24,6 +25,7 @@ bool GetLoginInfoFromArgs(int argc, char** argv, ClientConfig* config) { string host_jid; string username; string auth_token; + string auth_service(kChromotingTokenDefaultServiceName); for (int i = 1; i < argc; i++) { std::string arg = argv[i]; @@ -48,6 +50,12 @@ bool GetLoginInfoFromArgs(int argc, char** argv, ClientConfig* config) { found_auth_token = true; auth_token = argv[i]; } + } else if (arg == "--service") { + if (++i >= argc) { + LOG(WARNING) << "Expected service name to follow --service option"; + } else { + auth_service = argv[i]; + } } else { LOG(WARNING) << "Unrecognized option: " << arg; } @@ -66,6 +74,7 @@ bool GetLoginInfoFromArgs(int argc, char** argv, ClientConfig* config) { config->host_jid = host_jid; config->username = username; config->auth_token = auth_token; + config->auth_service = auth_service; return true; } diff --git a/remoting/client/plugin/chromoting_scriptable_object.cc b/remoting/client/plugin/chromoting_scriptable_object.cc index b9b8073..a2b85b8 100644 --- a/remoting/client/plugin/chromoting_scriptable_object.cc +++ b/remoting/client/plugin/chromoting_scriptable_object.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/stringprintf.h" #include "ppapi/cpp/var.h" +#include "remoting/base/auth_token_util.h" #include "remoting/client/client_config.h" #include "remoting/client/chromoting_stats.h" #include "remoting/client/plugin/chromoting_instance.h" @@ -387,7 +388,7 @@ Var ChromotingScriptableObject::DoConnectUnsandboxed( // Parameter order is: // host_jid // username - // xmpp_token + // auth_token // access_code (optional) unsigned int arg = 0; if (!args[arg].is_string()) { @@ -403,10 +404,15 @@ Var ChromotingScriptableObject::DoConnectUnsandboxed( std::string username = args[arg++].AsString(); if (!args[arg].is_string()) { - *exception = Var("The auth_token must be a string."); + *exception = Var("The auth_token_with_service must be a string."); return Var(); } - std::string auth_token = args[arg++].AsString(); + std::string auth_token_with_service = args[arg++].AsString(); + + std::string auth_service; + std::string auth_token; + ParseAuthTokenWithService(auth_token_with_service, &auth_token, + &auth_service); std::string access_code; if (args.size() > arg) { @@ -427,8 +433,10 @@ Var ChromotingScriptableObject::DoConnectUnsandboxed( config.host_jid = host_jid; config.username = username; config.auth_token = auth_token; + config.auth_service = auth_service; config.nonce = access_code; VLOG(1) << "host_jid: " << host_jid << ", username: " << username + << ", auth_service: " << auth_service << ", access_code: " << access_code; instance_->Connect(config); diff --git a/remoting/client/plugin/chromoting_scriptable_object.h b/remoting/client/plugin/chromoting_scriptable_object.h index 44a3b65..5b9c397 100644 --- a/remoting/client/plugin/chromoting_scriptable_object.h +++ b/remoting/client/plugin/chromoting_scriptable_object.h @@ -85,7 +85,10 @@ // // // // When using the sandboxed versions, sendIq must be set and responses to // // calls on sendIq must be piped back into onIq(). -// void connect(string host_jid, string client_jid, +// // +// // Note that auth_token_with_service should be specified as +// // "auth_service:auth_token". For example, "oauth2:5/aBd123". +// void connect(string host_jid, string auth_token_with_service, // optional string access_code); // // Non-sandboxed version used for debugging/testing. // // TODO(garykac): Remove this version once we no longer need it. diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index fe9c5a4..7aff37b 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc @@ -95,8 +95,10 @@ void ChromotingHost::Start(Task* shutdown_task) { std::string xmpp_login; std::string xmpp_auth_token; + std::string xmpp_auth_service; if (!config_->GetString(kXmppLoginConfigPath, &xmpp_login) || - !config_->GetString(kXmppAuthTokenConfigPath, &xmpp_auth_token)) { + !config_->GetString(kXmppAuthTokenConfigPath, &xmpp_auth_token) || + !config_->GetString(kXmppAuthServiceConfigPath, &xmpp_auth_service)) { LOG(ERROR) << "XMPP credentials are not defined in the config."; return; } @@ -105,7 +107,7 @@ void ChromotingHost::Start(Task* shutdown_task) { signal_strategy_.reset( new XmppSignalStrategy(context_->jingle_thread(), xmpp_login, xmpp_auth_token, - kChromotingTokenServiceName)); + xmpp_auth_service)); jingle_client_ = new JingleClient(context_->jingle_thread(), signal_strategy_.get(), NULL, NULL, NULL, this); diff --git a/remoting/host/host_config.cc b/remoting/host/host_config.cc index cc02b15..09ba8e3 100644 --- a/remoting/host/host_config.cc +++ b/remoting/host/host_config.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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. @@ -9,6 +9,7 @@ namespace remoting { const char kHostEnabledConfigPath[] = "enabled"; const char kXmppLoginConfigPath[] = "xmpp_login"; const char kXmppAuthTokenConfigPath[] = "xmpp_auth_token"; +const char kXmppAuthServiceConfigPath[] = "xmpp_auth_service"; const char kHostIdConfigPath[] = "host_id"; const char kHostNameConfigPath[] = "host_name"; const char kPrivateKeyConfigPath[] = "private_key"; diff --git a/remoting/host/host_config.h b/remoting/host/host_config.h index d9c1cd4..00490b0 100644 --- a/remoting/host/host_config.h +++ b/remoting/host/host_config.h @@ -19,8 +19,10 @@ namespace remoting { extern const char kHostEnabledConfigPath[]; // Login used to authenticate in XMPP network. extern const char kXmppLoginConfigPath[]; -// Auth token used to authenticate in XMPP network. +// Auth token used to authenticate to XMPP network. extern const char kXmppAuthTokenConfigPath[]; +// Auth service used to authenticate to XMPP network. +extern const char kXmppAuthServiceConfigPath[]; // Unique identifier of the host used to register the host in directory. // Normally a random UUID. extern const char kHostIdConfigPath[]; diff --git a/remoting/host/host_plugin.cc b/remoting/host/host_plugin.cc index 4713d6b..d152ce2 100644 --- a/remoting/host/host_plugin.cc +++ b/remoting/host/host_plugin.cc @@ -25,6 +25,7 @@ #include "base/mac/foundation_util.h" #endif #include "media/base/media.h" +#include "remoting/base/auth_token_util.h" #include "remoting/host/chromoting_host.h" #include "remoting/host/chromoting_host_context.h" #include "remoting/host/host_config.h" @@ -58,7 +59,9 @@ attribute Function void onStateChanged(); - void connect(string uid, string auth_token); + // The |auth_service_with_token| parametershould be in the format + // "auth_service:auth_token". An example would be "oauth2:1/2a3912vd". + void connect(string uid, string auth_service_with_token); void disconnect(); */ @@ -388,9 +391,13 @@ bool HostNPScriptObject::Connect(const NPVariant* args, return false; } - std::string auth_token = StringFromNPVariant(args[1]); + std::string auth_service_with_token = StringFromNPVariant(args[1]); + std::string auth_token; + std::string auth_service; + remoting::ParseAuthTokenWithService(auth_service_with_token, &auth_token, + &auth_service); if (auth_token.empty()) { - SetException("connect: bad auth_token argument"); + SetException("connect: auth_service_with_token argument has empty token"); return false; } @@ -422,6 +429,7 @@ bool HostNPScriptObject::Connect(const NPVariant* args, new remoting::InMemoryHostConfig; host_config->SetString(remoting::kXmppLoginConfigPath, uid); host_config->SetString(remoting::kXmppAuthTokenConfigPath, auth_token); + host_config->SetString(remoting::kXmppAuthServiceConfigPath, auth_service); // Create an access verifier and fetch the host secret. scoped_ptr access_verifier; diff --git a/remoting/host/simple_host_process.cc b/remoting/host/simple_host_process.cc index bd8385f..7bdb7fb 100644 --- a/remoting/host/simple_host_process.cc +++ b/remoting/host/simple_host_process.cc @@ -32,6 +32,7 @@ #include "base/threading/thread.h" #include "crypto/nss_util.h" #include "media/base/media.h" +#include "remoting/base/constants.h" #include "remoting/base/tracer.h" #include "remoting/host/capturer_fake.h" #include "remoting/host/chromoting_host.h" @@ -52,6 +53,8 @@ using remoting::ChromotingHost; using remoting::DesktopEnvironment; +using remoting::kChromotingTokenDefaultServiceName; +using remoting::kXmppAuthServiceConfigPath; using remoting::protocol::CandidateSessionConfig; using remoting::protocol::ChannelConfig; using std::string; @@ -122,6 +125,13 @@ class SimpleHost { return 1; } + // For the simple host, we assume we always use the ClientLogin token for + // chromiumsync because we do not have an HTTP stack with which we can + // easily request an OAuth2 access token even if we had a RefreshToken for + // the account. + config->SetString(kXmppAuthServiceConfigPath, + kChromotingTokenDefaultServiceName); + // Initialize AccessVerifier. // TODO(jamiewalch): For the Me2Mom case, the access verifier is passed to // RegisterSupportHostRequest::Init, so transferring ownership of it to the diff --git a/remoting/jingle_glue/jingle_client.cc b/remoting/jingle_glue/jingle_client.cc index ce11780..509e6f8 100644 --- a/remoting/jingle_glue/jingle_client.cc +++ b/remoting/jingle_glue/jingle_client.cc @@ -114,11 +114,16 @@ void XmppSignalStrategy::OnConnectionStateChanged( buzz::PreXmppAuth* XmppSignalStrategy::CreatePreXmppAuth( const buzz::XmppClientSettings& settings) { buzz::Jid jid(settings.user(), settings.host(), buzz::STR_EMPTY); + std::string mechanism = notifier::GaiaTokenPreXmppAuth::kDefaultAuthMechanism; + if (settings.token_service() == "oauth2") { + mechanism = "X-OAUTH2"; + } + return new notifier::GaiaTokenPreXmppAuth( jid.Str(), settings.auth_cookie(), settings.token_service(), - notifier::GaiaTokenPreXmppAuth::kDefaultAuthMechanism); + mechanism); } diff --git a/remoting/protocol/connection_to_host.cc b/remoting/protocol/connection_to_host.cc index f4a82f3..c86370e 100644 --- a/remoting/protocol/connection_to_host.cc +++ b/remoting/protocol/connection_to_host.cc @@ -55,6 +55,7 @@ MessageLoop* ConnectionToHost::message_loop() { void ConnectionToHost::Connect(const std::string& username, const std::string& auth_token, + const std::string& auth_service, const std::string& host_jid, const std::string& access_code, HostEventCallback* event_callback, @@ -67,8 +68,7 @@ void ConnectionToHost::Connect(const std::string& username, // Initialize |jingle_client_|. signal_strategy_.reset( - new XmppSignalStrategy(thread_, username, auth_token, - kChromotingTokenServiceName)); + new XmppSignalStrategy(thread_, username, auth_token, auth_service)); jingle_client_ = new JingleClient(thread_, signal_strategy_.get(), network_manager_.release(), socket_factory_.release(), diff --git a/remoting/protocol/connection_to_host.h b/remoting/protocol/connection_to_host.h index ac88645..bf990ac 100644 --- a/remoting/protocol/connection_to_host.h +++ b/remoting/protocol/connection_to_host.h @@ -73,6 +73,7 @@ class ConnectionToHost : public JingleClient::Callback { // TODO(ajwong): We need to generalize this API. virtual void Connect(const std::string& username, const std::string& auth_token, + const std::string& auth_service, const std::string& host_jid, const std::string& access_code, HostEventCallback* event_callback, diff --git a/remoting/protocol/protocol_test_client.cc b/remoting/protocol/protocol_test_client.cc index 9d01c32..2b8aefb 100644 --- a/remoting/protocol/protocol_test_client.cc +++ b/remoting/protocol/protocol_test_client.cc @@ -27,8 +27,6 @@ extern "C" { #include "remoting/jingle_glue/jingle_thread.h" #include "remoting/protocol/jingle_session_manager.h" -using remoting::kChromotingTokenServiceName; - namespace remoting { namespace protocol { @@ -93,7 +91,7 @@ class ProtocolTestClient virtual ~ProtocolTestClient() {} void Run(const std::string& username, const std::string& auth_token, - const std::string& host_jid); + const std::string& auth_service, const std::string& host_jid); void OnConnectionClosed(ProtocolTestConnection* connection); @@ -223,12 +221,13 @@ void ProtocolTestConnection::HandleReadResult(int result) { void ProtocolTestClient::Run(const std::string& username, const std::string& auth_token, + const std::string& auth_service, const std::string& host_jid) { remoting::JingleThread jingle_thread; jingle_thread.Start(); signal_strategy_.reset( new XmppSignalStrategy(&jingle_thread, username, auth_token, - kChromotingTokenServiceName)); + auth_service)); client_ = new JingleClient(&jingle_thread, signal_strategy_.get(), NULL, NULL, NULL, this); client_->Init(); @@ -374,9 +373,14 @@ int main(int argc, char** argv) { usage(argv[0]); std::string auth_token(cmd_line->GetSwitchValueASCII("auth_token")); + // Default to OAuth2 for the auth token. + std::string auth_service("oauth2"); + if (cmd_line->HasSwitch("auth_service")) + auth_service = cmd_line->GetSwitchValueASCII("auth_service"); + scoped_refptr client(new ProtocolTestClient()); - client->Run(username, auth_token, host_jid); + client->Run(username, auth_token, host_jid, auth_service); return 0; } diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 3e5d239..78b967d 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -234,6 +234,8 @@ # depend on chromotocol_proto_lib for headers. 'hard_dependency': 1, 'sources': [ + 'base/auth_token_util.cc', + 'base/auth_token_util.h', 'base/capture_data.cc', 'base/capture_data.h', 'base/compound_buffer.cc', @@ -621,6 +623,7 @@ '../testing/gmock/include', ], 'sources': [ + 'base/auth_token_util_unittest.cc', 'base/codec_test.cc', 'base/codec_test.h', 'base/compound_buffer_unittest.cc', diff --git a/remoting/webapp/me2mom/choice.html b/remoting/webapp/me2mom/choice.html index 3c44172..768e314 100644 --- a/remoting/webapp/me2mom/choice.html +++ b/remoting/webapp/me2mom/choice.html @@ -33,7 +33,16 @@ found in the LICENSE file. -
+
+ Current Email: +
+ + + +
+
+