1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
// 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_FACTOR_ENGINE_H_
#define CHROMEOS_ASH_COMPONENTS_OSAUTH_PUBLIC_AUTH_FACTOR_ENGINE_H_
#include "base/component_export.h"
#include "base/functional/callback.h"
#include "chromeos/ash/components/osauth/public/common_types.h"
#include "components/account_id/account_id.h"
namespace ash {
// Common interface for interaction with implementations of various
// authentication factors during authentication.
// As methods for establishing/editing different factors vary too much,
// factor editing capabilities are not covered by this interface.
//
// The overall interaction between AuthHub and factor engines is:
// * Once AuthHub is initialized (on login screen / inside the session),
// it would attempt to initialize all factor engines (`InitializeCommon`),
// giving them a chance to wait for underlying services to become ready.
// * Once authentication attempt starts (for user/purpose), AuthHub
// invokes `StartAuthFlow` on each factor engine to query if the factor
// is present for the user/purpose. Factors are started in `kDisabled` state
// and would be enabled by AuthHub once all factors are ready.
// * If factor is not present, `StopAuthFlow` would eventually be called on
// corresponding engine to release resources.
// * If factor is present, AuthHub would check if there are any restrictions
// on using this factor, by querying methods like `IsDisabledByPolicy`.
// Once all restrictions are checked, factor might be disabled via calling
// `SetUsageAllowed(kDisabled)` method. Disabled factor should not allow
// any authentication attempts.
// * While authentication is active, factor engine should notify AuthHub
// about any events that might change factor restrictions: policy changes,
// factor lockout, etc.
// Upon notification, AuthHub would query the restriction using corresponding
// methods and might enable/disable factor as a result.
// Factor might also be disabled for other reasons (e.g. parallel
// authentication attempt using another factor, e.g. entering password and
// touching fingerprint sensor at the same time).
// * If there is an authentication attempt while factor is disabled (e.g.
// fingerprint touch is detected while another factor is being checked),
// engine might queue it and run it when factor is enabled again.
// * Engine also notifies AuthHub when authentication attempt is triggered for
// the factor (AuthHub would disable other factors, and wait for attempt
// result), and when the outcome of the attempt is known (success/failure).
// * In case of failure, AuthHub would re-enable all factors, and wait for
// another attempt.
// * In case of success, AuthHub would eventually call `StopAuthFlow` on all
// engines.
// * Engine should not send any updates over FactorEngineObserver after
// receiving `StopAuthFlow`.
// * It is guaranteed that `StopAuthFlow` would be called before another
// `StartAuthFlow`, e.g. when another user pod is selected on the login
// screen.
// * Upon system shutdown, `ShutdownCommon` would be called for all engines,
// allowing engines needs to release global resources. No operations would be
// invoked after `ShutdownCommon` is called.
class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_OSAUTH) AuthFactorEngine {
public:
// Interface for Engine to communicate with AuthHub.
// When notifying methods, engine should identify itself by
// providing `factor` value same as one returned by `GetFactor()`.
class FactorEngineObserver {
public:
virtual ~FactorEngineObserver() = default;
// Notify AuthHub about result of factor presence check.
virtual void OnFactorPresenceChecked(AshAuthFactor factor,
bool factor_present) = 0;
// Notify AuthHub about start of authentication attempt using this factor.
virtual void OnFactorAttempt(AshAuthFactor factor) = 0;
// Notify AuthHub about result of authentication attempt.
virtual void OnFactorAttemptResult(AshAuthFactor factor, bool success) = 0;
// Notify AuthHub about possible changes in various possible restrictions.
virtual void OnPolicyChanged(AshAuthFactor factor) = 0;
virtual void OnLockoutChanged(AshAuthFactor factor) = 0;
virtual void OnFactorSpecificRestrictionsChanged(AshAuthFactor factor) = 0;
// Notify AuthHub about some critical error. AuthHub would treat
// this factor as disabled.
virtual void OnCriticalError(AshAuthFactor factor) = 0;
// A way for the engine to send an extra signal to UI that is not
// covered by AuthFactorState. For example, unlocking via nearby
// paired smartphone might use this to signal that UI showing
// phone state might need to be updated.
virtual void OnFactorCustomSignal(AshAuthFactor factor) = 0;
};
// Defines how engine should react to authentication attempts.
enum class UsageAllowed {
kEnabled, // Allow authentication attempts;
kDisabledParallelAttempt, // Enqueue or discard authentication attempt;
kDisabled, // Discard authentication attempts.
};
using CleanupCallback = base::OnceCallback<void(AshAuthFactor)>;
using CommonInitCallback = base::OnceCallback<void(AshAuthFactor)>;
using ShutdownCallback = base::OnceCallback<void(AshAuthFactor)>;
virtual ~AuthFactorEngine() = default;
virtual AshAuthFactor GetFactor() const = 0;
// Factor initialization stage that is not dependent on particular user.
// E.g. awaiting the required DBus service to start.
virtual void InitializeCommon(CommonInitCallback callback) = 0;
virtual void ShutdownCommon(ShutdownCallback callback) = 0;
// Initialization for particular user/purpose.
// It is expected that FactorEngine would start a check if the
// factor is configured for user/purpose, and would notify `observer`
// by calling either `OnFactorPresenceChecked` or `OnCriticalError`.
// After that, engine would notify `observer` upon authentication
// attempts using the factor, changes in affecting policies or
// other restrictions.
// It is guaranteed that only one user authentication attempt
// would be running at time.
virtual void StartAuthFlow(const AccountId& account,
AuthPurpose purpose,
FactorEngineObserver* observer) = 0;
// The way for the owning object to change the object that would
// be notified about engine events.
// All events after this call should be sent using new `observer`.
virtual void UpdateObserver(FactorEngineObserver* observer) = 0;
// Engine tears down any internal/external state that needs
// access of allocated resources, such as UserContext, after authentication
// and before shutdown. Typically, cryptohome based Engine should
// use this function to call TerminateAuthFactor.
virtual void CleanUp(CleanupCallback callback) = 0;
// After this call Engine should stop notifying an `observer` set in
// `StartAttempt`, and release any resources allocated as a result of
// starting attempt. Engine should not assume UserContext is available
// in this function.
virtual void StopAuthFlow(ShutdownCallback callback) = 0;
// Client should call this method only when `OnFactorAttemptResult`
// returned `true`.
// This method should store all data related to authentication
// to the `AuthSessionStorage` and return resulting AuthProofToken.
virtual AuthProofToken StoreAuthenticationContext() = 0;
// Used by AuthHub to control if authentication attempts can be performed
// by the engine. Most relevant for factors like fingerprint that can not
// be disabled at UI level.
// If `kDisabledParallelAttempt`, engine should not send `OnAuthAttempt`
// events to observer, but it may queue them and post them as separate
// event once engine returns to `kEnabled`.
// If usage is `kDisabled`, then attempts should be ignored.
virtual void SetUsageAllowed(UsageAllowed usage) = 0;
// Following group of methods would only be called between `StartAuthFlow`
// and `StopAuthFlow`, and are related to account/purpose used to start
// authentication flow.
// They might be called immediately after `OnFactorPresenceCheck` is
// called on observer, as well as after corresponding `OnNNNChanged`
// observer calls.
virtual bool IsDisabledByPolicy() = 0;
virtual bool IsLockedOut() = 0;
// Relevant for factors like fingerprint, where in some
// device orientations FP sensor can be used unintentionally.
virtual bool IsFactorSpecificRestricted() = 0;
// Engines might override these methods to gracefully handle
// timeout during relevant lifecycle operations.
virtual void InitializationTimedOut() {}
virtual void ShutdownTimedOut() {}
virtual void StartFlowTimedOut() {}
virtual void StopFlowTimedOut() {}
// Called when any engine successfully authenticates an auth factor. Engines
// can override this when they have some action (e.g. removing a lockout) that
// should be carried out upon auth even when doing via another engine.
virtual void OnSuccessfulAuthentiation() {}
};
} // namespace ash
#endif // CHROMEOS_ASH_COMPONENTS_OSAUTH_PUBLIC_AUTH_FACTOR_ENGINE_H_
|