fullstackhero/dotnet-starter-kit · error · UnauthorizedAccessException
Invalid credentials.
Error message
Invalid credentials.
What it means
Thrown by the token generation handler after ValidateCredentialsAsync (which also covers 2FA verification when enabled) returns a null identity result. It means the email/password pair (or supplied two-factor code) failed authentication; the handler first records a failed-login security audit entry bound to the request's IP/user-agent/clientId, then throws.
Solutions
- Verify the email/password are correct and the account is not locked out
- Re-run the DbMigrator --seed if the user record is missing
- Check you're connecting to the intended database/environment
Example fix
// before dotnet run --project src/Host/FSH.Starter.Api // after dotnet run --project src/Host/FSH.Starter.DbMigrator -- apply --seed dotnet run --project src/Host/FSH.Starter.Api
Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password))
throw new ValidationException("Email and password are required before calling generate-token"); Try / catch
try { return await api.post('/tokens', { email, password }); }
catch (UnauthorizedAccessException) { showError('Invalid email or password'); return null; } // never reveal which one was wrong Prevention
- Show a generic 'invalid credentials' message; never reveal whether the email exists
- Handle lockout: after repeated failures direct the user to password reset
- Ensure seed users exist (DbMigrator --seed) in fresh environments
- Confirm API/database environment variables point at the intended database
When it happens
Trigger: Wrong password, nonexistent email, account locked/disabled, or the password hash doesn't verify against the stored Identity user.
Common situations: Users typing wrong password; seed data reset so the account no longer exists; pointing the app at an empty/different database; Identity lockout after repeated failures.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/05bf640c1fccb20f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Identity/Modules.Identity/Features/v1/Tokens/TokenGeneration/GenerateTokenCommandHandler.cs:73
var ip = _requestContext.IpAddress ?? "unknown";
var ua = _requestContext.UserAgent ?? "unknown";
var clientId = _requestContext.ClientId;
// Validate credentials (includes 2FA verification when the user has it enabled)
var identityResult = await _identityService
.ValidateCredentialsAsync(request.Email, request.Password, request.TwoFactorCode, cancellationToken);
if (identityResult is null)
{
// 1) Audit failed login BEFORE throwing
await _securityAudit.LoginFailedAsync(
subjectIdOrName: request.Email,
clientId: clientId!,
reason: "InvalidCredentials",
ip: ip,
ct: cancellationToken);
throw new UnauthorizedAccessException("Invalid credentials.");
}
// Unpack subject + claims
var (subject, claims) = identityResult.Value;
// 2) Audit successful login
await _securityAudit.LoginSucceededAsync(
userId: subject,
userName: claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value ?? request.Email,
clientId: clientId!,
ip: ip,
userAgent: ua,
ct: cancellationToken);
// Issue token
var token = await _tokenService.IssueAsync(subject, claims, /*extra*/ null, cancellationToken);
// Persist refresh token (hashed) for this userView on GitHub (pinned to 3f2959e683)