I want to implement some actions (such as given award points to a user daily if the user sign in every day), I need to add an event to OpenIddict server event that it could fire an event handler to implement the logistics, I have followed the article add the event handler and registered in AuthServer project (a micro-services architecture solution), but the event handler not fired and no logs logged, is there any suggestions to debug, or I am using an incorrect way to configure the event handler?
- Exception message and full stack trace: No
- Steps to reproduce the issue: Create an OpenIddictServerEvents.ProcessSignInContext event handler and registered, some code as below:
public class DailyPointsHandler : IOpenIddictServerHandler<OpenIddictServerEvents.ProcessSignInContext>//, ITransientDependency
{
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<OpenIddictServerEvents.ProcessSignInContext>()
.UseScopedHandler<DailyPointsHandler>()
.SetOrder(100_000)
.SetType(OpenIddictServerHandlerType.Custom)
.Build();
private readonly IdentityUserManager _userManager;
private readonly IClock _clock;
private readonly ILogger<DailyPointsHandler> _logger;
private readonly IRewardPointsHistoriesAppService _rewardPointsHistoriesAppService;
private readonly IUnitOfWorkManager _unitOfWorkManager;
public DailyPointsHandler(
IdentityUserManager userManager,
IClock clock,
ILogger<DailyPointsHandler> logger,
IRewardPointsHistoriesAppService rewardPointsHistoriesAppService,
IUnitOfWorkManager unitOfWorkManager)
{
_userManager = userManager;
_clock = clock;
_logger = logger;
_rewardPointsHistoriesAppService = rewardPointsHistoriesAppService;
_unitOfWorkManager = unitOfWorkManager;
_logger.LogInformation("DailyPointsHandler constructor initialized");
}
public async ValueTask HandleAsync(OpenIddictServerEvents.ProcessSignInContext context)
{
_logger.LogInformation("进入每日积分处理器");
if (context is null) throw new ArgumentNullException(nameof(context));
// 跳过客户端凭证流程和刷新令牌流程
if (context.Request.IsClientCredentialsGrantType() ||
context.Request.IsRefreshTokenGrantType())
{
_logger.LogInformation("跳过非用户登录流程");
return;
}
// 获取用户ID
var userId = context.Principal?.FindFirst(OpenIddictConstants.Claims.Subject)?.Value;
if (string.IsNullOrEmpty(userId))
{
_logger.LogWarning("无法从声明中获取用户ID");
return;
}
try
{
using var uow = _unitOfWorkManager.Begin(requiresNew: true);
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
_logger.LogWarning("用户未找到: {UserId}", userId);
return;
}
if (user != null)
{
var rewardPointsHistoryCreate = new RewardPointsHistoryCreateDto();
rewardPointsHistoryCreate.UserId = user.Id;
rewardPointsHistoryCreate.RewardPointType = RewardPointType.DailySignIn;
await _rewardPointsHistoriesAppService.CreateAsync(rewardPointsHistoryCreate);
await uow.CompleteAsync();
_logger.LogInformation("用户 {UserName} 获得每日登录奖励", user.UserName);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "每日积分赠送处理失败");
// 失败时继续登录流程,不影响认证
}
}
}
registered it at:
private void PreConfigureOpenIddict(IConfiguration configuration, IWebHostEnvironment hostingEnvironment)
{
PreConfigure<OpenIddictBuilder>(builder =>
{
builder.AddValidation(options =>
{
options.AddAudiences("AuthServer");
options.UseLocalServer();
options.UseAspNetCore();
});
builder.AddServer(options =>
{
options.AddEventHandler<ProcessSignInContext>(builder =>
builder.UseInlineHandler(context =>
{
// Attach custom metadata to the configuration document.
//context.Metadata["custom_metadata"] = 42;
context.Logger.LogInformation("Processing sign-in event in inline handler for user {userId}.", context.Principal?.FindFirst(OpenIddictConstants.Claims.Subject)?.Value);
return default;
}));
});
});
PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
{
serverBuilder.AddEventHandler(DailyPointsHandler.Descriptor);
serverBuilder.AddEventHandler(SignOutEventHandler.Descriptor);
serverBuilder.AddEventHandler<ProcessSignInContext>(builder =>
builder.UseInlineHandler(context =>
{
// Attach custom metadata to the configuration document.
//context.Metadata["custom_metadata"] = 42;
context.Logger.LogInformation("Processing sign-in event in inline handler for user {userId}.", context.Principal?.FindFirst(OpenIddictConstants.Claims.Subject)?.Value);
return default;
}));
});
}
5 Answer(s)
-
0
- To ensure your custom OpenIddict server event handler (e.g., for
ProcessSignInContext
) is fired in an ABP microservices solution, follow these steps and debugging suggestions:
- Correct Registration Location
- Register your handler using
PreConfigure<OpenIddictServerBuilder>
in your AuthServer module'sPreConfigureServices
method. - Example:
- Register your handler using
public override void PreConfigureServices(ServiceConfigurationContext context) { PreConfigure<OpenIddictServerBuilder>(serverBuilder => { serverBuilder.AddEventHandler(DailyPointsHandler.Descriptor); }); }
- Avoid registering the same handler in both
OpenIddictBuilder
andOpenIddictServerBuilder
. Use onlyOpenIddictServerBuilder
for server events.
Handler Lifetime
- If your handler depends on scoped services (like
IUnitOfWorkManager
), use.UseScopedHandler<DailyPointsHandler>()
in the descriptor. - Ensure your handler is not registered as a singleton if it depends on scoped services.
- If your handler depends on scoped services (like
Check Event Handler Order
- The
SetOrder(100_000)
is usually fine, but if other handlers short-circuit the pipeline before yours, your handler may not be called. Try lowering the order value to ensure it runs earlier.
- The
Logging and Diagnostics
- Enable verbose logging for OpenIddict to see if your handler is being invoked or if there are pipeline issues:
var loggerConfiguration = new LoggerConfiguration() .MinimumLevel.Debug() .MinimumLevel.Override("OpenIddict", LogEventLevel.Verbose) .WriteTo.File("Logs/openiddict.txt");
- Also, ensure your logger is properly configured and that log files are being written.
- Validate Handler Execution
- Add a simple inline handler for
ProcessSignInContext
to verify if any handler is being called:
- Add a simple inline handler for
serverBuilder.AddEventHandler<ProcessSignInContext>(builder => builder.UseInlineHandler(context => { context.Logger.LogInformation("Inline sign-in handler fired for user {userId}.", context.Principal?.FindFirst(OpenIddictConstants.Claims.Subject)?.Value); return default; }));
- If this inline handler is not triggered, the event itself may not be firing due to pipeline misconfiguration.
Check Grant Types
- Your handler skips client credentials and refresh token grants. Make sure your sign-in flow is not using these grant types.
Microservices Considerations
- Ensure the AuthServer is the only service handling authentication and that requests are routed correctly.
- If using multiple environments or containers, confirm the correct module is being loaded and configured.
No Duplicate Registrations
- Avoid registering the same handler multiple times or in both
OpenIddictBuilder
andOpenIddictServerBuilder
.
- Avoid registering the same handler multiple times or in both
Restart and Clean Build
- After changes, do a clean build and restart your AuthServer to ensure all configurations are applied.
If after these steps your handler is still not firing, try creating a minimal reproduction project with only the handler and registration logic to isolate the issue.
Sources:
- Customizing Authentication Flow with OpenIddict Events in ABP Framework
- ABP OpenIddict Module Documentation
- OpenIddict Events Model
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
- To ensure your custom OpenIddict server event handler (e.g., for
-
0
The simple inline handle is not triggered, the event itself may not be firing due to pipeline misconfiguration, could you give some suggestions which pipeline misconfiguration?
-
0
hi
Please add your code to a new app template project and share it.
liming.ma@volosoft.com
Thanks
-
0
Thanks for the help from Maliming, the auth server UI login is a cookie authentication, not the token scenario, added below code auth server module works fine
` context.Services.ConfigureApplicationCookie(options => { var previousOnSignedIn = options.Events.OnSignedIn; options.Events.OnSignedIn = async cookieSignedInContext => { await previousOnSignedIn(cookieSignedInContext);
};var previousOnSigningOut = options.Events.OnSigningOut; options.Events.OnSigningOut = async cookieSigningOutContext => { await previousOnSigningOut(cookieSigningOutContext); };
}); `
-
0
You’re welcome. 👍