Commit a5176675 authored by Alex Ilin's avatar Alex Ilin Committed by Commit Bot

[identity] Add gaia id field to OAuth2MintTokenConsentResult

This CL adds a new field to OAuth2MintTokenConsentResult proto, modifies
the parsing function and plumbs this new field to
GaiaRemoteConsentFlow::Delegate::OnGaiaRemoteConsentFlowApproved().

IdentityGetAuthTokenFunction is going to remember this gaia id and reuse
the same account for the next calls.

The usage of the gaia id will be added in future CLs.

Bug: 1026237
Change-Id: Ieb407ee26d8b2ab9e4a4f4bb3c164f5c88c37440
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2042097Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Commit-Queue: Alex Ilin <alexilin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#739039}
parent ca60da81
...@@ -108,8 +108,9 @@ void GaiaRemoteConsentFlow::OnConsentResultSet( ...@@ -108,8 +108,9 @@ void GaiaRemoteConsentFlow::OnConsentResultSet(
identity_api_set_consent_result_subscription_.reset(); identity_api_set_consent_result_subscription_.reset();
bool consent_approved = false; bool consent_approved = false;
std::string gaia_id;
if (!gaia::ParseOAuth2MintTokenConsentResult(consent_result, if (!gaia::ParseOAuth2MintTokenConsentResult(consent_result,
&consent_approved)) { &consent_approved, &gaia_id)) {
delegate_->OnGaiaRemoteConsentFlowFailed( delegate_->OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT); GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT);
return; return;
...@@ -120,7 +121,7 @@ void GaiaRemoteConsentFlow::OnConsentResultSet( ...@@ -120,7 +121,7 @@ void GaiaRemoteConsentFlow::OnConsentResultSet(
return; return;
} }
delegate_->OnGaiaRemoteConsentFlowApproved(consent_result); delegate_->OnGaiaRemoteConsentFlowApproved(consent_result, gaia_id);
} }
void GaiaRemoteConsentFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) { void GaiaRemoteConsentFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) {
......
...@@ -37,7 +37,8 @@ class GaiaRemoteConsentFlow ...@@ -37,7 +37,8 @@ class GaiaRemoteConsentFlow
// Called when the user gives the approval via the OAuth2 remote consent // Called when the user gives the approval via the OAuth2 remote consent
// screen. // screen.
virtual void OnGaiaRemoteConsentFlowApproved( virtual void OnGaiaRemoteConsentFlowApproved(
const std::string& consent_result) = 0; const std::string& consent_result,
const std::string& gaia_id) = 0;
}; };
GaiaRemoteConsentFlow(Delegate* delegate, GaiaRemoteConsentFlow(Delegate* delegate,
......
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
namespace extensions { namespace extensions {
const char kWindowKey[] = "window_key"; const char kWindowKey[] = "window_key";
const char kConsentResult[] = "CAESCUVOQ1JZUFRFRA"; const char kGaiaId[] = "fake_gaia_id";
const char kConsentResult[] = "CAESCUVOQ1JZUFRFRBoMZmFrZV9nYWlhX2lk";
class FakeWebAuthFlowWithWindowKey : public WebAuthFlow { class FakeWebAuthFlowWithWindowKey : public WebAuthFlow {
public: public:
...@@ -60,8 +61,9 @@ class MockGaiaRemoteConsentFlowDelegate ...@@ -60,8 +61,9 @@ class MockGaiaRemoteConsentFlowDelegate
public: public:
MOCK_METHOD1(OnGaiaRemoteConsentFlowFailed, MOCK_METHOD1(OnGaiaRemoteConsentFlowFailed,
void(GaiaRemoteConsentFlow::Failure failure)); void(GaiaRemoteConsentFlow::Failure failure));
MOCK_METHOD1(OnGaiaRemoteConsentFlowApproved, MOCK_METHOD2(OnGaiaRemoteConsentFlowApproved,
void(const std::string& consent_result)); void(const std::string& consent_result,
const std::string& gaia_id));
}; };
class IdentityGaiaRemoteConsentFlowTest : public testing::Test { class IdentityGaiaRemoteConsentFlowTest : public testing::Test {
...@@ -99,7 +101,8 @@ class IdentityGaiaRemoteConsentFlowTest : public testing::Test { ...@@ -99,7 +101,8 @@ class IdentityGaiaRemoteConsentFlowTest : public testing::Test {
TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult) { TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult) {
std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey); std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowApproved(kConsentResult)); EXPECT_CALL(delegate_,
OnGaiaRemoteConsentFlowApproved(kConsentResult, kGaiaId));
flow->OnConsentResultSet(kConsentResult, kWindowKey); flow->OnConsentResultSet(kConsentResult, kWindowKey);
} }
...@@ -117,10 +120,11 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult_TwoWindows) { ...@@ -117,10 +120,11 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult_TwoWindows) {
CreateTestFlow(kWindowKey2, &delegate2); CreateTestFlow(kWindowKey2, &delegate2);
const char kConsentResult2[] = "CAESCkVOQ1JZUFRFRDI"; const char kConsentResult2[] = "CAESCkVOQ1JZUFRFRDI";
EXPECT_CALL(delegate2, OnGaiaRemoteConsentFlowApproved(kConsentResult2)); EXPECT_CALL(delegate2, OnGaiaRemoteConsentFlowApproved(kConsentResult2, ""));
flow2->OnConsentResultSet(kConsentResult2, kWindowKey2); flow2->OnConsentResultSet(kConsentResult2, kWindowKey2);
EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowApproved(kConsentResult)); EXPECT_CALL(delegate_,
OnGaiaRemoteConsentFlowApproved(kConsentResult, kGaiaId));
flow->OnConsentResultSet(kConsentResult, kWindowKey); flow->OnConsentResultSet(kConsentResult, kWindowKey);
} }
......
...@@ -735,7 +735,10 @@ void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowFailed( ...@@ -735,7 +735,10 @@ void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowFailed(
} }
void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowApproved( void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowApproved(
const std::string& consent_result) { const std::string& consent_result,
const std::string& gaia_id) {
// TODO(crbug.com/1026237): Reuse the same gaia id for this extension the next
// time.
DCHECK(!consent_result.empty()); DCHECK(!consent_result.empty());
consent_result_ = consent_result; consent_result_ = consent_result;
should_prompt_for_scopes_ = false; should_prompt_for_scopes_ = false;
......
...@@ -80,8 +80,8 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction, ...@@ -80,8 +80,8 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
// GaiaRemoteConsentFlow::Delegate implementation: // GaiaRemoteConsentFlow::Delegate implementation:
void OnGaiaRemoteConsentFlowFailed( void OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure failure) override; GaiaRemoteConsentFlow::Failure failure) override;
void OnGaiaRemoteConsentFlowApproved( void OnGaiaRemoteConsentFlowApproved(const std::string& consent_result,
const std::string& consent_result) override; const std::string& gaia_id) override;
// Starts a login access token request. // Starts a login access token request.
virtual void StartTokenKeyAccountAccessTokenRequest(); virtual void StartTokenKeyAccountAccessTokenRequest();
......
...@@ -180,8 +180,10 @@ bool ParseListAccountsData(const std::string& data, ...@@ -180,8 +180,10 @@ bool ParseListAccountsData(const std::string& data,
} }
bool ParseOAuth2MintTokenConsentResult(const std::string& consent_result, bool ParseOAuth2MintTokenConsentResult(const std::string& consent_result,
bool* approved) { bool* approved,
std::string* gaia_id) {
DCHECK(approved); DCHECK(approved);
DCHECK(gaia_id);
std::string decoded_result; std::string decoded_result;
if (!base::Base64UrlDecode(consent_result, if (!base::Base64UrlDecode(consent_result,
...@@ -198,6 +200,7 @@ bool ParseOAuth2MintTokenConsentResult(const std::string& consent_result, ...@@ -198,6 +200,7 @@ bool ParseOAuth2MintTokenConsentResult(const std::string& consent_result,
} }
*approved = parsed_result.approved(); *approved = parsed_result.approved();
*gaia_id = parsed_result.obfuscated_id();
return true; return true;
} }
......
...@@ -68,11 +68,13 @@ bool ParseListAccountsData(const std::string& data, ...@@ -68,11 +68,13 @@ bool ParseListAccountsData(const std::string& data,
std::vector<ListedAccount>* signed_out_accounts); std::vector<ListedAccount>* signed_out_accounts);
// Parses base64url encoded protobuf message returned by the remote consent // Parses base64url encoded protobuf message returned by the remote consent
// flow, returning whether the consent was approved. // flow, returning whether the consent was approved and the gaia id of the user
// that was shown the consent page.
// Returns false if the method failed to decode the protobuf. // Returns false if the method failed to decode the protobuf.
// |approved| must not be null. // |approved| and |gaia_id| must not be null.
bool ParseOAuth2MintTokenConsentResult(const std::string& consent_result, bool ParseOAuth2MintTokenConsentResult(const std::string& consent_result,
bool* approved); bool* approved,
std::string* gaia_id);
} // namespace gaia } // namespace gaia
......
...@@ -14,9 +14,12 @@ namespace gaia { ...@@ -14,9 +14,12 @@ namespace gaia {
namespace { namespace {
const char kGaiaId[] = "fake_gaia_id";
std::string GenerateOAuth2MintTokenConsentResult( std::string GenerateOAuth2MintTokenConsentResult(
base::Optional<bool> approved, base::Optional<bool> approved,
const base::Optional<std::string>& encrypted_approval_data, const base::Optional<std::string>& encrypted_approval_data,
const base::Optional<std::string>& obfuscated_id,
base::Base64UrlEncodePolicy encode_policy = base::Base64UrlEncodePolicy encode_policy =
base::Base64UrlEncodePolicy::OMIT_PADDING) { base::Base64UrlEncodePolicy::OMIT_PADDING) {
OAuth2MintTokenConsentResult consent_result; OAuth2MintTokenConsentResult consent_result;
...@@ -24,6 +27,8 @@ std::string GenerateOAuth2MintTokenConsentResult( ...@@ -24,6 +27,8 @@ std::string GenerateOAuth2MintTokenConsentResult(
consent_result.set_approved(approved.value()); consent_result.set_approved(approved.value());
if (encrypted_approval_data.has_value()) if (encrypted_approval_data.has_value())
consent_result.set_encrypted_approval_data(encrypted_approval_data.value()); consent_result.set_encrypted_approval_data(encrypted_approval_data.value());
if (obfuscated_id.has_value())
consent_result.set_obfuscated_id(obfuscated_id.value());
std::string serialized_consent = consent_result.SerializeAsString(); std::string serialized_consent = consent_result.SerializeAsString();
std::string encoded_consent; std::string encoded_consent;
base::Base64UrlEncode(serialized_consent, encode_policy, &encoded_consent); base::Base64UrlEncode(serialized_consent, encode_policy, &encoded_consent);
...@@ -345,64 +350,93 @@ TEST(GaiaAuthUtilTest, ParseListAccountsAcceptsNull) { ...@@ -345,64 +350,93 @@ TEST(GaiaAuthUtilTest, ParseListAccountsAcceptsNull) {
} }
TEST(GaiaAuthUtilTest, ParseConsentResultApproved) { TEST(GaiaAuthUtilTest, ParseConsentResultApproved) {
const char kApprovedConsent[] = "CAESCUVOQ1JZUFRFRA"; const char kApprovedConsent[] = "CAESCUVOQ1JZUFRFRBoMZmFrZV9nYWlhX2lk";
EXPECT_EQ(kApprovedConsent, EXPECT_EQ(kApprovedConsent,
GenerateOAuth2MintTokenConsentResult(true, "ENCRYPTED")); GenerateOAuth2MintTokenConsentResult(true, "ENCRYPTED", kGaiaId));
bool approved = false; bool approved = false;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult(kApprovedConsent, &approved)); std::string gaia_id;
ASSERT_TRUE(
ParseOAuth2MintTokenConsentResult(kApprovedConsent, &approved, &gaia_id));
EXPECT_TRUE(approved); EXPECT_TRUE(approved);
EXPECT_EQ(gaia_id, kGaiaId);
} }
TEST(GaiaAuthUtilTest, ParseConsentResultApprovedEmptyData) { TEST(GaiaAuthUtilTest, ParseConsentResultApprovedEmptyData) {
const char kApprovedConsent[] = "CAE"; const char kApprovedConsent[] = "CAEaDGZha2VfZ2FpYV9pZA";
EXPECT_EQ(kApprovedConsent, EXPECT_EQ(kApprovedConsent,
GenerateOAuth2MintTokenConsentResult(true, base::nullopt)); GenerateOAuth2MintTokenConsentResult(true, base::nullopt, kGaiaId));
bool approved = false;
std::string gaia_id;
ASSERT_TRUE(
ParseOAuth2MintTokenConsentResult(kApprovedConsent, &approved, &gaia_id));
EXPECT_TRUE(approved);
EXPECT_EQ(gaia_id, kGaiaId);
}
TEST(GaiaAuthUtilTest, ParseConsentResultApprovedEmptyGaiaId) {
const char kApprovedConsent[] = "CAESCUVOQ1JZUFRFRA";
EXPECT_EQ(kApprovedConsent, GenerateOAuth2MintTokenConsentResult(
true, "ENCRYPTED", base::nullopt));
bool approved = false; bool approved = false;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult(kApprovedConsent, &approved)); std::string gaia_id;
ASSERT_TRUE(
ParseOAuth2MintTokenConsentResult(kApprovedConsent, &approved, &gaia_id));
EXPECT_TRUE(approved); EXPECT_TRUE(approved);
EXPECT_TRUE(gaia_id.empty());
} }
TEST(GaiaAuthUtilTest, ParseConsentResultNotApproved) { TEST(GaiaAuthUtilTest, ParseConsentResultNotApproved) {
const char kNoGrantConsent[] = "CAA"; const char kNoGrantConsent[] = "CAAaDGZha2VfZ2FpYV9pZA";
EXPECT_EQ(kNoGrantConsent, EXPECT_EQ(kNoGrantConsent, GenerateOAuth2MintTokenConsentResult(
GenerateOAuth2MintTokenConsentResult(false, base::nullopt)); false, base::nullopt, kGaiaId));
bool approved = false; bool approved = false;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult(kNoGrantConsent, &approved)); std::string gaia_id;
ASSERT_TRUE(
ParseOAuth2MintTokenConsentResult(kNoGrantConsent, &approved, &gaia_id));
EXPECT_FALSE(approved); EXPECT_FALSE(approved);
EXPECT_EQ(gaia_id, kGaiaId);
} }
TEST(GaiaAuthUtilTest, ParseConsentResultEmpty) { TEST(GaiaAuthUtilTest, ParseConsentResultEmpty) {
EXPECT_EQ("", EXPECT_EQ("", GenerateOAuth2MintTokenConsentResult(
GenerateOAuth2MintTokenConsentResult(base::nullopt, base::nullopt)); base::nullopt, base::nullopt, base::nullopt));
bool approved = false; bool approved = false;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult("", &approved)); std::string gaia_id;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult("", &approved, &gaia_id));
// false is the default value for a bool in proto. // false is the default value for a bool in proto.
EXPECT_FALSE(approved); EXPECT_FALSE(approved);
// String is empty in proto by default.
EXPECT_TRUE(gaia_id.empty());
} }
TEST(GaiaAuthUtilTest, ParseConsentResultBase64UrlDisallowedPadding) { TEST(GaiaAuthUtilTest, ParseConsentResultBase64UrlDisallowedPadding) {
const char kApprovedConsentWithPadding[] = "CAE="; const char kApprovedConsentWithPadding[] = "CAE=";
EXPECT_EQ( EXPECT_EQ(kApprovedConsentWithPadding,
kApprovedConsentWithPadding, GenerateOAuth2MintTokenConsentResult(
GenerateOAuth2MintTokenConsentResult( true, base::nullopt, base::nullopt,
true, base::nullopt, base::Base64UrlEncodePolicy::INCLUDE_PADDING)); base::Base64UrlEncodePolicy::INCLUDE_PADDING));
bool approved = false; bool approved = false;
std::string gaia_id;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kApprovedConsentWithPadding, EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kApprovedConsentWithPadding,
&approved)); &approved, &gaia_id));
} }
TEST(GaiaAuthUtilTest, ParseConsentResultInvalidBase64Url) { TEST(GaiaAuthUtilTest, ParseConsentResultInvalidBase64Url) {
const char kMalformedConsent[] = const char kMalformedConsent[] =
"+/"; // '+' and '/' are disallowed in base64url alphabet. "+/"; // '+' and '/' are disallowed in base64url alphabet.
bool approved = false; bool approved = false;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kMalformedConsent, &approved)); std::string gaia_id;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kMalformedConsent, &approved,
&gaia_id));
} }
TEST(GaiaAuthUtilTest, ParseConsentResultInvalidProto) { TEST(GaiaAuthUtilTest, ParseConsentResultInvalidProto) {
const char kMalformedConsent[] = const char kMalformedConsent[] =
"ab"; // Valid base64url string but invalid proto. "ab"; // Valid base64url string but invalid proto.
bool approved = false; bool approved = false;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kMalformedConsent, &approved)); std::string gaia_id;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kMalformedConsent, &approved,
&gaia_id));
} }
} // namespace gaia } // namespace gaia
...@@ -19,4 +19,7 @@ message OAuth2MintTokenConsentResult { ...@@ -19,4 +19,7 @@ message OAuth2MintTokenConsentResult {
// Opaque data to be passed to the IssueToken. // Opaque data to be passed to the IssueToken.
// Absent if `approved` is false. // Absent if `approved` is false.
optional bytes encrypted_approval_data = 2; optional bytes encrypted_approval_data = 2;
// The obfuscated gaia ID of the user that was shown the consent page.
optional string obfuscated_id = 3;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment