Class PasswordAuthentication
Authenticator plugin based on a username and password.
public class PasswordAuthentication : IAuthentication
- Inheritance
-
PasswordAuthentication
- Implements
- Inherited Members
Remarks
Sessions are established in two steps. The server stores a salt and a hash derived from the password, and:
- challenges the client with the hash's key derivation, the salt and a random nonce;
- accepts an answer that is an HMAC of the challenge keyed by the hash, which the client derives from the password;
- returns the session key encrypted with the hash. The hash itself is never sent, but anyone who sees an answer or a handshake can test password guesses against it offline. A client answering a challenge for a HASH_KEY also sends a HASH2_KEY for the same password, sealed with the old hash, which replaces it.
Fields
DIFFICULTY
public const int DIFFICULTY = 10000
Field Value
DIFFICULTY2
public const int DIFFICULTY2 = 600000
Field Value
HASH2_KEY
public const string HASH2_KEY = "pbkdf.hash2"
Field Value
HASH_KEY
public const string HASH_KEY = "pbkdf.hash"
Field Value
REALM_KEY
public const string REALM_KEY = "pbkdf"
Field Value
SALT_BYTES
public const int SALT_BYTES = 32
Field Value
SALT_KEY
public const string SALT_KEY = "pbkdf.salt"
Field Value
TEMP_HASH_KEY
public const string TEMP_HASH_KEY = "pbkdf.temp-hash"
Field Value
Properties
AccountFailureRateLimit
How many wrong answers to session challenges each account may give, counted separately on each server; once exhausted, even a correct answer is refused until the budget refills.
public RateLimit AccountFailureRateLimit { get; init; }
Property Value
AllowAutomaticLogin
Whether to allow the user to automatically log in with saved credentials. Requires AllowSavedCredentials=true.
public bool AllowAutomaticLogin { get; set; }
Property Value
AllowChangePassword
Whether to generate a "Change password" menu command.
public bool AllowChangePassword { get; set; }
Property Value
AllowSavedCredentials
Whether to allow the user to save credentials so that they don't have to enter them manually every time.
public bool AllowSavedCredentials { get; set; }
Property Value
CanEncrypt
true if the authenticator supports secured key exchange
public bool CanEncrypt { get; }
Property Value
Remarks
this is used to establish shared secrets. implementations could be based on public key cryptography, diffie-helmann, or out of band methods
CanLookup
true if the authenticator supports looking up an IUserAccount for an authenticator-specific username
public bool CanLookup { get; }
Property Value
IsAuthoritative
If true, the returned identity should be accepted without server verification
public bool IsAuthoritative { get; }
Property Value
Remarks
May depend on ambient state - don't cache the result. As well as enabling automatic login, this is used by SecurityService to decide whether it's ok to perform purely-local authentication without calling IEntityStore.Connect.
PasswordRules
Includes a default password rule requiring a minimum password strength of Strong.
public List<IPasswordRule> PasswordRules { get; init; }
Property Value
Realm
Describes identities within the purview of this authenticator
public string Realm { get; }
Property Value
RequiresCredentials
Expects non-empty Credentials in order to perform client-side identity operations
public bool RequiresCredentials { get; }
Property Value
UsernameProvider
If not null, causes UseIntegratedLogin to use PasswordOnlyLoginHandler, which will obtain a username from this function.
public Func<string>? UsernameProvider { get; set; }
Property Value
Methods
AnswerSessionChallengeAsync(IAlgorithmProvider, Credentials, byte[])
Answer a challenge issued by CreateSessionChallengeAsync(IEntityContext, Identity), using the supplied credentials.
public Task<AuthenticationResult<byte[]>> AnswerSessionChallengeAsync(IAlgorithmProvider algorithmProvider, Credentials credentials, byte[] challenge)
Parameters
algorithmProviderIAlgorithmProvidercredentialsCredentialschallengebyte[]
Returns
ChangeCurrentUserPasswordAsync(IServices, ChangePasswordParameters)
public static Task ChangeCurrentUserPasswordAsync(IServices services, ChangePasswordParameters parameters)
Parameters
servicesIServicesparametersChangePasswordParameters
Returns
ChangeUserTemporaryPasswordAsync(IServices, ChangePasswordParameters)
Replace a temporary password, connecting with it to a session that may do nothing else.
public static Task ChangeUserTemporaryPasswordAsync(IServices services, ChangePasswordParameters parameters)
Parameters
servicesIServicesparametersChangePasswordParameters
Returns
CreateHash(string)
Create a salt and a Pbkdf2Sha1 hash, as stored in HASH_KEY and TEMP_HASH_KEY.
public static (string salt, string hash) CreateHash(string password)
Parameters
passwordstring
Returns
CreateHash(string, string)
Create a Pbkdf2Sha1 hash, as stored in HASH_KEY and TEMP_HASH_KEY.
public static string CreateHash(string password, string salt)
Parameters
Returns
CreateHash(Credentials)
public AuthenticationResult<(string salt, string hash)> CreateHash(Credentials credentials)
Parameters
credentialsCredentials
Returns
CreateHash2(string)
Create a salt and a Pbkdf2Sha256 hash, as stored in HASH2_KEY.
public static (string salt, string hash) CreateHash2(string password)
Parameters
passwordstring
Returns
CreateHash2(string, string)
Create a Pbkdf2Sha256 hash, as stored in HASH2_KEY.
public static string CreateHash2(string password, string salt)
Parameters
Returns
CreateSessionChallengeAsync(IEntityContext, Identity)
Issue a challenge which the client must answer before a session is prepared for the subject, or null if the session needs no answer.
public Task<AuthenticationResult<byte[]?>> CreateSessionChallengeAsync(IEntityContext context, Identity subject)
Parameters
contextIEntityContextsubjectIdentity
Returns
CreateTemporaryPassword()
Generate a random password for an administrator to give to a user, who must replace it when they first log in.
public static string CreateTemporaryPassword()
Returns
DecryptDataAsync(IAlgorithmProvider, Credentials, byte[])
decrypt a message addressed to the supplied credentials
public Task<AuthenticationResult<byte[]>> DecryptDataAsync(IAlgorithmProvider algorithmProvider, Credentials credentials, byte[] packet)
Parameters
algorithmProviderIAlgorithmProvidercredentialsCredentialspacketbyte[]
Returns
- Task<AuthenticationResult<byte[]>>
(decrypted message/null, null/reason for failure)
EncryptDataAsync(IAlgorithmProvider, object?, byte[])
create an encrypted message which can only be decrypted by the specified subject (which will be an account username if CanLookup)
public Task<AuthenticationResult<byte[]>> EncryptDataAsync(IAlgorithmProvider algorithmProvider, object? state, byte[] data)
Parameters
algorithmProviderIAlgorithmProviderstateobjectdatabyte[]
Returns
- Task<AuthenticationResult<byte[]>>
encrypted message
GetCurrentUsernameAndHashAsync(IServices)
Read the current user's password username, hash and salt; the hash is the HASH2_KEY if the account has one, else the HASH_KEY.
public static Task<(string username, string hash, string salt)> GetCurrentUsernameAndHashAsync(IServices services)
Parameters
servicesIServices
Returns
GetIdentity(Credentials)
Extract a subject from the environment or the supplied credentials.
public AuthenticationResult<string> GetIdentity(Credentials credentials)
Parameters
credentialsCredentials
Returns
- AuthenticationResult<string>
subject name, unverified - from local knowledge only
HashesEqual(string, string)
Compare two hashes produced by CreateHash(string, string) or CreateHash2(string, string) in time independent of their contents.
public static bool HashesEqual(string first, string second)
Parameters
Returns
IsPasswordClaim(string)
True for the claims that hold password material, as opposed to the username claim REALM_KEY.
public static bool IsPasswordClaim(string key)
Parameters
keystring
Returns
LookupAccount(IEntityContext, string)
public AuthenticationResult<string> LookupAccount(IEntityContext context, string subject)
Parameters
contextIEntityContextsubjectstring
Returns
LookupAccountAsync(IEntityContext, string)
Find the username of an IUserAccount for a username produced by this authenticator.
public Task<AuthenticationResult<string>> LookupAccountAsync(IEntityContext context, string subject)
Parameters
contextIEntityContextsubjectstring
Returns
PrepareSessionAsync(IEntityContext, Identity, byte[]?, byte[]?)
Prepare an encrypted session with the specified subject by looking up their account and retrieving authentication state.
public Task<AuthenticationResult<Handshake<object?>>> PrepareSessionAsync(IEntityContext context, Identity subject, byte[]? challenge, byte[]? answer)
Parameters
contextIEntityContextsubjectIdentityThe identity for which to prepare a session.
challengebyte[]The challenge issued by CreateSessionChallengeAsync(IEntityContext, Identity), if any.
answerbyte[]The client's answer to the challenge, if any.
Returns
- Task<AuthenticationResult<Handshake<object>>>
A handshake containing the session type and associated state for use in subsequent encryption operations.
RemoveUsernameAndPasswordAsync(IUserAccount, CancellationToken?)
public static Task RemoveUsernameAndPasswordAsync(IUserAccount account, CancellationToken? cancellationToken = null)
Parameters
accountIUserAccountcancellationTokenCancellationToken?
Returns
SetUsernameAndPasswordAsync(IUserAccount, string, string, bool, CancellationToken?)
public static Task SetUsernameAndPasswordAsync(IUserAccount account, string username, string password, bool forcePasswordChange = false, CancellationToken? cancellationToken = null)
Parameters
accountIUserAccountusernamestringpasswordstringforcePasswordChangeboolcancellationTokenCancellationToken?
Returns
ValidatePassword(string)
public string? ValidatePassword(string password)
Parameters
passwordstring
Returns
VerifyIdentity(Credentials, string)
Verify that the subject matches the supplied credentials. Available synchronously only if IsAuthoritative returns true.
public AuthenticationResult VerifyIdentity(Credentials credentials, string subject)
Parameters
credentialsCredentialssubjectstring
Returns
- AuthenticationResult
(true/false for authentication state, null/reason for failure)
VerifyIdentityAsync(Credentials, IEntityContext, string)
verify that the subject matches the supplied credentials
public Task<AuthenticationResult> VerifyIdentityAsync(Credentials credentials, IEntityContext context, string subject)
Parameters
credentialsCredentialscontextIEntityContextsubjectstring
Returns
- Task<AuthenticationResult>
(true/false for authentication state, null/reason for failure)