ASP.NET Core Identity has UserManager.SupportsUserLockout()
, which for me is true.
Description:
Gets a flag indicating whether the backing user store supports user lock-outs.
Is it ever possible for the user manager NOT to support lockouts?
Is it ever possible for the user manager NOT to support lockouts?
Yes
Under any of these 2 circumstances:
UserManager<TUser>
is subclassed and the virtual bool SupportsUserLockout
property is overridden and that implementation returns false
.UserManager<TUser>.Store
(your IUserStore<TUser>
implementation) does not implement the optional IUserLockoutStore<TUser>
interface.IUserStore
implementation (and without subclassing UserManager<TUser>
), then your runtime IUserStore<TUser>
will be some subclass of abstract class UserStoreBase<...>
which does implement IUserLockoutStore<TUser>
.
Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserOnlyStore
which inherits the IUserLockoutStore<TUser>
interface implementation.UserManager<TUser>
then you will cannot use a subclass UserStoreBase<>
as the basis for your reimplementation of IUserStore<>
- you'll have to start from scratch, basically.
UserManager
and UserStoreBase<...>
is a bad OOP design because it requires implementations to actively go through a lot of effort to correctly not support something, instead of making everything opt-in.class Derived
that subclasses a parent class Base : ISomeInterface
such that class Derived
no longer implements ISomeInterface
(the best we can do is either abuse implicit conversions to a separate type, or "hide" members with [EditorBrowsable]
and reimplement the interface explicitly with throw new NotSupportedException()
, which is horrible, but even Microsoft does it in some places in .NET's base libraries, such as in Stream
and TextWriter
subclasses).1: By "interface" I don't mean interface
types; I mean the set of public
members of a class
or struct
, i.e. a type's exposed surface.
(In an earlier edit of my post, I suggested that IConfigureOptions<LockoutOptions>
could be used to configure SupportsUserLockout
, however I was wrong: as there is no option to outright disable the lockout system, but if you were to subclass both LockoutOptions
to add a bool Enabled
property and subclass UserManager<TUser>
to specify override bool SupportsUserLockout
to return LockoutOptions.Enabled
(ideally, from an immutable copy, not the original mutable options object) then that would work.