Table of Contents

Class PasswordAuthentication

Namespace
The.Security.Password
Assembly
Instagile.dll

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

int

DIFFICULTY2

public const int DIFFICULTY2 = 600000

Field Value

int

HASH2_KEY

public const string HASH2_KEY = "pbkdf.hash2"

Field Value

string

HASH_KEY

public const string HASH_KEY = "pbkdf.hash"

Field Value

string

REALM_KEY

public const string REALM_KEY = "pbkdf"

Field Value

string

SALT_BYTES

public const int SALT_BYTES = 32

Field Value

int

SALT_KEY

public const string SALT_KEY = "pbkdf.salt"

Field Value

string

TEMP_HASH_KEY

public const string TEMP_HASH_KEY = "pbkdf.temp-hash"

Field Value

string

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

RateLimit

AllowAutomaticLogin

Whether to allow the user to automatically log in with saved credentials. Requires AllowSavedCredentials=true.

public bool AllowAutomaticLogin { get; set; }

Property Value

bool

AllowChangePassword

Whether to generate a "Change password" menu command.

public bool AllowChangePassword { get; set; }

Property Value

bool

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

bool

CanEncrypt

true if the authenticator supports secured key exchange

public bool CanEncrypt { get; }

Property Value

bool

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

bool

IsAuthoritative

If true, the returned identity should be accepted without server verification

public bool IsAuthoritative { get; }

Property Value

bool

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

List<IPasswordRule>

Realm

Describes identities within the purview of this authenticator

public string Realm { get; }

Property Value

string

RequiresCredentials

Expects non-empty Credentials in order to perform client-side identity operations

public bool RequiresCredentials { get; }

Property Value

bool

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

Func<string>

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

algorithmProvider IAlgorithmProvider
credentials Credentials
challenge byte[]

Returns

Task<AuthenticationResult<byte[]>>

ChangeCurrentUserPasswordAsync(IServices, ChangePasswordParameters)

public static Task ChangeCurrentUserPasswordAsync(IServices services, ChangePasswordParameters parameters)

Parameters

services IServices
parameters ChangePasswordParameters

Returns

Task

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

services IServices
parameters ChangePasswordParameters

Returns

Task

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

password string

Returns

(string salt, string hash)

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

password string
salt string

Returns

string

CreateHash(Credentials)

public AuthenticationResult<(string salt, string hash)> CreateHash(Credentials credentials)

Parameters

credentials Credentials

Returns

AuthenticationResult<(string salt, string hash)>

CreateHash2(string)

Create a salt and a Pbkdf2Sha256 hash, as stored in HASH2_KEY.

public static (string salt, string hash) CreateHash2(string password)

Parameters

password string

Returns

(string salt, string hash)

CreateHash2(string, string)

Create a Pbkdf2Sha256 hash, as stored in HASH2_KEY.

public static string CreateHash2(string password, string salt)

Parameters

password string
salt string

Returns

string

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

context IEntityContext
subject Identity

Returns

Task<AuthenticationResult<byte[]>>

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

string

DecryptDataAsync(IAlgorithmProvider, Credentials, byte[])

decrypt a message addressed to the supplied credentials

public Task<AuthenticationResult<byte[]>> DecryptDataAsync(IAlgorithmProvider algorithmProvider, Credentials credentials, byte[] packet)

Parameters

algorithmProvider IAlgorithmProvider
credentials Credentials
packet byte[]

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

algorithmProvider IAlgorithmProvider
state object
data byte[]

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

services IServices

Returns

Task<(string username, string hash, string salt)>

GetIdentity(Credentials)

Extract a subject from the environment or the supplied credentials.

public AuthenticationResult<string> GetIdentity(Credentials credentials)

Parameters

credentials Credentials

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

first string
second string

Returns

bool

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

key string

Returns

bool

LookupAccount(IEntityContext, string)

public AuthenticationResult<string> LookupAccount(IEntityContext context, string subject)

Parameters

context IEntityContext
subject string

Returns

AuthenticationResult<string>

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

context IEntityContext
subject string

Returns

Task<AuthenticationResult<string>>

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

context IEntityContext
subject Identity

The identity for which to prepare a session.

challenge byte[]

The challenge issued by CreateSessionChallengeAsync(IEntityContext, Identity), if any.

answer byte[]

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

account IUserAccount
cancellationToken CancellationToken?

Returns

Task

SetUsernameAndPasswordAsync(IUserAccount, string, string, bool, CancellationToken?)

public static Task SetUsernameAndPasswordAsync(IUserAccount account, string username, string password, bool forcePasswordChange = false, CancellationToken? cancellationToken = null)

Parameters

account IUserAccount
username string
password string
forcePasswordChange bool
cancellationToken CancellationToken?

Returns

Task

ValidatePassword(string)

public string? ValidatePassword(string password)

Parameters

password string

Returns

string

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

credentials Credentials
subject string

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

credentials Credentials
context IEntityContext
subject string

Returns

Task<AuthenticationResult>

(true/false for authentication state, null/reason for failure)