fullstackhero/dotnet-starter-kit · warning · InvalidOperationException

User is not authenticated.

Error message

User is not authenticated.

What it means

ChangePasswordCommandHandler throws InvalidOperationException('User is not authenticated.') when ICurrentUser.IsAuthenticated() is false. Unlike the 2FA handlers it uses the BCL exception type instead of the module's UnauthorizedException, so it surfaces as a 500 unless mapped.

Solutions

  1. Sign in again and retry with a fresh Authorization: Bearer header
  2. Confirm the endpoint requires authorization and middleware order is UseAuthentication → UseAuthorization
  3. In tests, stub ICurrentUser with IsAuthenticated() = true
  4. Consider aligning with the module's UnauthorizedException so callers get a proper 401 instead of a 500

Example fix

// before
if (!_currentUser.IsAuthenticated())
{
    throw new InvalidOperationException("User is not authenticated.");
}
// after
if (!_currentUser.IsAuthenticated())
{
    throw new UnauthorizedException();
}
Defensive patterns

Strategy: try-catch

Validate before calling

function canChangePassword() {
  return Boolean(accessToken) && !isTokenExpired(accessToken);
}
if (!canChangePassword()) await reauthenticate();

Try / catch

try {
  await api.changePassword(payload);
} catch (e) {
  if (e.status === 500 && /not authenticated/i.test(e.message)
      || e.status === 401) {
    await reauthenticate();
    return retry();
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling change-password without a valid bearer token or with an expired JWT; invoking the handler directly in tests without an authenticated ICurrentUser; a route accidentally exposed without authorization.

Common situations: Token expired mid-session; frontend dropped the Authorization header; auth middleware misordered or omitted; test harness lacking an authenticated principal.

Understand the failure class

Related errors


AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15). Data as JSON: /api/errors/71d8a6d414eb05b9. Report an issue: GitHub.

Appendix: source

Thrown at src/Modules/Identity/Modules.Identity/Features/v1/Users/ChangePassword/ChangePasswordCommandHandler.cs:25

public sealed class ChangePasswordCommandHandler : ICommandHandler<ChangePasswordCommand, string>
{
    private readonly IUserService _userService;
    private readonly ICurrentUser _currentUser;

    public ChangePasswordCommandHandler(IUserService userService, ICurrentUser currentUser)
    {
        _userService = userService;
        _currentUser = currentUser;
    }

    public async ValueTask<string> Handle(ChangePasswordCommand command, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(command);

        if (!_currentUser.IsAuthenticated())
        {
            throw new InvalidOperationException("User is not authenticated.");
        }

        var userId = _currentUser.GetUserId().ToString();

        await _userService.ChangePasswordAsync(command.Password, command.NewPassword, command.ConfirmNewPassword, userId, cancellationToken).ConfigureAwait(false);

        return "password reset email sent";
    }
}

View on GitHub (pinned to 3f2959e683)