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

[identity] Parse the consent result in GaiaRemoteConsentFlow

This CL adds a helper method for parsing the consent result returned
from Gaia via JavaScript. This method is used in GaiaRemoteConsentFlow
to check that the consent was actually granted by the user.

Bug: 1026237
Change-Id: I9d5b44f275d227316794dd06be69bf68878e24fa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2030948Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Commit-Queue: Alex Ilin <alexilin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#737301}
parent b02b245a
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h" #include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
#include "google_apis/gaia/gaia_auth_fetcher.h" #include "google_apis/gaia/gaia_auth_fetcher.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/gaia_urls.h" #include "google_apis/gaia/gaia_urls.h"
#include "net/base/escape.h" #include "net/base/escape.h"
#include "services/network/public/mojom/cookie_manager.mojom.h" #include "services/network/public/mojom/cookie_manager.mojom.h"
...@@ -73,7 +74,7 @@ void GaiaRemoteConsentFlow::Start() { ...@@ -73,7 +74,7 @@ void GaiaRemoteConsentFlow::Start() {
void GaiaRemoteConsentFlow::OnSetAccountsComplete( void GaiaRemoteConsentFlow::OnSetAccountsComplete(
signin::SetAccountsInCookieResult result) { signin::SetAccountsInCookieResult result) {
if (result != signin::SetAccountsInCookieResult::kSuccess) { if (result != signin::SetAccountsInCookieResult::kSuccess) {
delegate_->OnGaiaRemoteConsentFlowFailure( delegate_->OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure::SET_ACCOUNTS_IN_COOKIE_FAILED); GaiaRemoteConsentFlow::Failure::SET_ACCOUNTS_IN_COOKIE_FAILED);
return; return;
} }
...@@ -105,9 +106,21 @@ void GaiaRemoteConsentFlow::OnConsentResultSet( ...@@ -105,9 +106,21 @@ void GaiaRemoteConsentFlow::OnConsentResultSet(
return; return;
identity_api_set_consent_result_subscription_.reset(); identity_api_set_consent_result_subscription_.reset();
// TODO(crbug.com/1026237): parse consent result to check whether the consent
// was approved. bool consent_approved = false;
delegate_->OnGaiaRemoteConsentFlowCompleted(consent_result); if (!gaia::ParseOAuth2MintTokenConsentResult(consent_result,
&consent_approved)) {
delegate_->OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT);
return;
}
if (!consent_approved) {
delegate_->OnGaiaRemoteConsentFlowFailed(GaiaRemoteConsentFlow::NO_GRANT);
return;
}
delegate_->OnGaiaRemoteConsentFlowApproved(consent_result);
} }
void GaiaRemoteConsentFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) { void GaiaRemoteConsentFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) {
...@@ -126,7 +139,7 @@ void GaiaRemoteConsentFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) { ...@@ -126,7 +139,7 @@ void GaiaRemoteConsentFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) {
break; break;
} }
delegate_->OnGaiaRemoteConsentFlowFailure(gaia_failure); delegate_->OnGaiaRemoteConsentFlowFailed(gaia_failure);
} }
std::unique_ptr<GaiaAuthFetcher> std::unique_ptr<GaiaAuthFetcher>
......
...@@ -25,16 +25,18 @@ class GaiaRemoteConsentFlow ...@@ -25,16 +25,18 @@ class GaiaRemoteConsentFlow
WINDOW_CLOSED, WINDOW_CLOSED,
LOAD_FAILED, LOAD_FAILED,
SET_ACCOUNTS_IN_COOKIE_FAILED, SET_ACCOUNTS_IN_COOKIE_FAILED,
INVALID_CONSENT_RESULT,
NO_GRANT
}; };
class Delegate { class Delegate {
public: public:
virtual ~Delegate(); virtual ~Delegate();
// Called when the flow fails prior to the ConsentResult returned from // Called when the flow ends without getting the user consent.
// JavaScript. virtual void OnGaiaRemoteConsentFlowFailed(Failure failure) = 0;
virtual void OnGaiaRemoteConsentFlowFailure(Failure failure) = 0; // Called when the user gives the approval via the OAuth2 remote consent
// Called when the OAuth2 flow completes. // screen.
virtual void OnGaiaRemoteConsentFlowCompleted( virtual void OnGaiaRemoteConsentFlowApproved(
const std::string& consent_result) = 0; const std::string& consent_result) = 0;
}; };
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
namespace extensions { namespace extensions {
const char kWindowKey[] = "window_key"; const char kWindowKey[] = "window_key";
const char kConsentResult[] = "abcdef"; const char kConsentResult[] = "CAESCUVOQ1JZUFRFRA";
class FakeWebAuthFlowWithWindowKey : public WebAuthFlow { class FakeWebAuthFlowWithWindowKey : public WebAuthFlow {
public: public:
...@@ -58,9 +58,9 @@ class TestGaiaRemoteConsentFlow : public GaiaRemoteConsentFlow { ...@@ -58,9 +58,9 @@ class TestGaiaRemoteConsentFlow : public GaiaRemoteConsentFlow {
class MockGaiaRemoteConsentFlowDelegate class MockGaiaRemoteConsentFlowDelegate
: public GaiaRemoteConsentFlow::Delegate { : public GaiaRemoteConsentFlow::Delegate {
public: public:
MOCK_METHOD1(OnGaiaRemoteConsentFlowFailure, MOCK_METHOD1(OnGaiaRemoteConsentFlowFailed,
void(GaiaRemoteConsentFlow::Failure failure)); void(GaiaRemoteConsentFlow::Failure failure));
MOCK_METHOD1(OnGaiaRemoteConsentFlowCompleted, MOCK_METHOD1(OnGaiaRemoteConsentFlowApproved,
void(const std::string& consent_result)); void(const std::string& consent_result));
}; };
...@@ -99,7 +99,7 @@ class IdentityGaiaRemoteConsentFlowTest : public testing::Test { ...@@ -99,7 +99,7 @@ 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_, OnGaiaRemoteConsentFlowCompleted(kConsentResult)); EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowApproved(kConsentResult));
flow->OnConsentResultSet(kConsentResult, kWindowKey); flow->OnConsentResultSet(kConsentResult, kWindowKey);
} }
...@@ -116,19 +116,36 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult_TwoWindows) { ...@@ -116,19 +116,36 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult_TwoWindows) {
std::unique_ptr<TestGaiaRemoteConsentFlow> flow2 = std::unique_ptr<TestGaiaRemoteConsentFlow> flow2 =
CreateTestFlow(kWindowKey2, &delegate2); CreateTestFlow(kWindowKey2, &delegate2);
const char kConsentResult2[] = "ghijkl"; const char kConsentResult2[] = "CAESCkVOQ1JZUFRFRDI";
EXPECT_CALL(delegate2, OnGaiaRemoteConsentFlowCompleted(kConsentResult2)); EXPECT_CALL(delegate2, OnGaiaRemoteConsentFlowApproved(kConsentResult2));
flow2->OnConsentResultSet(kConsentResult2, kWindowKey2); flow2->OnConsentResultSet(kConsentResult2, kWindowKey2);
EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowCompleted(kConsentResult)); EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowApproved(kConsentResult));
flow->OnConsentResultSet(kConsentResult, kWindowKey); flow->OnConsentResultSet(kConsentResult, kWindowKey);
} }
TEST_F(IdentityGaiaRemoteConsentFlowTest, InvalidConsentResult) {
const char kInvalidConsentResult[] = "abc";
std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
EXPECT_CALL(delegate_,
OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure::INVALID_CONSENT_RESULT));
flow->OnConsentResultSet(kInvalidConsentResult, kWindowKey);
}
TEST_F(IdentityGaiaRemoteConsentFlowTest, NoGrant) {
const char kNoGrantConsentResult[] = "CAA";
std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure::NO_GRANT));
flow->OnConsentResultSet(kNoGrantConsentResult, kWindowKey);
}
TEST_F(IdentityGaiaRemoteConsentFlowTest, SetAccountsFailure) { TEST_F(IdentityGaiaRemoteConsentFlowTest, SetAccountsFailure) {
std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey); std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
EXPECT_CALL( EXPECT_CALL(
delegate_, delegate_,
OnGaiaRemoteConsentFlowFailure( OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure::SET_ACCOUNTS_IN_COOKIE_FAILED)); GaiaRemoteConsentFlow::Failure::SET_ACCOUNTS_IN_COOKIE_FAILED));
flow->OnSetAccountsComplete( flow->OnSetAccountsComplete(
signin::SetAccountsInCookieResult::kPersistentError); signin::SetAccountsInCookieResult::kPersistentError);
...@@ -136,14 +153,14 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, SetAccountsFailure) { ...@@ -136,14 +153,14 @@ TEST_F(IdentityGaiaRemoteConsentFlowTest, SetAccountsFailure) {
TEST_F(IdentityGaiaRemoteConsentFlowTest, WebAuthFlowFailure_WindowClosed) { TEST_F(IdentityGaiaRemoteConsentFlowTest, WebAuthFlowFailure_WindowClosed) {
std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey); std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowFailure( EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure::WINDOW_CLOSED)); GaiaRemoteConsentFlow::Failure::WINDOW_CLOSED));
flow->OnAuthFlowFailure(WebAuthFlow::Failure::WINDOW_CLOSED); flow->OnAuthFlowFailure(WebAuthFlow::Failure::WINDOW_CLOSED);
} }
TEST_F(IdentityGaiaRemoteConsentFlowTest, WebAuthFlowFailure_LoadFailed) { TEST_F(IdentityGaiaRemoteConsentFlowTest, WebAuthFlowFailure_LoadFailed) {
std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey); std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowFailure( EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure::LOAD_FAILED)); GaiaRemoteConsentFlow::Failure::LOAD_FAILED));
flow->OnAuthFlowFailure(WebAuthFlow::Failure::LOAD_FAILED); flow->OnAuthFlowFailure(WebAuthFlow::Failure::LOAD_FAILED);
} }
......
...@@ -19,6 +19,7 @@ const char kInvalidRedirect[] = "Did not redirect to the right URL."; ...@@ -19,6 +19,7 @@ const char kInvalidRedirect[] = "Did not redirect to the right URL.";
const char kOffTheRecord[] = "Identity API is disabled in incognito windows."; const char kOffTheRecord[] = "Identity API is disabled in incognito windows.";
const char kPageLoadFailure[] = "Authorization page could not be loaded."; const char kPageLoadFailure[] = "Authorization page could not be loaded.";
const char kSetAccountsInCookieFailure[] = "Account cookies could not be set."; const char kSetAccountsInCookieFailure[] = "Account cookies could not be set.";
const char kInvalidConsentResult[] = "Returned an invalid consent result.";
const char kCanceled[] = "canceled"; const char kCanceled[] = "canceled";
const int kCachedIssueAdviceTTLSeconds = 1; const int kCachedIssueAdviceTTLSeconds = 1;
......
...@@ -20,6 +20,7 @@ extern const char kInvalidRedirect[]; ...@@ -20,6 +20,7 @@ extern const char kInvalidRedirect[];
extern const char kOffTheRecord[]; extern const char kOffTheRecord[];
extern const char kPageLoadFailure[]; extern const char kPageLoadFailure[];
extern const char kSetAccountsInCookieFailure[]; extern const char kSetAccountsInCookieFailure[];
extern const char kInvalidConsentResult[];
extern const char kCanceled[]; extern const char kCanceled[];
extern const int kCachedIssueAdviceTTLSeconds; extern const int kCachedIssueAdviceTTLSeconds;
......
...@@ -704,7 +704,7 @@ void IdentityGetAuthTokenFunction::OnGaiaFlowCompleted( ...@@ -704,7 +704,7 @@ void IdentityGetAuthTokenFunction::OnGaiaFlowCompleted(
CompleteFunctionWithResult(access_token); CompleteFunctionWithResult(access_token);
} }
void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowFailure( void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure failure) { GaiaRemoteConsentFlow::Failure failure) {
CompleteMintTokenFlow(); CompleteMintTokenFlow();
std::string error; std::string error;
...@@ -721,12 +721,20 @@ void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowFailure( ...@@ -721,12 +721,20 @@ void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowFailure(
case GaiaRemoteConsentFlow::LOAD_FAILED: case GaiaRemoteConsentFlow::LOAD_FAILED:
error = identity_constants::kPageLoadFailure; error = identity_constants::kPageLoadFailure;
break; break;
case GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT:
error = identity_constants::kInvalidConsentResult;
break;
case GaiaRemoteConsentFlow::NO_GRANT:
error = identity_constants::kNoGrant;
break;
} }
CompleteFunctionWithError(error); CompleteFunctionWithError(error);
} }
void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowCompleted( void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowApproved(
const std::string& consent_result) { const std::string& consent_result) {
DCHECK(!consent_result.empty()); DCHECK(!consent_result.empty());
consent_result_ = consent_result; consent_result_ = consent_result;
......
...@@ -78,9 +78,9 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction, ...@@ -78,9 +78,9 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
const std::string& expiration) override; const std::string& expiration) override;
// GaiaRemoteConsentFlow::Delegate implementation: // GaiaRemoteConsentFlow::Delegate implementation:
void OnGaiaRemoteConsentFlowFailure( void OnGaiaRemoteConsentFlowFailed(
GaiaRemoteConsentFlow::Failure failure) override; GaiaRemoteConsentFlow::Failure failure) override;
void OnGaiaRemoteConsentFlowCompleted( void OnGaiaRemoteConsentFlowApproved(
const std::string& consent_result) override; const std::string& consent_result) override;
// Starts a login access token request. // Starts a login access token request.
......
...@@ -6,6 +6,7 @@ import("//build/config/chrome_build.gni") ...@@ -6,6 +6,7 @@ import("//build/config/chrome_build.gni")
import("//build/config/features.gni") import("//build/config/features.gni")
import("//extensions/buildflags/buildflags.gni") import("//extensions/buildflags/buildflags.gni")
import("//testing/test.gni") import("//testing/test.gni")
import("//third_party/protobuf/proto_library.gni")
declare_args() { declare_args() {
# You can set the variable 'use_official_google_api_keys' to true # You can set the variable 'use_official_google_api_keys' to true
...@@ -133,6 +134,7 @@ template("google_apis_tmpl") { ...@@ -133,6 +134,7 @@ template("google_apis_tmpl") {
] ]
deps = [ deps = [
":oauth2_mint_token_consent_result_proto",
"//base", "//base",
"//base/third_party/dynamic_annotations", "//base/third_party/dynamic_annotations",
"//build:branding_buildflags", "//build:branding_buildflags",
...@@ -169,6 +171,10 @@ google_apis_tmpl("google_apis") { ...@@ -169,6 +171,10 @@ google_apis_tmpl("google_apis") {
] ]
} }
proto_library("oauth2_mint_token_consent_result_proto") {
sources = [ "gaia/oauth2_mint_token_consent_result.proto" ]
}
static_library("test_support") { static_library("test_support") {
testonly = true testonly = true
sources = [ sources = [
...@@ -225,6 +231,7 @@ test("google_apis_unittests") { ...@@ -225,6 +231,7 @@ test("google_apis_unittests") {
deps = [ deps = [
":google_apis", ":google_apis",
":oauth2_mint_token_consent_result_proto",
":run_all_unittests", ":run_all_unittests",
":test_support", ":test_support",
"//base", "//base",
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include "base/base64url.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/json/json_reader.h" #include "base/json/json_reader.h"
#include "base/logging.h" #include "base/logging.h"
...@@ -16,6 +17,7 @@ ...@@ -16,6 +17,7 @@
#include "base/supports_user_data.h" #include "base/supports_user_data.h"
#include "base/values.h" #include "base/values.h"
#include "google_apis/gaia/gaia_urls.h" #include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/oauth2_mint_token_consent_result.pb.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace gaia { namespace gaia {
...@@ -177,4 +179,26 @@ bool ParseListAccountsData(const std::string& data, ...@@ -177,4 +179,26 @@ bool ParseListAccountsData(const std::string& data,
return true; return true;
} }
bool ParseOAuth2MintTokenConsentResult(const std::string& consent_result,
bool* approved) {
DCHECK(approved);
std::string decoded_result;
if (!base::Base64UrlDecode(consent_result,
base::Base64UrlDecodePolicy::DISALLOW_PADDING,
&decoded_result)) {
VLOG(1) << "Base64UrlDecode() failed to decode the consent result";
return false;
}
OAuth2MintTokenConsentResult parsed_result;
if (!parsed_result.ParseFromString(decoded_result)) {
VLOG(1) << "Failed to parse the consent result protobuf message";
return false;
}
*approved = parsed_result.approved();
return true;
}
} // namespace gaia } // namespace gaia
...@@ -67,6 +67,13 @@ bool ParseListAccountsData(const std::string& data, ...@@ -67,6 +67,13 @@ bool ParseListAccountsData(const std::string& data,
std::vector<ListedAccount>* accounts, std::vector<ListedAccount>* accounts,
std::vector<ListedAccount>* signed_out_accounts); std::vector<ListedAccount>* signed_out_accounts);
// Parses base64url encoded protobuf message returned by the remote consent
// flow, returning whether the consent was approved.
// Returns false if the method failed to decode the protobuf.
// |approved| must not be null.
bool ParseOAuth2MintTokenConsentResult(const std::string& consent_result,
bool* approved);
} // namespace gaia } // namespace gaia
#endif // GOOGLE_APIS_GAIA_GAIA_AUTH_UTIL_H_ #endif // GOOGLE_APIS_GAIA_GAIA_AUTH_UTIL_H_
...@@ -4,11 +4,34 @@ ...@@ -4,11 +4,34 @@
#include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_auth_util.h"
#include "base/base64url.h"
#include "base/optional.h"
#include "google_apis/gaia/oauth2_mint_token_consent_result.pb.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace gaia { namespace gaia {
namespace {
std::string GenerateOAuth2MintTokenConsentResult(
base::Optional<bool> approved,
const base::Optional<std::string>& encrypted_approval_data,
base::Base64UrlEncodePolicy encode_policy =
base::Base64UrlEncodePolicy::OMIT_PADDING) {
OAuth2MintTokenConsentResult consent_result;
if (approved.has_value())
consent_result.set_approved(approved.value());
if (encrypted_approval_data.has_value())
consent_result.set_encrypted_approval_data(encrypted_approval_data.value());
std::string serialized_consent = consent_result.SerializeAsString();
std::string encoded_consent;
base::Base64UrlEncode(serialized_consent, encode_policy, &encoded_consent);
return encoded_consent;
}
} // namespace
TEST(GaiaAuthUtilTest, EmailAddressNoOp) { TEST(GaiaAuthUtilTest, EmailAddressNoOp) {
const char lower_case[] = "user@what.com"; const char lower_case[] = "user@what.com";
EXPECT_EQ(lower_case, CanonicalizeEmail(lower_case)); EXPECT_EQ(lower_case, CanonicalizeEmail(lower_case));
...@@ -321,4 +344,65 @@ TEST(GaiaAuthUtilTest, ParseListAccountsAcceptsNull) { ...@@ -321,4 +344,65 @@ TEST(GaiaAuthUtilTest, ParseListAccountsAcceptsNull) {
ASSERT_TRUE(signed_out_accounts[0].signed_out); ASSERT_TRUE(signed_out_accounts[0].signed_out);
} }
TEST(GaiaAuthUtilTest, ParseConsentResultApproved) {
const char kApprovedConsent[] = "CAESCUVOQ1JZUFRFRA";
EXPECT_EQ(kApprovedConsent,
GenerateOAuth2MintTokenConsentResult(true, "ENCRYPTED"));
bool approved = false;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult(kApprovedConsent, &approved));
EXPECT_TRUE(approved);
}
TEST(GaiaAuthUtilTest, ParseConsentResultApprovedEmptyData) {
const char kApprovedConsent[] = "CAE";
EXPECT_EQ(kApprovedConsent,
GenerateOAuth2MintTokenConsentResult(true, base::nullopt));
bool approved = false;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult(kApprovedConsent, &approved));
EXPECT_TRUE(approved);
}
TEST(GaiaAuthUtilTest, ParseConsentResultNotApproved) {
const char kNoGrantConsent[] = "CAA";
EXPECT_EQ(kNoGrantConsent,
GenerateOAuth2MintTokenConsentResult(false, base::nullopt));
bool approved = false;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult(kNoGrantConsent, &approved));
EXPECT_FALSE(approved);
}
TEST(GaiaAuthUtilTest, ParseConsentResultEmpty) {
EXPECT_EQ("",
GenerateOAuth2MintTokenConsentResult(base::nullopt, base::nullopt));
bool approved = false;
ASSERT_TRUE(ParseOAuth2MintTokenConsentResult("", &approved));
// false is the default value for a bool in proto.
EXPECT_FALSE(approved);
}
TEST(GaiaAuthUtilTest, ParseConsentResultBase64UrlDisallowedPadding) {
const char kApprovedConsentWithPadding[] = "CAE=";
EXPECT_EQ(
kApprovedConsentWithPadding,
GenerateOAuth2MintTokenConsentResult(
true, base::nullopt, base::Base64UrlEncodePolicy::INCLUDE_PADDING));
bool approved = false;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kApprovedConsentWithPadding,
&approved));
}
TEST(GaiaAuthUtilTest, ParseConsentResultInvalidBase64Url) {
const char kMalformedConsent[] =
"+/"; // '+' and '/' are disallowed in base64url alphabet.
bool approved = false;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kMalformedConsent, &approved));
}
TEST(GaiaAuthUtilTest, ParseConsentResultInvalidProto) {
const char kMalformedConsent[] =
"ab"; // Valid base64url string but invalid proto.
bool approved = false;
EXPECT_FALSE(ParseOAuth2MintTokenConsentResult(kMalformedConsent, &approved));
}
} // namespace gaia } // namespace gaia
// Copyright 2020 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.
syntax = "proto2";
package gaia;
// Required in Chrome.
option optimize_for = LITE_RUNTIME;
// This message is a pass-through for chrome.identity extension remote consent
// implementation. It is both created and consumed by LSO, and passed through
// the browser via as a web-safe omit-padding base64-encoded string in the
// `consent_result` field of the IssueToken request.
message OAuth2MintTokenConsentResult {
optional bool approved = 1;
// Opaque data to be passed to the IssueToken.
// Absent if `approved` is false.
optional bytes encrypted_approval_data = 2;
}
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