chromium/net/device_bound_sessions/session.h

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

#ifndef NET_DEVICE_BOUND_SESSIONS_SESSION_H_
#define NET_DEVICE_BOUND_SESSIONS_SESSION_H_

#include <memory>
#include <optional>
#include <string>

#include "base/types/strong_alias.h"
#include "components/unexportable_keys/service_error.h"
#include "components/unexportable_keys/unexportable_key_id.h"
#include "net/base/net_export.h"
#include "net/device_bound_sessions/cookie_craving.h"
#include "net/device_bound_sessions/session_inclusion_rules.h"
#include "net/device_bound_sessions/session_params.h"
#include "url/gurl.h"

namespace net {
class URLRequest;
}

namespace net::device_bound_sessions {

namespace proto {
class Session;
}

// This class represents a DBSC (Device Bound Session Credentials) session.
class NET_EXPORT Session {
 public:
  using Id = base::StrongAlias<class IdTag, std::string>;

  ~Session();

  static std::unique_ptr<Session> CreateIfValid(const SessionParams& params,
                                                GURL url);
  static std::unique_ptr<Session> CreateFromProto(const proto::Session& proto);
  proto::Session ToProto() const;

  // this bool could also be an enum for UMA, eventually devtools, etc.
  bool ShouldDeferRequest(URLRequest* request) const;

  const Id& id() const { return id_; }

  const GURL& refresh_url() const { return refresh_url_; }

  bool should_defer_when_expired() const { return should_defer_when_expired_; }

  bool IsEqualForTesting(const Session& other) const;

 private:
  Session(Id id, url::Origin origin, GURL refresh);
  Session(Id id,
          GURL refresh,
          SessionInclusionRules inclusion_rules,
          std::vector<CookieCraving> cookie_cravings,
          bool should_defer_when_expired,
          base::Time expiry_date);
  Session(const Session& other) = delete;
  Session& operator=(const Session& other) = delete;
  Session(Session&& other) = delete;
  Session& operator=(Session&& other) = delete;

  // The unique server-issued identifier of the session.
  const Id id_;
  // The URL to use for refresh requests made on behalf of this session.
  // Note: This probably also needs to store its IsolationInfo, so that the
  // correct IsolationInfo can be used when sending refresh requests.
  // If requests are not deferred when missing a craving, this should still
  // be set as this URL must be able to set all cravings.
  const GURL refresh_url_;
  // Determines which requests are potentially subject to deferral on behalf of
  // this session.
  SessionInclusionRules inclusion_rules_;
  // The set of credentials required by this session. Derived from the
  // "credentials" array in the session config.
  std::vector<CookieCraving> cookie_cravings_;
  // If this session should defer requests when cookies are not present.
  // Default is true, and strongly recommended.
  // If this is false, requests will still be sent when cookies are not present,
  // and will be signed using the cached challenge if present, if not signed
  // using a default value for challenge.
  bool should_defer_when_expired_ = true;
  // Expiry date for session, 400 days from last refresh similar to cookies.
  base::Time expiry_date_;
  // Unexportable key for this session. Once provisioned, this will never
  // change.
  // NOTE: The key may not be available for sometime after a browser restart.
  // This is because the key needs to be restored from a corresponding
  // "wrapped" value that is persisted to disk. This restoration takes time
  // and can be done lazily. The "wrapped" key and the restore process are
  // transparent to this class.
  unexportable_keys::ServiceErrorOr<unexportable_keys::UnexportableKeyId>
      key_id_or_error_ =
          base::unexpected(unexportable_keys::ServiceError::kKeyNotReady);
  // Precached challenge, if any. Should not be persisted.
  std::optional<std::string> cached_challenge_;
};

}  // namespace net::device_bound_sessions

#endif  // NET_DEVICE_BOUND_SESSIONS_SESSION_H_