Skip to content

Exceptions ​

Every exception the package throws is a plain exception carrying no message of its own. A mapper built on IExceptionMapper turns each into a status code, a machine-readable error value, and a message key resolved through Localization.

ExceptionStatuserror
InvalidCredentialsException401invalid_credentials
InvalidSessionException401invalid_session
InvalidTwoFactorCodeException401invalid_two_factor_code
InvalidTwoFactorChallengeException401invalid_two_factor_challenge
AccountDisabledException403account_disabled
InvalidPasswordResetTokenException410invalid_password_reset_token
InvalidEmailVerificationTokenException410invalid_email_verification_token
PasswordMismatchException422password_mismatch
PasswordReusedException422password_reused
UsernameTakenException422username_taken
EmailTakenException422email_taken
AccountLockedException423account_locked_out

TIP

Pass registerExceptionHandler: false to AddAuthCredentials to answer these with a handler of your own. The mapper that produces the statuses above is internal, so a replacement maps these exceptions itself rather than reusing it.

InvalidCredentialsException ​

Thrown for every credential failure: an unknown identifier, a wrong password, or a wrong current password during a password change.

It is deliberately one exception rather than several. Reporting "no such user" separately from "wrong password" tells an attacker which addresses are registered, so do not catch it and re-throw something more specific.

Type signature ​

csharp
public sealed class InvalidCredentialsException : Exception;

AccountLockedException ​

Thrown when the lockout policy has locked the account, on login, on VerifyAsync and the CompleteTwoFactorLoginAsync that calls it, and on session refresh. Carries LockoutEnd, which is passed to the message as {0} so the text can say when to try again.

Only thrown when lockout is enabled.

Type signature ​

csharp
public sealed class AccountLockedException(
    DateTimeOffset lockoutEnd
) : Exception;

AccountDisabledException ​

Thrown when credentials are correct but IsActive is false, and when refreshing a session for a disabled account.

Checked after the password, so it does not confirm an account exists to someone who does not know the password.

Type signature ​

csharp
public sealed class AccountDisabledException : Exception;

InvalidSessionException ​

Thrown when a refresh token matches no usable session, whether it is unknown, expired, revoked, or scoped to a different application, and when the session it names has reached the AbsoluteSessionLifetimeDays ceiling measured from when it was created.

Type signature ​

csharp
public sealed class InvalidSessionException : Exception;

InvalidPasswordResetTokenException ​

Thrown when a reset token is unknown, already used, or expired. 410 rather than 404, because the resource existed and is gone.

Type signature ​

csharp
public sealed class InvalidPasswordResetTokenException : Exception;

InvalidEmailVerificationTokenException ​

Thrown when a verification token is unknown, already spent, expired, issued for the other purpose, or a registration token naming an address the account no longer holds. 410 rather than 404, because the resource existed and is gone.

All five causes answer identically, so the endpoint cannot be used to learn which tokens once existed, which flow one belongs to, or what address the account is on. A token a concurrent request spends first answers as an already spent one, since redemption claims the row with a guarded update rather than on the strength of the read that found it.

Type signature ​

csharp
public sealed class InvalidEmailVerificationTokenException : Exception;

InvalidTwoFactorCodeException ​

Thrown when completing enrolment with a wrong code, when a user with no enrolment at all is asked to verify one, and by CompleteTwoFactorLoginAsync for a code the verification refused, replayed codes and spent recovery codes included. VerifyAsync itself returns false for those rather than throwing.

The challenge is left unspent, so a mistyped code can be corrected without sending the password again.

Type signature ​

csharp
public sealed class InvalidTwoFactorCodeException : Exception;

InvalidTwoFactorChallengeException ​

Thrown by CompleteTwoFactorLoginAsync when the challenge cannot be redeemed, whether it is unknown, already spent, past its expiry, or issued through a different application than the one completing it.

All four answer identically, so the endpoint cannot be used to learn which challenges once existed. A challenge another request claims first answers the same way, since completion claims the row with a guarded update rather than on the strength of the read that found it.

Type signature ​

csharp
public sealed class InvalidTwoFactorChallengeException : Exception;

PasswordMismatchException ​

Thrown when the new password and its confirmation differ, on both ChangePasswordAsync and CompleteForgotPasswordAsync.

Type signature ​

csharp
public sealed class PasswordMismatchException : Exception;

PasswordReusedException ​

Thrown when the new password verifies against the password already stored, so a change that changes nothing is refused rather than silently accepted.

Type signature ​

csharp
public sealed class PasswordReusedException : Exception;

UsernameTakenException ​

Thrown by CreateUserAsync and RegisterAsync when another account already holds the username, compared under the database's collation.

Type signature ​

csharp
public sealed class UsernameTakenException : Exception;

EmailTakenException ​

Thrown by CreateUserAsync and RegisterAsync when another account already holds the email address, compared under the database's collation.

Also thrown by RequestEmailChangeAsync and again by CompleteEmailChangeAsync, since the check made when the change was requested cannot hold the address until it is redeemed.

Type signature ​

csharp
public sealed class EmailTakenException : Exception;

All packages are released under the MIT License.