BlindSignAuth: Refactor Privacy Pass auth flow by splitting it into reusable functions.

PiperOrigin-RevId: 776695229
diff --git a/quiche/blind_sign_auth/blind_sign_auth.cc b/quiche/blind_sign_auth/blind_sign_auth.cc
index d7f8542..8c0415d 100644
--- a/quiche/blind_sign_auth/blind_sign_auth.cc
+++ b/quiche/blind_sign_auth/blind_sign_auth.cc
@@ -44,6 +44,30 @@
 
 constexpr absl::string_view kIssuerHostname =
     "https://ipprotection-ppissuer.googleapis.com";
+constexpr size_t kExpectedExtensionTypesSize = 5;
+constexpr std::array<uint16_t, kExpectedExtensionTypesSize>
+    kExpectedExtensionTypes = {0x0001, 0x0002, 0xF001, 0xF002, 0xF003};
+
+using privacy::ppn::AuthAndSignRequest;
+using privacy::ppn::AuthAndSignResponse;
+using privacy::ppn::GetInitialDataRequest;
+using privacy::ppn::GetInitialDataResponse;
+using privacy::ppn::PrivacyPassTokenData;
+using anonymous_tokens::AnonymousTokensUseCase;
+using anonymous_tokens::CreatePublicKeyRSA;
+using anonymous_tokens::DecodeExtensions;
+using anonymous_tokens::ExpirationTimestamp;
+using anonymous_tokens::ExtendedTokenRequest;
+using anonymous_tokens::Extensions;
+using anonymous_tokens::GeoHint;
+using anonymous_tokens::MarshalTokenChallenge;
+using anonymous_tokens::ParseUseCase;
+using anonymous_tokens::
+    PrivacyPassRsaBssaPublicMetadataClient;
+using anonymous_tokens::RSAPublicKey;
+using anonymous_tokens::Token;
+using anonymous_tokens::TokenChallenge;
+using anonymous_tokens::ValidateExtensionsOrderAndValues;
 
 }  // namespace
 
@@ -52,7 +76,7 @@
                               BlindSignAuthServiceType service_type,
                               SignedTokenCallback callback) {
   // Create GetInitialData RPC.
-  privacy::ppn::GetInitialDataRequest request;
+  GetInitialDataRequest request;
   request.set_use_attestation(false);
   request.set_service_type(BlindSignAuthServiceTypeToString(service_type));
   request.set_location_granularity(
@@ -75,38 +99,21 @@
     ProxyLayer proxy_layer, BlindSignAuthServiceType service_type,
     SignedTokenCallback callback,
     absl::StatusOr<BlindSignMessageResponse> response) {
-  if (!response.ok()) {
-    QUICHE_LOG(WARNING) << "GetInitialDataRequest failed: "
-                        << response.status();
-    std::move(callback)(absl::InvalidArgumentError(
-        "GetInitialDataRequest failed: invalid response"));
-    return;
-  }
-  absl::StatusCode code = response->status_code();
-  if (code != absl::StatusCode::kOk) {
-    std::string message =
-        absl::StrCat("GetInitialDataRequest failed with code: ", code);
-    QUICHE_LOG(WARNING) << message;
-    std::move(callback)(absl::InvalidArgumentError(message));
-    return;
-  }
-  // Parse GetInitialDataResponse.
-  privacy::ppn::GetInitialDataResponse initial_data_response;
-  if (!initial_data_response.ParseFromString(response->body())) {
-    QUICHE_LOG(WARNING) << "Failed to parse GetInitialDataResponse";
-    std::move(callback)(
-        absl::InternalError("Failed to parse GetInitialDataResponse"));
+  absl::StatusOr<GetInitialDataResponse> initial_data_response =
+      ParseGetInitialDataResponseMessage(response);
+  if (!initial_data_response.ok()) {
+    std::move(callback)(initial_data_response.status());
     return;
   }
 
   // Create token signing requests.
-  bool use_privacy_pass_client =
-      initial_data_response.has_privacy_pass_data() &&
+  const bool use_privacy_pass_client =
+      initial_data_response->has_privacy_pass_data() &&
       auth_options_.enable_privacy_pass();
 
   if (use_privacy_pass_client) {
     QUICHE_DVLOG(1) << "Using Privacy Pass client";
-    GeneratePrivacyPassTokens(initial_data_response, std::move(oauth_token),
+    GeneratePrivacyPassTokens(*initial_data_response, std::move(oauth_token),
                               num_tokens, proxy_layer, service_type,
                               std::move(callback));
   } else {
@@ -121,73 +128,18 @@
     std::optional<std::string> oauth_token, int num_tokens,
     ProxyLayer proxy_layer, BlindSignAuthServiceType service_type,
     SignedTokenCallback callback) {
-  // Set up values used in the token generation loop.
-  anonymous_tokens::RSAPublicKey public_key_proto;
-  if (!public_key_proto.ParseFromString(
-          initial_data_response.at_public_metadata_public_key()
-              .serialized_public_key())) {
-    std::move(callback)(
-        absl::InvalidArgumentError("Failed to parse Privacy Pass public key"));
+  absl::StatusOr<PrivacyPassContext> pp_context =
+      CreatePrivacyPassContext(initial_data_response);
+  if (!pp_context.ok()) {
+    std::move(callback)(pp_context.status());
     return;
   }
-  absl::StatusOr<bssl::UniquePtr<RSA>> bssl_rsa_key =
-      anonymous_tokens::CreatePublicKeyRSA(
-          public_key_proto.n(), public_key_proto.e());
-  if (!bssl_rsa_key.ok()) {
-    QUICHE_LOG(ERROR) << "Failed to create RSA public key: "
-                      << bssl_rsa_key.status();
-    std::move(callback)(absl::InternalError("Failed to create RSA public key"));
-    return;
-  }
-  absl::StatusOr<anonymous_tokens::Extensions> extensions =
-      anonymous_tokens::DecodeExtensions(
-          initial_data_response.privacy_pass_data()
-              .public_metadata_extensions());
-  if (!extensions.ok()) {
-    QUICHE_LOG(WARNING) << "Failed to decode extensions: "
-                        << extensions.status();
-    std::move(callback)(
-        absl::InvalidArgumentError("Failed to decode extensions"));
-    return;
-  }
-  std::vector<uint16_t> kExpectedExtensionTypes = {
-      /*ExpirationTimestamp=*/0x0001, /*GeoHint=*/0x0002,
-      /*ServiceType=*/0xF001, /*DebugMode=*/0xF002, /*ProxyLayer=*/0xF003};
-  // TODO(b/345801768): Improve the API of
-  // `anonymous_tokens::ValidateExtensionsOrderAndValues` to
-  // avoid any possible TOCTOU problems.
-  absl::Status result =
-      anonymous_tokens::ValidateExtensionsOrderAndValues(
-          *extensions, absl::MakeSpan(kExpectedExtensionTypes), absl::Now());
-  if (!result.ok()) {
-    QUICHE_LOG(WARNING) << "Failed to validate extensions: " << result;
-    std::move(callback)(
-        absl::InvalidArgumentError("Failed to validate extensions"));
-    return;
-  }
-  absl::StatusOr<anonymous_tokens::ExpirationTimestamp>
-      expiration_timestamp = anonymous_tokens::
-          ExpirationTimestamp::FromExtension(extensions->extensions.at(0));
-  if (!expiration_timestamp.ok()) {
-    QUICHE_LOG(WARNING) << "Failed to parse expiration timestamp: "
-                        << expiration_timestamp.status();
-    std::move(callback)(
-        absl::InvalidArgumentError("Failed to parse expiration timestamp"));
-    return;
-  }
-  absl::Time public_metadata_expiry_time =
-      absl::FromUnixSeconds(expiration_timestamp->timestamp);
-
-  absl::StatusOr<anonymous_tokens::GeoHint> geo_hint =
-      anonymous_tokens::GeoHint::FromExtension(
-          extensions->extensions.at(1));
-  QUICHE_CHECK(geo_hint.ok());
 
   // Create token challenge.
-  anonymous_tokens::TokenChallenge challenge;
+  TokenChallenge challenge;
   challenge.issuer_name = kIssuerHostname;
   absl::StatusOr<std::string> token_challenge =
-      anonymous_tokens::MarshalTokenChallenge(challenge);
+      MarshalTokenChallenge(challenge);
   if (!token_challenge.ok()) {
     QUICHE_LOG(WARNING) << "Failed to marshal token challenge: "
                         << token_challenge.status();
@@ -196,78 +148,34 @@
     return;
   }
 
-  QuicheRandom* random = QuicheRandom::GetInstance();
-  // Create vector of Privacy Pass clients, one for each token.
-  std::vector<anonymous_tokens::ExtendedTokenRequest>
-      extended_token_requests;
-  std::vector<std::unique_ptr<anonymous_tokens::
-                                  PrivacyPassRsaBssaPublicMetadataClient>>
-      privacy_pass_clients;
-  std::vector<std::string> privacy_pass_blinded_tokens;
-
-  for (int i = 0; i < num_tokens; i++) {
-    // Create client.
-    auto client = anonymous_tokens::
-        PrivacyPassRsaBssaPublicMetadataClient::Create(*bssl_rsa_key.value());
-    if (!client.ok()) {
-      QUICHE_LOG(WARNING) << "Failed to create Privacy Pass client: "
-                          << client.status();
-      std::move(callback)(
-          absl::InternalError("Failed to create Privacy Pass client"));
-      return;
-    }
-
-    // Create nonce.
-    std::string nonce_rand(32, '\0');
-    random->RandBytes(nonce_rand.data(), nonce_rand.size());
-
-    // Create token request.
-    absl::StatusOr<anonymous_tokens::ExtendedTokenRequest>
-        extended_token_request = client.value()->CreateTokenRequest(
-            *token_challenge, nonce_rand,
-            initial_data_response.privacy_pass_data().token_key_id(),
-            *extensions);
-    if (!extended_token_request.ok()) {
-      QUICHE_LOG(WARNING) << "Failed to create ExtendedTokenRequest: "
-                          << extended_token_request.status();
-      std::move(callback)(
-          absl::InternalError("Failed to create ExtendedTokenRequest"));
-      return;
-    }
-    privacy_pass_clients.push_back(*std::move(client));
-    extended_token_requests.push_back(*extended_token_request);
-    privacy_pass_blinded_tokens.push_back(absl::Base64Escape(
-        extended_token_request->request.blinded_token_request));
+  absl::StatusOr<GeneratedTokenRequests> token_requests_data =
+      GenerateBlindedTokenRequests(num_tokens, *pp_context->rsa_public_key,
+                                   *token_challenge, pp_context->token_key_id,
+                                   pp_context->extensions);
+  if (!token_requests_data.ok()) {
+    std::move(callback)(token_requests_data.status());
+    return;
   }
 
-  privacy::ppn::AuthAndSignRequest sign_request;
+  AuthAndSignRequest sign_request;
   sign_request.set_service_type(BlindSignAuthServiceTypeToString(service_type));
   sign_request.set_key_type(privacy::ppn::AT_PUBLIC_METADATA_KEY_TYPE);
   sign_request.set_key_version(
       initial_data_response.at_public_metadata_public_key().key_version());
-  sign_request.mutable_blinded_token()->Assign(
-      privacy_pass_blinded_tokens.begin(), privacy_pass_blinded_tokens.end());
+  *sign_request.mutable_blinded_token() = {
+      token_requests_data->privacy_pass_blinded_tokens_b64.begin(),
+      token_requests_data->privacy_pass_blinded_tokens_b64.end()};
   sign_request.mutable_public_metadata_extensions()->assign(
       initial_data_response.privacy_pass_data().public_metadata_extensions());
   // TODO(b/295924807): deprecate this option after AT server defaults to it
   sign_request.set_do_not_use_rsa_public_exponent(true);
   sign_request.set_proxy_layer(QuicheProxyLayerToPpnProxyLayer(proxy_layer));
 
-  absl::StatusOr<anonymous_tokens::AnonymousTokensUseCase>
-      use_case = anonymous_tokens::ParseUseCase(
-          initial_data_response.at_public_metadata_public_key().use_case());
-  if (!use_case.ok()) {
-    QUICHE_LOG(WARNING) << "Failed to parse use case: " << use_case.status();
-    std::move(callback)(absl::InvalidArgumentError("Failed to parse use case"));
-    return;
-  }
-
   BlindSignMessageCallback auth_and_sign_callback =
       absl::bind_front(&BlindSignAuth::PrivacyPassAuthAndSignCallback, this,
-                       std::move(initial_data_response.privacy_pass_data()
-                                     .public_metadata_extensions()),
-                       public_metadata_expiry_time, *geo_hint, *use_case,
-                       std::move(privacy_pass_clients), std::move(callback));
+                       *std::move(pp_context),
+                       std::move(token_requests_data->privacy_pass_clients),
+                       std::move(callback));
   // TODO(b/304811277): remove other usages of string.data()
   fetcher_->DoRequest(BlindSignMessageRequestType::kAuthAndSign, oauth_token,
                       sign_request.SerializeAsString(),
@@ -275,9 +183,7 @@
 }
 
 void BlindSignAuth::PrivacyPassAuthAndSignCallback(
-    std::string encoded_extensions, absl::Time public_key_expiry_time,
-    anonymous_tokens::GeoHint geo_hint,
-    anonymous_tokens::AnonymousTokensUseCase use_case,
+    const PrivacyPassContext& pp_context,
     std::vector<std::unique_ptr<anonymous_tokens::
                                     PrivacyPassRsaBssaPublicMetadataClient>>
         privacy_pass_clients,
@@ -299,7 +205,7 @@
   }
 
   // Decode AuthAndSignResponse.
-  privacy::ppn::AuthAndSignResponse sign_response;
+  AuthAndSignResponse sign_response;
   if (!sign_response.ParseFromString(response->body())) {
     QUICHE_LOG(WARNING) << "Failed to parse AuthAndSignResponse";
     std::move(callback)(
@@ -328,7 +234,7 @@
       return;
     }
 
-    absl::StatusOr<anonymous_tokens::Token> token =
+    absl::StatusOr<Token> token =
         privacy_pass_clients[i]->FinalizeToken(unescaped_blinded_sig);
     if (!token.ok()) {
       QUICHE_LOG(WARNING) << "Failed to finalize token: " << token.status();
@@ -336,8 +242,7 @@
       return;
     }
 
-    absl::StatusOr<std::string> marshaled_token =
-        anonymous_tokens::MarshalToken(*token);
+    absl::StatusOr<std::string> marshaled_token = MarshalToken(*token);
     if (!marshaled_token.ok()) {
       QUICHE_LOG(WARNING) << "Failed to marshal token: "
                           << marshaled_token.status();
@@ -345,35 +250,21 @@
       return;
     }
 
-    privacy::ppn::PrivacyPassTokenData privacy_pass_token_data;
+    PrivacyPassTokenData privacy_pass_token_data;
     privacy_pass_token_data.mutable_token()->assign(
         ConvertBase64ToWebSafeBase64(absl::Base64Escape(*marshaled_token)));
     privacy_pass_token_data.mutable_encoded_extensions()->assign(
-        ConvertBase64ToWebSafeBase64(absl::Base64Escape(encoded_extensions)));
-    privacy_pass_token_data.set_use_case_override(use_case);
-    tokens_vec.push_back(
-        BlindSignToken{privacy_pass_token_data.SerializeAsString(),
-                       public_key_expiry_time, geo_hint});
+        ConvertBase64ToWebSafeBase64(
+            absl::Base64Escape(pp_context.public_metadata_extensions_str)));
+    privacy_pass_token_data.set_use_case_override(pp_context.use_case);
+    tokens_vec.push_back(BlindSignToken{
+        privacy_pass_token_data.SerializeAsString(),
+        pp_context.public_metadata_expiry_time, pp_context.geo_hint});
   }
 
   std::move(callback)(absl::Span<BlindSignToken>(tokens_vec));
 }
 
-privacy::ppn::ProxyLayer BlindSignAuth::QuicheProxyLayerToPpnProxyLayer(
-    quiche::ProxyLayer proxy_layer) {
-  switch (proxy_layer) {
-    case ProxyLayer::kProxyA: {
-      return privacy::ppn::ProxyLayer::PROXY_A;
-    }
-    case ProxyLayer::kProxyB: {
-      return privacy::ppn::ProxyLayer::PROXY_B;
-    }
-    case ProxyLayer::kTerminalLayer: {
-      return privacy::ppn::ProxyLayer::TERMINAL_LAYER;
-    }
-  }
-}
-
 void BlindSignAuth::GetAttestationTokens(int /*num_tokens*/,
                                          ProxyLayer /*layer*/,
                                          AttestationDataCallback callback) {
@@ -391,6 +282,158 @@
       absl::UnimplementedError("AttestAndSign is not implemented"));
 }
 
+absl::StatusOr<privacy::ppn::GetInitialDataResponse>
+BlindSignAuth::ParseGetInitialDataResponseMessage(
+    const absl::StatusOr<BlindSignMessageResponse>& response) {
+  if (!response.ok()) {
+    QUICHE_LOG(WARNING) << "GetInitialDataRequest failed: "
+                        << response.status();
+    return absl::InvalidArgumentError(
+        "GetInitialDataRequest failed: invalid response");
+  }
+  if (absl::StatusCode code = response->status_code();
+      code != absl::StatusCode::kOk) {
+    std::string message =
+        absl::StrCat("GetInitialDataRequest failed with code: ", code);
+    QUICHE_LOG(WARNING) << message;
+    return absl::InvalidArgumentError(message);
+  }
+  // Parse GetInitialDataResponse.
+  GetInitialDataResponse initial_data_response;
+  if (!initial_data_response.ParseFromString(response->body())) {
+    QUICHE_LOG(WARNING) << "Failed to parse GetInitialDataResponse";
+    return absl::InternalError("Failed to parse GetInitialDataResponse");
+  }
+  return initial_data_response;
+}
+
+absl::StatusOr<BlindSignAuth::PrivacyPassContext>
+BlindSignAuth::CreatePrivacyPassContext(
+    const privacy::ppn::GetInitialDataResponse& initial_data_response) {
+  RSAPublicKey public_key_proto;
+  if (!public_key_proto.ParseFromString(
+          initial_data_response.at_public_metadata_public_key()
+              .serialized_public_key())) {
+    return absl::InvalidArgumentError(
+        "Failed to parse Privacy Pass public key");
+  }
+  absl::StatusOr<bssl::UniquePtr<RSA>> bssl_rsa_key =
+      CreatePublicKeyRSA(public_key_proto.n(), public_key_proto.e());
+  if (!bssl_rsa_key.ok()) {
+    return absl::InternalError(absl::StrCat("Failed to create RSA public key: ",
+                                            bssl_rsa_key.status().ToString()));
+  }
+
+  PrivacyPassContext context;
+  context.rsa_public_key = *std::move(bssl_rsa_key);
+  context.key_version =
+      initial_data_response.at_public_metadata_public_key().key_version();
+  context.token_key_id =
+      initial_data_response.privacy_pass_data().token_key_id();
+  context.public_metadata_extensions_str =
+      initial_data_response.privacy_pass_data().public_metadata_extensions();
+
+  absl::StatusOr<Extensions> extensions =
+      DecodeExtensions(context.public_metadata_extensions_str);
+  if (!extensions.ok()) {
+    return absl::InvalidArgumentError(absl::StrCat(
+        "Failed to decode extensions: ", extensions.status().ToString()));
+  }
+
+  if (absl::Status validation_result = ValidateExtensionsOrderAndValues(
+          *extensions, absl::MakeSpan(kExpectedExtensionTypes), absl::Now());
+      validation_result.ok()) {
+    context.extensions = *std::move(extensions);
+  } else {
+    return absl::InvalidArgumentError(absl::StrCat(
+        "Failed to validate extensions: ", validation_result.ToString()));
+  }
+
+  if (absl::StatusOr<ExpirationTimestamp> expiration_timestamp =
+          ExpirationTimestamp::FromExtension(
+              context.extensions.extensions.at(0));
+      expiration_timestamp.ok()) {
+    context.public_metadata_expiry_time =
+        absl::FromUnixSeconds(expiration_timestamp->timestamp);
+  } else {
+    return absl::InvalidArgumentError(
+        absl::StrCat("Failed to parse expiration timestamp: ",
+                     expiration_timestamp.status().ToString()));
+  }
+
+  if (absl::StatusOr<GeoHint> geo_hint =
+          GeoHint::FromExtension(context.extensions.extensions.at(1));
+      geo_hint.ok()) {
+    context.geo_hint = *std::move(geo_hint);
+  } else {
+    return absl::InvalidArgumentError(absl::StrCat(
+        "Failed to parse geo hint: ", geo_hint.status().ToString()));
+  }
+
+  if (absl::StatusOr<AnonymousTokensUseCase> use_case = ParseUseCase(
+          initial_data_response.at_public_metadata_public_key().use_case());
+      use_case.ok()) {
+    context.use_case = *std::move(use_case);
+  } else {
+    return absl::InvalidArgumentError(absl::StrCat(
+        "Failed to parse use case: ", use_case.status().ToString()));
+  }
+
+  return context;
+}
+
+absl::StatusOr<BlindSignAuth::GeneratedTokenRequests>
+BlindSignAuth::GenerateBlindedTokenRequests(
+    int num_tokens, const RSA& rsa_public_key,
+    absl::string_view token_challenge_str, absl::string_view token_key_id,
+    const anonymous_tokens::Extensions& extensions) {
+  GeneratedTokenRequests result;
+  result.privacy_pass_clients.reserve(num_tokens);
+  result.privacy_pass_blinded_tokens_b64.reserve(num_tokens);
+  QuicheRandom* random = QuicheRandom::GetInstance();
+
+  for (int i = 0; i < num_tokens; i++) {
+    absl::StatusOr<std::unique_ptr<PrivacyPassRsaBssaPublicMetadataClient>>
+        client = PrivacyPassRsaBssaPublicMetadataClient::Create(rsa_public_key);
+    if (!client.ok()) {
+      return absl::InternalError(
+          absl::StrCat("Failed to create Privacy Pass client: ",
+                       client.status().ToString()));
+    }
+
+    std::string nonce_rand(32, '\0');
+    random->RandBytes(nonce_rand.data(), nonce_rand.size());
+
+    absl::StatusOr<ExtendedTokenRequest> extended_token_request =
+        (*client)->CreateTokenRequest(token_challenge_str, nonce_rand,
+                                      token_key_id, extensions);
+    if (!extended_token_request.ok()) {
+      return absl::InternalError(
+          absl::StrCat("Failed to create ExtendedTokenRequest: ",
+                       extended_token_request.status().ToString()));
+    }
+    result.privacy_pass_clients.push_back(*std::move(client));
+    result.privacy_pass_blinded_tokens_b64.push_back(absl::Base64Escape(
+        extended_token_request->request.blinded_token_request));
+  }
+  return result;
+}
+
+privacy::ppn::ProxyLayer BlindSignAuth::QuicheProxyLayerToPpnProxyLayer(
+    quiche::ProxyLayer proxy_layer) {
+  switch (proxy_layer) {
+    case ProxyLayer::kProxyA: {
+      return privacy::ppn::ProxyLayer::PROXY_A;
+    }
+    case ProxyLayer::kProxyB: {
+      return privacy::ppn::ProxyLayer::PROXY_B;
+    }
+    case ProxyLayer::kTerminalLayer: {
+      return privacy::ppn::ProxyLayer::TERMINAL_LAYER;
+    }
+  }
+}
+
 std::string BlindSignAuth::ConvertBase64ToWebSafeBase64(
     std::string base64_string) {
   absl::c_replace(base64_string, /*old_value=*/'+', /*new_value=*/'-');
diff --git a/quiche/blind_sign_auth/blind_sign_auth.h b/quiche/blind_sign_auth/blind_sign_auth.h
index ccc3118..7ff742c 100644
--- a/quiche/blind_sign_auth/blind_sign_auth.h
+++ b/quiche/blind_sign_auth/blind_sign_auth.h
@@ -62,25 +62,57 @@
                      SignedTokenCallback callback) override;
 
  private:
+  struct PrivacyPassContext {
+    bssl::UniquePtr<RSA> rsa_public_key;
+    anonymous_tokens::Extensions extensions;
+    absl::Time public_metadata_expiry_time;
+    anonymous_tokens::GeoHint geo_hint;
+    anonymous_tokens::AnonymousTokensUseCase use_case;
+    std::string token_key_id;
+    uint32_t key_version = 0;
+    std::string public_metadata_extensions_str;
+  };
+
+  struct GeneratedTokenRequests {
+    std::vector<std::unique_ptr<anonymous_tokens::
+                                    PrivacyPassRsaBssaPublicMetadataClient>>
+        privacy_pass_clients;
+    std::vector<std::string> privacy_pass_blinded_tokens_b64;
+  };
+
+  // Helper functions for GetTokens flow without device attestation.
   void GetInitialDataCallback(
       std::optional<std::string> oauth_token, int num_tokens,
       ProxyLayer proxy_layer, BlindSignAuthServiceType service_type,
       SignedTokenCallback callback,
       absl::StatusOr<BlindSignMessageResponse> response);
+
   void GeneratePrivacyPassTokens(
       privacy::ppn::GetInitialDataResponse initial_data_response,
       std::optional<std::string> oauth_token, int num_tokens,
       ProxyLayer proxy_layer, BlindSignAuthServiceType service_type,
       SignedTokenCallback callback);
+
   void PrivacyPassAuthAndSignCallback(
-      std::string encoded_extensions, absl::Time public_key_expiry_time,
-      anonymous_tokens::GeoHint geo_hint,
-      anonymous_tokens::AnonymousTokensUseCase use_case,
+      const PrivacyPassContext& pp_context,
       std::vector<std::unique_ptr<anonymous_tokens::
                                       PrivacyPassRsaBssaPublicMetadataClient>>
           privacy_pass_clients,
       SignedTokenCallback callback,
       absl::StatusOr<BlindSignMessageResponse> response);
+
+  absl::StatusOr<privacy::ppn::GetInitialDataResponse>
+  ParseGetInitialDataResponseMessage(
+      const absl::StatusOr<BlindSignMessageResponse>& response_statusor);
+
+  absl::StatusOr<PrivacyPassContext> CreatePrivacyPassContext(
+      const privacy::ppn::GetInitialDataResponse& initial_data_response);
+
+  absl::StatusOr<GeneratedTokenRequests> GenerateBlindedTokenRequests(
+      int num_tokens, const RSA& rsa_public_key,
+      absl::string_view token_challenge_str, absl::string_view token_key_id,
+      const anonymous_tokens::Extensions& extensions);
+
   privacy::ppn::ProxyLayer QuicheProxyLayerToPpnProxyLayer(
       quiche::ProxyLayer proxy_layer);
   // Replaces '+' and '/' with '-' and '_' in a Base64 string.