CurrentUser is null even though [Authorize]
is applied — controller method still executes after failed authentication
Hey ABP team,
We’re running into an issue where a controller method is still being executed even though authentication has failed. This causes CurrentUser.GetId() to throw an exception because CurrentUser is null.
Here's the setup:
[RemoteService]
[Area("umob")]
[ControllerName("UserDocument")]
[Authorize]
public class UserDocumentController : AppVersionRestrictedController
{
private readonly IUserDocumentHelperAppService _userDocumentHelperAppService;
public UserDocumentController(IUserDocumentHelperAppService userDocumentHelperAppService)
{
_userDocumentHelperAppService = userDocumentHelperAppService;
}
[HttpPost]
[Route("/api/umob/userdocument/validate")]
public async Task<UserDocumentValidationDto> Validate(PostUserDocumentValidation data) =>
await _userDocumentHelperAppService.ValidateUserDocumentForAsset(CurrentUser.GetId(), data);
}
In our logs, we clearly see that OpenIddict.Validation.AspNetCore logs an authentication failure:
The token is no longer valid because the user’s session expired.
Validation.AspNetCore was not authenticated.
Yet, immediately afterward, the controller method still runs. We end up with this exception:
System.InvalidOperationException: Nullable object must have a value.
at uMob.Controllers.UserDocumentController.Validate(...)
I've verified that:
-
[Authorize]
is on the controller level. -
No
[AllowAnonymous]
is applied. -
We're not using any custom middleware that could short-circuit auth.
-
The failure seems to occur in OpenIddict middleware, yet doesn’t prevent the controller from executing.
Do you know how this can happen in an ABP-based app?
Is there any ABP config or middleware behavior that could cause CurrentUser
to be null while still executing controller methods?
3 Answer(s)
-
0
-
0
Hey Liming,
Thanks for the quick response!
Unfortunately, I’m not able to reproduce this issue locally — it only occurs in our production environment under specific conditions, which seem related to expired access tokens or invalid sessions. I did try to delete a active session locally, but then the authentication functions properly.
I’ve double-checked our configuration:
-
[Authorize] is applied at the controller level.
-
We’re using ABP + OpenIddict for auth.
-
No [AllowAnonymous] attributes are used.
-
Authentication failures are logged (e.g., “token no longer valid because session expired”), but the controller method still executes and CurrentUser is null.
Since it’s a production-only issue, I can’t easily provide a minimal repro project. But I’m happy to share relevant logs, config, or middleware setup if that helps narrow it down.
Would you have any ideas what might cause this behavior? Or anything specific I should inspect further?
Thanks again!
-
-
0
hi
You can test 1 or 2.
Thanks.
-
You can try to disable the
DynamicClaims
.
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options => { options.IsDynamicClaimsEnabled = false; });
-
You can use the latest middleware code.
- app.UseDynamicClaims(); + app.UseMiddleware<MyAbpDynamicClaimsMiddleware>();
public class MyAbpDynamicClaimsMiddleware : AbpMiddlewareBase, ITransientDependency { public async override Task InvokeAsync(HttpContext context, RequestDelegate next) { if (context.User.Identity?.IsAuthenticated == true) { if (context.RequestServices.GetRequiredService<IOptions<AbpClaimsPrincipalFactoryOptions>>().Value.IsDynamicClaimsEnabled) { var authenticateResultFeature = context.Features.Get<IAuthenticateResultFeature>(); var authenticationType = authenticateResultFeature?.AuthenticateResult?.Ticket?.AuthenticationScheme ?? context.User.Identity.AuthenticationType; if (authenticateResultFeature != null && !authenticationType.IsNullOrWhiteSpace()) { var abpClaimsPrincipalFactory = context.RequestServices.GetRequiredService<IAbpClaimsPrincipalFactory>(); var user = await abpClaimsPrincipalFactory.CreateDynamicAsync(context.User); authenticateResultFeature.AuthenticateResult = AuthenticateResult.Success(new AuthenticationTicket( user, authenticateResultFeature?.AuthenticateResult?.Properties, authenticationType)); } if (context.User.Identity?.IsAuthenticated == false) { var authenticationSchemeProvider = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>(); if (!authenticationType.IsNullOrWhiteSpace()) { var authenticationScheme = await authenticationSchemeProvider.GetSchemeAsync(authenticationType); if (authenticationScheme != null && typeof(IAuthenticationSignOutHandler).IsAssignableFrom(authenticationScheme.HandlerType)) { await context.SignOutAsync(authenticationScheme.Name); } } } } } await next(context); } }
-