// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

library fuchsia.identity.account;

using fuchsia.auth;
using fuchsia.identity.keys;
using fuchsia.sys;

/// A protocol to receive events when the authentication state of an account
/// changes.
///
/// AuthListeners may be registered through the `AuthTarget` protocol and this
/// registration also defines the types of authentication state changes that
/// should be sent to the listener.
///
/// All methods include an empty response to follow the "Throttle push using
/// acknowledgements" FIDL design pattern.
protocol AuthListener {
    /// A method that is called when the AccountListener is first connected.
    OnInitialize(AuthState auth_state) -> ();

    /// A method that is called when the authentication state of the account
    /// changes.
    OnAuthStateChanged(AuthState auth_state) -> ();
};

/// A protocol that is extended by other protocols defining an entity
/// (referred to as the "target") with an authentication state, such as a
/// Fuchsia account or persona.
///
/// AuthTarget defines a set of methods to monitor the current authentication
/// state of an entity and to request changes in that authentication state.
[FragileBase]
protocol AuthTarget {
    /// Returns the current `AuthState` of the target.
    ///
    /// `scenario` The scenario to produce the authentication state for.
    ///
    /// Returns: `auth_state` The target's current authentication state.
    GetAuthState(Scenario scenario) -> (AuthState auth_state) error Error;

    /// Connects a channel that will receive changes in the authentication
    /// state of the target.
    ///
    /// `listener` The client end of an `AuthListener` channel
    /// `initial_state` If true, the listener will receive the initial auth
    ///                 state in addition to any changes.
    /// `granularity` An `AuthChangeGranularity` expressing the magnitude of
    ///               change in authentication state than should lead to a
    ///               callback
    RegisterAuthListener(
        Scenario scenario,
        AuthListener listener,
        bool initial_state,
        AuthChangeGranularity granularity)
        -> () error Error;

    // TODO(AUTH-220): Add methods that request in increase in the authentication
    //                 state or authentication for a particular event.
};

/// A protocol that exposes information about the personae and recovery account
/// for a Fuchsia account and provides methods to manipulate these.
///
/// An Account provides access to sensitive long term identifiers and is only
/// intended only for use by a small number of trusted system components.
protocol Account {
    compose AuthTarget;

    // Note: a LocalAccountID accessor method may be added if and when the
    // first valid use case arrives.

    /// Returns a human readable name for the account. Account names are set by
    /// a human and are not guaranteed to be meaningful or unique, even among
    /// the accounts on a single device.
    GetAccountName() -> (string:MAX_NAME_SIZE name);

    /// Returns the account's lifetime.
    GetLifetime() -> (Lifetime lifetime);

    /// Returns a vector of all the personae defined for the account.
    /// NOTE: Currently all Fuchsia accounts have exactly one persona.
    GetPersonaIds() -> (vector<LocalPersonaId>:MAX_PERSONAE_PER_ACCOUNT persona_ids);

    /// Connects a channel to read properties of and access tokens for
    /// the default persona for the account.
    ///
    /// `persona` The client end of a `Persona` channel
    ///
    /// Returns: `id` The identifier for the default persona
    GetDefaultPersona(request<Persona> persona)
        -> (LocalPersonaId id) error Error;

    /// Connects a channel to read properties of and access tokens for
    /// one of the personae for the account.
    ///
    /// `id` The persona's identifier as returned by GetPersonaIds()
    /// `persona` The client end of a `Persona` channel
    GetPersona(LocalPersonaId id, request<Persona> persona) -> () error Error;

    // TODO(AUTH-221): Add methods to create, delete, and manage personae.

    /// Returns the service provider account that can be used to access the
    /// Fuchsia account if more direct methods of authentication are not
    /// available, provided such an account exists.
    ///
    /// Returns: The `ServiceProviderAccount` used for recovery if one exists
    GetRecoveryAccount()
        -> (fuchsia.auth.ServiceProviderAccount? account) error Error;

    /// Sets the service provider account that can be used to access the Fuchsia
    /// account if more direct methods of authentication are not available.
    ///
    /// `account` The `ServiceProviderAccount` to use as the recovery account.
    ///           This must be an existing account that has already been
    ///           provisioned on the current device using TokenManager.
    SetRecoveryAccount(fuchsia.auth.ServiceProviderAccount account)
        -> () error Error;
};

/// A protocol that exposes basic information about a Fuchsia persona and access
/// to the authentication tokens that are visible through it.
///
/// Note a Persona purposefully does not provide access to a long term
/// identifier for the persona. This is to support components in the system that
/// work with short lived identifiers (e.g. SessionManager), but note that long
/// term identifiers can usually still be derived via the TokenManger protocol.
protocol Persona {
    compose AuthTarget;

    /// Returns the lifetime of this persona.
    GetLifetime() -> (Lifetime lifetime);

    /// Connects a channel to acquire and revoke authentication tokens for
    /// service provider (aka cloud service) accounts that are visible through
    /// this persona.
    ///
    /// `application_url` A url for the Fuchsia agent that this channel will be
    ///                   used by. Applications are only allowed to access
    ///                   tokens that they created.
    /// `token_manager` The client end of a `TokenManager` channel
    GetTokenManager(
        // TODO(AUTH-218): Migrate token manager to a more appropriate form
        // of software identity. This is likely to be some verifiable
        // representation of the organization that wrote the software, such as
        // a URL domain.
        fuchsia.sys.component_url application_url,
        request<fuchsia.auth.TokenManager> token_manager)
        -> () error Error;

    /// Connects a channel to access and manage key material that is consistent
    /// across all devices with access to this persona.
    ///
    /// Persona key storage is a very limited resource. Only a small number of
    /// core components should use KeyManager, often in order to supply more
    /// scalable forms of synchronization to other applications (e.g. Ledger).
    ///
    /// `application_url` A url for the component that this channel will be
    ///                   used by. Applications are only allowed to access
    ///                   their own keys.
    /// `key_manager` The client end of a `KeyManager` channel
    GetKeyManager(
        // TODO(AUTH-218): Migrate key manager to a more appropriate form
        // of software identity. This might be a set of whitelisted URLs or a
        // simple enum.
        fuchsia.sys.component_url application_url,
        request<fuchsia.identity.keys.KeyManager> key_manager)
        -> () error Error;
};
