chromium/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"

#include <memory>
#include <string>
#include <string_view>
#include <vector>

#include "base/containers/flat_set.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ref.h"
#include "base/strings/string_util.h"
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
#include "net/http/http_response_headers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/origin_trials/origin_trial_policy.h"
#include "third_party/blink/public/common/origin_trials/trial_token.h"
#include "third_party/blink/public/common/origin_trials/trial_token_result.h"
#include "url/gurl.h"

namespace blink::trial_token_validator_unittest {

// These are sample public keys for testing the API.

// For the first public key, the corresponding private key (use this
// to generate new samples for this test file) is:
//
//  0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43, 0x13,
//  0x4c, 0x67, 0xc4, 0xf4, 0x28, 0xc9, 0x90, 0x15, 0x02, 0xe2, 0xba,
//  0xfd, 0xbb, 0xfa, 0xbc, 0x92, 0x76, 0x8a, 0x2c, 0x4b, 0xc7, 0x75,
//  0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2, 0x9a,
//  0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f, 0x64,
//  0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0

//  For the second public key, the corresponding private key is:

//  0x21, 0xee, 0xfa, 0x81, 0x6a, 0xff, 0xdf, 0xb8, 0xc1, 0xdd, 0x75,
//  0x05, 0x04, 0x29, 0x68, 0x67, 0x60, 0x85, 0x91, 0xd0, 0x50, 0x16,
//  0x0a, 0xcf, 0xa2, 0x37, 0xa3, 0x2e, 0x11, 0x7a, 0x17, 0x96, 0x50,
//  0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c, 0x47,
//  0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51, 0x3e,
//  0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca
const OriginTrialPublicKey kTestPublicKey1 =;

const OriginTrialPublicKey kTestPublicKey2 =;

// This is a good trial token, signed with the above test private key.
// TODO(iclelland): This token expires in 2033. Update it or find a way
// to autogenerate it before then.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py valid.example.com Frobulate --expire-timestamp=2000000000
const char kSampleToken[] =;
const uint8_t kSampleTokenSignature[] =;

// The expiry time of the sample token (2033-05-18 03:33:20 UTC).
const base::Time kSampleTokenExpiryTime =;

// This is a trial token signed with the corresponding private key
// for kTestPublicKeys2
// TODO(iclelland): This token expires in 2033. Update it or find a way
// to autogenerate it before then.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py valid.example.com Frobulate --expire-timestamp=2000000000
// --key-file=eftest2.key
const char kSampleToken2[] =;

// The token should be valid for this origin and for this feature.
const char kAppropriateOrigin[] =;
const char kAppropriateFeatureName[] =;
const char kAppropriateThirdPartyFeatureName[] =;
const char kAppropriateDeprecationFeatureName[] =;
const char kAppropriateGracePeriodFeatureName[] =;

const char kInappropriateFeatureName[] =;
const char kInappropriateOrigin[] =;
const char kInsecureOrigin[] =;
const char kUnrelatedOrigin[] =;

// Well-formed trial token with an invalid signature.
// This token is a corruption of the above valid token.
const char kInvalidSignatureToken[] =;

// Well-formed, but expired, trial token. (Expired in 2001)
// Generate this token with the command (in tools/origin_trials):
// generate_token.py valid.example.com Frobulate --expire-timestamp=1000000000
const char kExpiredToken[] =;
const uint8_t kExpiredTokenSignature[] =;

const char kUnparsableToken[] =;

// Well-formed token, for an insecure origin.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py http://valid.example.com Frobulate
// --expire-timestamp=2000000000
const char kInsecureOriginToken[] =;

// Well-formed token, for match against third party origins.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py valid.example.com FrobulateThirdParty
// --is-third-party --expire-timestamp=2000000000
const char kThirdPartyToken[] =;

// Well-formed token, for match against third party origins and its usage
// set to user subset exclusion.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py valid.example.com FrobulateThirdParty
//  --version 3 --is-third-party --usage-restriction subset
//  --expire-timestamp=2000000000
const char kThirdPartyUsageSubsetToken[] =;

// Well-formed token, for first party, with usage set to user subset exclusion.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py valid.example.com FrobulateThirdParty
//  --version 3 --usage-restriction subset --expire-timestamp=2000000000
const char kUsageSubsetToken[] =;

// Well-formed token for a feature with an expiry grace period.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py valid.example.com FrobulateExpiryGracePeriod
//  --expire-timestamp=2000000000
const char kExpiryGracePeriodToken[] =;

// Well-formed token for match against third party origins and a feature with an
// expiry grace period.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py valid.example.com FrobulateExpiryGracePeriodThirdParty
//  --is-third-party --expire-timestamp=2000000000
const char kExpiryGracePeriodThirdPartyToken[] =;

// Well-formed token, with an unknown feature name.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py valid.example.com Grokalyze
//  --expire-timestamp=2000000000
const char kUnknownFeatureToken[] =;

// Well-formed token for match against third party origins, with an unknown
// feature name. Generate this token with the command (in tools/origin_trials):
// generate_token.py valid.example.com Grokalyze
//  --is-third-party --expire-timestamp=2000000000
const char kUnknownFeatureThirdPartyToken[] =;

// Well-formed token, for match against third party origins for a trial that
// doesn't allow third-party origins.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py valid.example.com Frobulate
// --is-third-party --expire-timestamp=2000000000
const char kThirdPartyTokenForNonThirdPartyTrial[] =;

// Well-formed token, for match against insecure origins for a deprecation
// trial.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py http://valid.example.com FrobulateDeprecation
// --expire-timestamp=2000000000
const char kDeprecationInsecureToken[] =;

// Well-formed token, for match against insecure third-party origins.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py http://valid.example.com FrobulateThirdParty
// --is-third-party --expire-timestamp=2000000000
const char kThirdPartyInsecureToken[] =;

// Well-formed token, for match against subdomain origins.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py example.com Frobulate
// --is-subdomain --expire-timestamp=2000000000
const char kSubdomainToken[] =;

// Well-formed token, for match against third-party subdomain origins.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py example.com FrobulateThirdParty
// --is-subdomain --is-third-party --expire-timestamp=2000000000
const char kThirdPartySubdomainToken[] =;

// Token for insecure third-party subdomain matching.
// Generate this token with the command (in tools/origin_trials):
// generate_token.py http://example.com FrobulateThirdParty
// --is-subdomain --is-third-party --expire-timestamp=2000000000
const char kThirdPartyInsecureSubdomainToken[] =;

// This timestamp is set to a time after the expiry timestamp of kExpiredToken,
// but before the expiry timestamp of kValidToken.
double kNowTimestamp =;

class TestOriginTrialPolicy : public OriginTrialPolicy {};

class TrialTokenValidatorTest : public testing::Test {};

// Define two classes that wrap the ValidateToken and ValidateTokenAndTrial
// methods respectively under a common name, so we can repeat the tests for each
// function where it makes sense
class ValidateTokenWrapper {};

class ValidateTokenAndTrialWrapper : public ValidateTokenWrapper {};

class ValidateTokenAndTrialWithOriginInfoWrapper : public ValidateTokenWrapper {};
// Factory classes that allows us to instantiate a parameterized test
class ValidateTokenWrapperFactory {};

class ValidateTokenAndTrialWrapperFactory : public ValidateTokenWrapperFactory {};

class ValidateTokenAndTrialWithOriginInfoWrapperFactory
    : public ValidateTokenWrapperFactory {};

// Test suite for tests where TrialTokenValidator::ValidateToken and
// TrialTokenValidator::ValidateTokenAndTrial should yield the same result
class TrialTokenValidatorEquivalenceTest
    : public TrialTokenValidatorTest,
      public testing::WithParamInterface<ValidateTokenWrapperFactory> {};

// Tests of the basic ValidateToken functionality where ValidateTokenAndTrial
// should yield the same result
// Using TrialTokenValidatorTest as prefix to allow for unified gtest_filter
INSTANTIATE_TEST_SUITE_P();

TEST_P(TrialTokenValidatorEquivalenceTest, ValidateValidToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidateThirdPartyToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest,
       ValidateThirdPartyTokenFromExternalScript) {}

TEST_P(TrialTokenValidatorEquivalenceTest,
       ValidateThirdPartyTokenFromMultipleExternalScripts) {}

TEST_P(TrialTokenValidatorEquivalenceTest,
       ValidateThirdPartyTokenFromInappropriateScriptOrigin) {}

TEST_P(TrialTokenValidatorEquivalenceTest,
       ValidateThirdPartyTokenFromMultipleInappropriateScriptOrigins) {}

TEST_P(TrialTokenValidatorEquivalenceTest,
       ValidateThirdPartyTokenNotFromExternalScript) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidateInappropriateOrigin) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidateInvalidSignature) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidateUnparsableToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidateExpiredToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidateValidTokenWithIncorrectKey) {}

TEST_P(TrialTokenValidatorEquivalenceTest, PublicKeyNotAvailable) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidatorRespectsDisabledFeatures) {}
TEST_P(TrialTokenValidatorEquivalenceTest,
       ValidatorRespectsDisabledFeaturesForUserWithFirstPartyToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest,
       ValidatorRespectsDisabledFeaturesForUserWithThirdPartyToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidatorRespectsDisabledTokens) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidateValidExpiryGraceToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidateExpiredExpiryGraceToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest,
       ValidateValidExpiryGraceThirdPartyToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest,
       ValidateExpiredExpiryGraceThirdPartyToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidateSubdomainToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest,
       ValidateSubdomainTokenUnrelatedOrigin) {}

TEST_P(TrialTokenValidatorEquivalenceTest, ValidateThirdPartySubdomainToken) {}

TEST_P(TrialTokenValidatorEquivalenceTest,
       ValidateThirdPartySubdomainTokenInsecureOrigin) {}

// Tests of RequestEnablesFeature methods

TEST_F(TrialTokenValidatorTest, ValidateRequestInsecure) {}

TEST_F(TrialTokenValidatorTest, ValidateRequestForDeprecationInsecure) {}

TEST_F(TrialTokenValidatorTest, ValidateRequestValidToken) {}

TEST_F(TrialTokenValidatorTest, ValidateRequestForDeprecationValidToken) {}

TEST_F(TrialTokenValidatorTest, ValidateRequestNoTokens) {}

TEST_F(TrialTokenValidatorTest, ValidateRequestForDeprecationNoTokens) {}

TEST_F(TrialTokenValidatorTest, ValidateRequestMultipleHeaders) {}

TEST_F(TrialTokenValidatorTest, ValidateRequestMultipleHeaderValues) {}

TEST_F(TrialTokenValidatorTest, ValidateRequestUnknownFeatureToken) {}

// Tests where ValidateToken and ValidateTokenAndTrial are expected
// to yield different results.
// These tests should test both |ValidateToken|, |ValidateTokenAndTrial|,
// and |ValidateTokenAndTrialWithOriginInfo| to ensure all entry points
// give the expected results

TEST_F(TrialTokenValidatorTest, ValidateUnknownFeatureToken) {}

TEST_F(TrialTokenValidatorTest, ValidateUnknownFeatureThirdPartyToken) {}

TEST_F(TrialTokenValidatorTest, ValidateInsecureToken) {}

TEST_F(TrialTokenValidatorTest,
       ValidateThirdPartyTokenForNonThirdPartyFeature) {}

TEST_F(TrialTokenValidatorTest, ValidateInsecureThirdPartyToken) {}

TEST_F(TrialTokenValidatorTest, ValidateInsecureThirdPartyTokenInsecureOrigin) {}

TEST_F(TrialTokenValidatorTest,
       ValidateInsecureThirdPartyTokenMultipleOrigins) {}

TEST_F(TrialTokenValidatorTest, ValidateThirdPartyTokenInsecureOrigin) {}

// Tests that only check the behaviour of
// |ValidateTokenAndTrialWithOriginInfo| - these are the ones
// that rely on changes in passing in specific OriginInfo

TEST_F(TrialTokenValidatorTest, ValidateInsecureOriginInfo) {}

TEST_F(TrialTokenValidatorTest, ValidateInsecureOriginThirdPartyOriginInfo) {}

TEST_F(TrialTokenValidatorTest,
       ValidateInsecureThirdPartyOriginThirdPartyOriginInfo) {}

TEST_F(TrialTokenValidatorTest,
       ValidateMultipleInsecureThirdPartyOriginThirdPartyOriginInfo) {}

//
// Tests of |RevalidateTokenAndTrial|
//
TEST_F(TrialTokenValidatorTest, RevalidateTokenInformation) {}

TEST_F(TrialTokenValidatorTest, RevalidateExpiredToken) {}

TEST_F(TrialTokenValidatorTest, RevalidateDisabledTrial) {}

TEST_F(TrialTokenValidatorTest, RevalidateDisabledToken) {}

TEST_F(TrialTokenValidatorTest, RevalidateDisabledTrialForUser) {}

TEST_F(TrialTokenValidatorTest, XRWTrialAllowedForAll3POrigins) {}

}  // namespace blink::trial_token_validator_unittest