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(
identity_api_set_consent_result_subscription_.reset();
bool consent_approved = false;
std::string gaia_id;
if (!gaia::ParseOAuth2MintTokenConsentResult(consent_result,
&consent_approved)) {
&consent_approved, &gaia_id)) {
delegate_->OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT);
return;
......@@ -120,7 +121,7 @@ void GaiaRemoteConsentFlow::OnConsentResultSet(
return;
}
delegate_->OnGaiaRemoteConsentFlowApproved(consent_result);
delegate_->OnGaiaRemoteConsentFlowApproved(consent_result, gaia_id);
}
void GaiaRemoteConsentFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) {
......
......@@ -37,7 +37,8 @@ class GaiaRemoteConsentFlow
// Called when the user gives the approval via the OAuth2 remote consent
// screen.
virtual void OnGaiaRemoteConsentFlowApproved(
const std::string& consent_result) = 0;
const std::string& consent_result,
const std::string& gaia_id) = 0;
};
GaiaRemoteConsentFlow(Delegate* delegate,
......
......@@ -18,7 +18,8 @@
namespace extensions {
const char kWindowKey[] = "window_key";
const char kConsentResult[] = "CAESCUVOQ1JZUFRFRA";
const char kGaiaId[] = "fake_gaia_id";
const char kConsentResult[] = "CAESCUVOQ1JZUFRFRBoMZmFrZV9nYWlhX2lk";
class FakeWebAuthFlowWithWindowKey : public WebAuthFlow {
public:
......@@ -60,8 +61,9 @@ class MockGaiaRemoteConsentFlowDelegate
public:
MOCK_METHOD1(OnGaiaRemoteConsentFlowFailed,
void(GaiaRemoteConsentFlow::Failure failure));
MOCK_METHOD1(OnGaiaRemoteConsentFlowApproved,
void(const std::string& consent_result));
MOCK_METHOD2(OnGaiaRemoteConsentFlowApproved,
void(const std::string& consent_result,
const std::string& gaia_id));
};
class IdentityGaiaRemoteConsentFlowTest : public testing::Test {
......@@ -99,7 +101,8 @@ class IdentityGaiaRemoteConsentFlowTest : public testing::Test {
TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult) {
std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowApproved(kConsentResult));
EXPECT_CALL(delegate_,
OnGaiaRemoteConsentFlowApproved(kConsentResult, kGaiaId));
flow->OnConsentResultSet(kConsentResult, kWindowKey);
}
......@@ -117,10 +120,11 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult_TwoWindows) {
CreateTestFlow(kWindowKey2, &delegate2);
const char kConsentResult2[] = "CAESCkVOQ1JZUFRFRDI";
EXPECT_CALL(delegate2, OnGaiaRemoteConsentFlowApproved(kConsentResult2));
EXPECT_CALL(delegate2, OnGaiaRemoteConsentFlowApproved(kConsentResult2, ""));
flow2->OnConsentResultSet(kConsentResult2, kWindowKey2);
EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowApproved(kConsentResult));
EXPECT_CALL(delegate_,
OnGaiaRemoteConsentFlowApproved(kConsentResult, kGaiaId));
flow->OnConsentResultSet(kConsentResult, kWindowKey);
}
......
......@@ -735,7 +735,10 @@ void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowFailed(
}
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());
consent_result_ = consent_result;
should_prompt_for_scopes_ = false;
......
......@@ -80,8 +80,8 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
// GaiaRemoteConsentFlow::Delegate implementation:
void OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure failure) override;
void OnGaiaRemoteConsentFlowApproved(
const std::string& consent_result) override;
void OnGaiaRemoteConsentFlowApproved(const std::string& consent_result,
const std::string& gaia_id) override;
// Starts a login access token request.
virtual void StartTokenKeyAccountAccessTokenRequest();
......
......@@ -180,8 +180,10 @@ bool ParseListAccountsData(const std::string& data,
}
bool ParseOAuth2MintTokenConsentResult(const std::string& consent_result,
bool* approved) {
bool* approved,
std::string* gaia_id) {
DCHECK(approved);
DCHECK(gaia_id);
std::string decoded_result;
if (!base::Base64UrlDecode(consent_result,
......@@ -198,6 +200,7 @@ bool ParseOAuth2MintTokenConsentResult(const std::string& consent_result,
}
*approved = parsed_result.approved();
*gaia_id = parsed_result.obfuscated_id();
return true;
}
......
......@@ -68,11 +68,13 @@ bool ParseListAccountsData(const std::string& data,
std::vector<ListedAccount>* signed_out_accounts);
// 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.
// |approved| must not be null.
// |approved| and |gaia_id| must not be null.
bool ParseOAuth2MintTokenConsentResult(const std::string& consent_result,
bool* approved);
bool* approved,
std::string* gaia_id);
} // namespace gaia
......
......@@ -14,9 +14,12 @@ namespace gaia {
namespace {
const char kGaiaId[] = "fake_gaia_id";
std::string GenerateOAuth2MintTokenConsentResult(
base::Optional<bool> approved,
const base::Optional<std::string>& encrypted_approval_data,
const base::Optional<std::string>& obfuscated_id,
base::Base64UrlEncodePolicy encode_policy =
base::Base64UrlEncodePolicy::OMIT_PADDING) {
OAuth2MintTokenConsentResult consent_result;
......@@ -24,6 +27,8 @@ std::string GenerateOAuth2MintTokenConsentResult(
consent_result.set_approved(approved.value());
if (encrypted_approval_data.has_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 encoded_consent;
base::Base64UrlEncode(serialized_consent, encode_policy, &encoded_consent);
......@@ -345,64 +350,93 @@ TEST(GaiaAuthUtilTest, ParseListAccountsAcceptsNull) {
}
TEST(GaiaAuthUtilTest, ParseConsentResultApproved) {
const char kApprovedConsent[] = "CAESCUVOQ1JZUFRFRA";
const char kApprovedConsent[] = "CAESCUVOQ1JZUFRFRBoMZmFrZV9nYWlhX2lk";
EXPECT_EQ(kApprovedConsent,
GenerateOAuth2MintTokenConsentResult(true, "ENCRYPTED"));
GenerateOAuth2MintTokenConsentResult(true, "ENCRYPTED", kGaiaId));
bool approved = false;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult(kApprovedConsent, &approved));
std::string gaia_id;
ASSERT_TRUE(
ParseOAuth2MintTokenConsentResult(kApprovedConsent, &approved, &gaia_id));
EXPECT_TRUE(approved);
EXPECT_EQ(gaia_id, kGaiaId);
}
TEST(GaiaAuthUtilTest, ParseConsentResultApprovedEmptyData) {
const char kApprovedConsent[] = "CAE";
const char kApprovedConsent[] = "CAEaDGZha2VfZ2FpYV9pZA";
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;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult(kApprovedConsent, &approved));
std::string gaia_id;
ASSERT_TRUE(
ParseOAuth2MintTokenConsentResult(kApprovedConsent, &approved, &gaia_id));
EXPECT_TRUE(approved);
EXPECT_TRUE(gaia_id.empty());
}
TEST(GaiaAuthUtilTest, ParseConsentResultNotApproved) {
const char kNoGrantConsent[] = "CAA";
EXPECT_EQ(kNoGrantConsent,
GenerateOAuth2MintTokenConsentResult(false, base::nullopt));
const char kNoGrantConsent[] = "CAAaDGZha2VfZ2FpYV9pZA";
EXPECT_EQ(kNoGrantConsent, GenerateOAuth2MintTokenConsentResult(
false, base::nullopt, kGaiaId));
bool approved = false;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult(kNoGrantConsent, &approved));
std::string gaia_id;
ASSERT_TRUE(
ParseOAuth2MintTokenConsentResult(kNoGrantConsent, &approved, &gaia_id));
EXPECT_FALSE(approved);
EXPECT_EQ(gaia_id, kGaiaId);
}
TEST(GaiaAuthUtilTest, ParseConsentResultEmpty) {
EXPECT_EQ("",
GenerateOAuth2MintTokenConsentResult(base::nullopt, base::nullopt));
EXPECT_EQ("", GenerateOAuth2MintTokenConsentResult(
base::nullopt, base::nullopt, base::nullopt));
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.
EXPECT_FALSE(approved);
// String is empty in proto by default.
EXPECT_TRUE(gaia_id.empty());
}
TEST(GaiaAuthUtilTest, ParseConsentResultBase64UrlDisallowedPadding) {
const char kApprovedConsentWithPadding[] = "CAE=";
EXPECT_EQ(
kApprovedConsentWithPadding,
GenerateOAuth2MintTokenConsentResult(
true, base::nullopt, base::Base64UrlEncodePolicy::INCLUDE_PADDING));
EXPECT_EQ(kApprovedConsentWithPadding,
GenerateOAuth2MintTokenConsentResult(
true, base::nullopt, base::nullopt,
base::Base64UrlEncodePolicy::INCLUDE_PADDING));
bool approved = false;
std::string gaia_id;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kApprovedConsentWithPadding,
&approved));
&approved, &gaia_id));
}
TEST(GaiaAuthUtilTest, ParseConsentResultInvalidBase64Url) {
const char kMalformedConsent[] =
"+/"; // '+' and '/' are disallowed in base64url alphabet.
bool approved = false;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kMalformedConsent, &approved));
std::string gaia_id;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kMalformedConsent, &approved,
&gaia_id));
}
TEST(GaiaAuthUtilTest, ParseConsentResultInvalidProto) {
const char kMalformedConsent[] =
"ab"; // Valid base64url string but invalid proto.
bool approved = false;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kMalformedConsent, &approved));
std::string gaia_id;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kMalformedConsent, &approved,
&gaia_id));
}
} // namespace gaia
......@@ -19,4 +19,7 @@ message OAuth2MintTokenConsentResult {
// Opaque data to be passed to the IssueToken.
// Absent if `approved` is false.
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