Thanks, that works! I’m just wondering - could this actually be a bug in ABP/OpenIddict? The current solution feels more like a workaround. I thought prompt=login
was supposed to always force authentication. According to the OpenID Connect spec:
prompt OPTIONAL. Space-delimited, case-sensitive list of ASCII string values that specifies whether the Authorization Server prompts the End-User for reauthentication and consent. The defined values are: none The Authorization Server MUST NOT display any authentication or consent user interface pages. An error is returned if an End-User is not already authenticated or the Client does not have pre-configured consent for the requested Claims or does not fulfill other conditions for processing the request. The error code will typically be login_required, interaction_required, or another code defined in Section 3.1.2.6. This can be used as a method to check for existing authentication and/or consent. login The Authorization Server SHOULD prompt the End-User for reauthentication. If it cannot reauthenticate the End-User, it MUST return an error, typically login_required. consent The Authorization Server SHOULD prompt the End-User for consent before returning information to the Client. If it cannot obtain consent, it MUST return an error, typically consent_required. select_account The Authorization Server SHOULD prompt the End-User to select a user account. This enables an End-User who has multiple accounts at the Authorization Server to select amongst the multiple accounts that they might have current sessions for. If it cannot obtain an account selection choice made by the End-User, it MUST return an error, typically account_selection_required.
So it seems like the behavior here doesn’t fully match the spec. Are there any plans to fix this in future ABP releases?
Hi,
It solves double click issue, but brings a new one. Even after successful BankID login it redirects back to BankID login page causing an endless loop. Check video bankid-login-issue-2-2025-09-24 100243
in the shared folder.
It skips Account/Login
after connect/authorize...
. That's what I found in logs:
18:29:05 INF] The authorization request was successfully validated. [18:29:05 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessRequestContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Authentication+ValidateAuthorizationRequest. [18:29:05 DBG] The event OpenIddict.Server.OpenIddictServerEvents+HandleAuthorizationRequestContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Authentication+AttachPrincipal. [18:29:05 DBG] The event OpenIddict.Server.OpenIddictServerEvents+HandleAuthorizationRequestContext was successfully processed by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+EnablePassthroughMode
2[[OpenIddict.Server.OpenIddictServerEvents+HandleAuthorizationRequestContext, OpenIddict.Server, Version=6.2.1.0, Culture=neutral, PublicKeyToken=35a561290d20de2f],[OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlerFilters+RequireAuthorizationEndpointPassthroughEnabled, OpenIddict.Server.AspNetCore, Version=6.2.1.0, Culture=neutral, PublicKeyToken=35a561290d20de2f]]. [18:29:05 DBG] **The event OpenIddict.Server.OpenIddictServerEvents+HandleAuthorizationRequestContext was marked as skipped by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+EnablePassthroughMode**
2[[OpenIddict.Server.OpenIddictServerEvents+HandleAuthorizationRequestContext, OpenIddict.Server, Version=6.2.1.0, Culture=neutral, PublicKeyToken=35a561290d20de2f],[OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlerFilters+RequireAuthorizationEndpointPassthroughEnabled, OpenIddict.Server.AspNetCore, Version=6.2.1.0, Culture=neutral, PublicKeyToken=35a561290d20de2f]]. [18:29:05 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessRequestContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Authentication+HandleAuthorizationRequest. [18:29:05 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessRequestContext was marked as skipped by OpenIddict.Server.OpenIddictServerHandlers+Authentication+HandleAuthorizationRequest.
It worked for me once, just like in your video, but now it only works after the second click. I’ve added a video illustrating the issue with demo project. Could you please take a look at the folder I shared with you earlier?
Sure, check your e-mail.
Hi, Check your e-mail please, har file should be there.
Hah, the AI-bot just copy-pasted my own code.
Hi, This is a continuation of my previous ticket.
In my application, some actions should only be allowed when the user is authenticated via BankID (external login).
I’m looking for a way to force a user to log in with a specific provider. So far, the only approach I found is overriding the LoginModel
. While it works, it feels like a hack and may not be the recommended way.
navigateToBankIdLogin(){
this.authService.navigateToLogin({
prompt: 'login',
bankid: true
});
}
[ExposeServices(typeof(Volo.Abp.Account.Public.Web.Pages.Account.LoginModel))]
public class LoginModel : Volo.Abp.Account.Public.Web.Pages.Account.LoginModel
{
public LoginModel(IAuthenticationSchemeProvider schemeProvider,
IOptions<AbpAccountOptions> accountOptions, IAbpRecaptchaValidatorFactory recaptchaValidatorFactory,
IAccountExternalProviderAppService accountExternalProviderAppService,
ICurrentPrincipalAccessor currentPrincipalAccessor, IOptions<IdentityOptions> identityOptions,
IOptionsSnapshot<reCAPTCHAOptions> reCaptchaOptions) : base(schemeProvider, accountOptions,
recaptchaValidatorFactory, accountExternalProviderAppService, currentPrincipalAccessor, identityOptions,
reCaptchaOptions)
{
}
public override Task<IActionResult> OnGetAsync()
{
return ShouldForceBankIdLogin()
? base.OnPostExternalLogin(MachineRegistryConsts.BankIdLoginProviderName)
: base.OnGetAsync();
}
private bool ShouldForceBankIdLogin()
{
if (ReturnUrl.IsNullOrEmpty())
{
return false;
}
var decodedReturnUrl = HttpUtility.UrlDecode(ReturnUrl);
return decodedReturnUrl.Split("&").Any(p => p.Equals("bankid=true", StringComparison.OrdinalIgnoreCase));
}
}
Additionally, there’s a UI/flow issue: I have to click the login button twice before the user is navigated to the BankID login, even though the prompt is set to 'login'. Bellow is a gif showing the issue:
Could you advise on the recommended ABP way to enforce external login for specific actions and/or address the double-click issue?
Ok, thanks.
[maliming] said: hi
using System; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Identity; using OpenIddict.Abstractions; using OpenIddict.Server; namespace BankIdDemo; public class BankIdOpenIddictServerHandler : IOpenIddictServerHandler<OpenIddictServerEvents.ProcessSignInContext> { public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder<OpenIddictServerEvents.ProcessSignInContext>() .UseSingletonHandler<BankIdOpenIddictServerHandler>() .SetOrder(100_000) .SetType(OpenIddictServerHandlerType.Custom) .Build(); public async ValueTask HandleAsync(OpenIddictServerEvents.ProcessSignInContext context) { var httpContext = context.Transaction.GetHttpRequest()?.HttpContext; if (httpContext == null) { return; } if (context.EndpointType == OpenIddictServerEndpointType.Authorization && context.AuthorizationCodePrincipal != null) { var identity = await httpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme); if (identity.Principal != null) { var bankIdClaim = identity.Principal.FindFirst("isbankidauthenticated"); if (bankIdClaim != null) { context.AuthorizationCodePrincipal?.AddClaim("isbankidauthenticated", bankIdClaim.Value); }; }; } if (context.EndpointType == OpenIddictServerEndpointType.Token) { if (context.AccessTokenPrincipal != null && context.IdentityTokenPrincipal != null) { var bankIdClaim = context.AccessTokenPrincipal .FindFirst("isbankidauthenticated"); if (bankIdClaim != null) { context.IdentityTokenPrincipal?.AddClaim("isbankidauthenticated", bankIdClaim.Value); } } } } }
Thanks, that was very helpful. I have a couple more questions related to authentication, should I continue here or open a new ticket?