chromium/chromeos/ash/components/osauth/public/auth_session_storage.h

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

#ifndef CHROMEOS_ASH_COMPONENTS_OSAUTH_PUBLIC_AUTH_SESSION_STORAGE_H_
#define CHROMEOS_ASH_COMPONENTS_OSAUTH_PUBLIC_AUTH_SESSION_STORAGE_H_

#include <memory>
#include <optional>

#include "base/component_export.h"
#include "base/functional/callback.h"
#include "chromeos/ash/components/osauth/public/auth_parts.h"
#include "chromeos/ash/components/osauth/public/common_types.h"

namespace base {

class Location;

}  // namespace base

namespace ash {

class UserContext;

class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_OSAUTH) ScopedSessionRefresher {
 public:
  ScopedSessionRefresher(const ScopedSessionRefresher&) = delete;
  ScopedSessionRefresher& operator=(const ScopedSessionRefresher&) = delete;
  virtual ~ScopedSessionRefresher() = default;

 protected:
  ScopedSessionRefresher() = default;
};

// Helper class that stores and manages lifetime of authenticated UserContext.
// Main use cases for this class are the situations where authenticated
// operations do not happen immediately after authentication, but require some
// user input, e.g. setting up additional factors during user onboarding on a
// first run, or entering authentication-related section of
// `chrome://os-settings`.
//
// When context is added to storage, storage would return a token as a
// replacement, this token can be relatively safely be passed between components
// as it does not contain any sensitive information.
//
// UserContext can be borrowed to perform authenticated operations and should be
// returned to storage as soon as operation completes.
class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_OSAUTH) AuthSessionStorage {
 public:
  using InvalidationCallback = base::OnceCallback<void(void)>;

  // TODO (b/271249180): Define an observer for notifications about token
  // expiration/borrowing.

  // Convenience method.
  static inline AuthSessionStorage* Get() {
    return AuthParts::Get()->GetAuthSessionStorage();
  }

  virtual ~AuthSessionStorage() = default;

  // Gets the ownership of (authenticated) context, and returns an
  // authentication proof token that can be safely passed around between
  // components. Storage manages the lifetime of the context (and
  // underlying cyrptohome authsession).
  virtual AuthProofToken Store(std::unique_ptr<UserContext> context) = 0;
  // Checks if given token is valid (exists and has not expired).
  virtual bool IsValid(const AuthProofToken& token) = 0;

  virtual std::unique_ptr<UserContext> BorrowForTests(
      const base::Location& location,
      const AuthProofToken& token) = 0;

  // Borrows UserContext to perform some authenticated operation. Borrowing
  // a context does not make it invalid.
  // If context is borrowed at the moment of the call, the callback
  // would be called once the context is returned to the storage.
  // Note that callback might be called with `null` value, if
  // the context would become invalid before it is returned.
  virtual void BorrowAsync(const base::Location& location,
                           const AuthProofToken& token,
                           BorrowContextCallback callback) = 0;

  // Allows client to obtain UserContext without intent to return it back.
  // Takes precedence over Borrow requests, but not over invalidate
  // request.
  // Withdrawing context from the storage makes associated token invalid.
  //
  // If context is borrowed at the moment of the call, the callback
  // would be called once the context is returned to the storage.
  // Note that callback might be called with `null` value, if
  // the context would become invalid before it is returned.
  //
  // There can be only one Withdraw request at one time, requesting parallel
  // Withdraw request would result in crash.
  virtual void Withdraw(const AuthProofToken& token,
                        BorrowContextCallback callback) = 0;

  // Allows to inspect stored UserContext. The reference is only valid within
  // same UI event, and should not be stored by caller.
  virtual const UserContext* Peek(const AuthProofToken& token) = 0;
  // Return context back to Storage.
  virtual void Return(const AuthProofToken& token,
                      std::unique_ptr<UserContext> context) = 0;

  // Cleans up UserContext and all associated resources (like cryptohome
  // AuthSession) once authentication is no longer needed.
  // In case when context is borrowed at the time of this call,
  // it would be properly invalidated once it is returned.
  virtual void Invalidate(
      const AuthProofToken& token,
      std::optional<InvalidationCallback> on_invalidated) = 0;

  // This method allows caller to make sure that authenticated authsession
  // associated with `token` would not expire by timeout as long as returned
  // object exists. AuthSessionStorage would automatically issue refresh calls
  // at required intervals. Note that this would only happen while Storage
  // actually has a UserContext. If it was borrowed, it's lifetime would be
  // refreshed only upon returning.
  virtual std::unique_ptr<ScopedSessionRefresher> KeepAlive(
      const AuthProofToken& token) = 0;

  // Checks whether there is a keep alive for the given token. Used by tests
  // that verify the usage of ScopedSessionRefresher on certain screens.
  virtual bool CheckHasKeepAliveForTesting(
      const AuthProofToken& token) const = 0;
};

}  // namespace ash

#endif  // CHROMEOS_ASH_COMPONENTS_OSAUTH_PUBLIC_AUTH_SESSION_STORAGE_H_