Hi,
Both. They aren't alternatives, each one fixes a different project, in this order:
context.Request.Scheme = "https", after app.UseForwardedHeaders() and before app.UseAuthentication(). Once deployed, jwks_uri in /.well-known/openid-configuration has to start with https.options.MapInboundClaims = false, and for now set options.TokenValidationParameters.ValidateAudience = false.currentUser in application-configuration.If isAuthenticated is true after that, add the missing resources to OpenIddictScopes as described in the second reply, then turn audience validation back on. If it's still false, send the new identitymodel logs from both projects.
Yaduraj said on Friday he was updating the code, so part of this may already be in place on his side.
Thanks
Hi,
A confirmed email is enough to enable two-factor for a user, no email sender is needed for that. The error comes from the service that hosts the Identity APIs. In ABP v10.6 and earlier, the email and phone two-factor token providers are only registered by AbpIdentityAspNetCoreModule, and the IdentityService of the microservice template doesn't depend on it, so it finds no provider for the user.
You can fix it for now in your IdentityService project. Add the package (same version as your other ABP packages):
<PackageReference Include="Volo.Abp.Identity.AspNetCore" Version="<your-abp-version>" />
Then depend on the module and turn off its cookie authentication setup, since the service uses JWT bearer:
using Volo.Abp.Identity.AspNetCore;
[DependsOn(
//...
typeof(AbpIdentityAspNetCoreModule)
)]
public class MyProjectNameIdentityServiceModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpIdentityAspNetCoreOptions>(options =>
{
options.ConfigureAuthentication = false;
});
//...
}
}
After restarting the service, the Two factor action works for users with a confirmed email.
In v10.7 these token providers are registered in the domain layer, so this workaround won't be needed after upgrading: https://github.com/abpframework/abp/pull/26113
If your solution isn't a microservice one, please share the solution type and your ABP version.
Your ticket has been refunded.
Thanks
Hi,
Thanks for the latest file. Two things, otherwise the scheme change alone won't get you there.
The access token carries no aud claim, while the gateway sets options.Audience from AuthServer:ApiResource. Audience validation will reject it as soon as the signing keys are reachable again.
To confirm that quickly, turn the check off for now in the JwtBearer scheme:
options.TokenValidationParameters.ValidateAudience = false;
If login works with that, the missing aud is what's left. The real fix is on the AuthServer side: ABP fills aud from the resources attached to the granted scopes, so the rows in OpenIddictScopes currently have none. The OpenIddict tables do matter here, contrary to what I said earlier.
select "Name", "Resources" from "OpenIddictScopes";
Resources of the Litmus scope has to contain the API resource name, the way the seeder creates it:
await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor {
Name = "Litmus", DisplayName = "Litmus API", Resources = { "Litmus" }
});
Also take options.MapInboundClaims = false back out. On the API side ABP reads the user id through AbpClaimTypes.UserId, and that stays ClaimTypes.NameIdentifier unless an OpenIddict module runs in the same process, which your gateway doesn't have. The default mapping is what turns sub into that claim, so switching it off leaves currentUser empty. AddAbpJwtBearer keeps the default for this reason, and it also explains why FindFirst("sub") in your new logging comes back null.
Thanks
Hi,
Thanks for the logs, they pinned it down. The gateway reads the discovery document over https, but the jwks_uri inside it is http://api-product.dev.tasconnect.net/.well-known/jwks, and port 80 refuses the connection. With no keys the gateway has no configuration to validate against, which is the IDX10204 you see, and the request ends up anonymous.
OpenIddict builds the endpoint URLs of that document from the scheme of the incoming request, and the identity task receives plain HTTP once the gateway terminates TLS. SetIssuer only fixes the issuer field, not those URLs.
In the identity host, right after app.UseForwardedHeaders() and before app.UseAuthentication():
app.Use(async (context, next) =>
{
if (context.Request.Path.StartsWithSegments("/.well-known"))
{
context.RequestServices
.GetRequiredService<ILogger<LitmusIdentityServerModule>>()
.LogWarning("Scheme: {Scheme}, Host: {Host}, X-Forwarded-Proto: {Proto}, X-Forwarded-Host: {ForwardedHost}",
context.Request.Scheme,
context.Request.Host.Value,
context.Request.Headers["X-Forwarded-Proto"].ToString(),
context.Request.Headers["X-Forwarded-Host"].ToString());
}
context.Request.Scheme = "https";
await next();
});
Once it's deployed, https://api-product.dev.tasconnect.net/.well-known/openid-configuration should list jwks_uri with https.
If it still fails, send the new identitymodel logs from both projects together with those Scheme / X-Forwarded-Proto lines. They tell us what the gateway really forwards, and we go from there.
Thanks
Hi,
Good to hear the identity service is up.
In ABP, currentUser.isAuthenticated is Id.HasValue, so false only tells us the API ended up with no claim matching AbpClaimTypes.UserId on the principal. That covers two different things: the token not being accepted at all, or the token being fine while the user id claim sits under a different claim type than the API expects.
To tell those apart, send me:
ConfigureAuthenticationSetup.ConfigureAuthenticationidentitymodel log, both for one application-configuration call made with that tokenBoth logs are described here: https://abp.io/support/questions/8622/How-to-enable-Debug-logs-for-troubleshoot-problems
The identitymodel one is what shows why a token gets refused. In the API host's Program.cs:
using System.Diagnostics.Tracing;
using Microsoft.IdentityModel.Logging;
IdentityModelEventSource.ShowPII = true;
IdentityModelEventSource.Logger.LogLevel = EventLevel.Verbose;
var wilsonTextLogger = new TextWriterEventListener("Logs/identitymodel.txt");
wilsonTextLogger.EnableEvents(IdentityModelEventSource.Logger, EventLevel.Verbose);
Thanks
Hi,
Please share the details below before the call. Without them I'd still be working through the same things during the meeting.
Two changes came out of this thread last week, both for the identity service:
Program.cs: await AddApplicationAsync and InitializeApplicationAsync, with an async Main. Yaduraj applied this one.dotnet publish output rather than the dotnet build output. No result reported on this one yet.Where does each stand now? Then, from the build that's running, search the identity task's startup log for this line:
Initialized all ABP modules.
If it's there, the ABP pipeline is up and the login problem is elsewhere. If it isn't, the app still isn't initializing, and the lines around it tell me why. Send me that part of the log, unfiltered.
Also:
/.well-known/openid-configuration and /connect/token, status code and bodyThanks
Hi,
That's a bug on our side. UpdateUserRolesBasedOnOrganizationUnits shouldn't write back to input, and we're changing it to a local variable exactly the way you suggested.
Until that ships, you can override the app service and put the caller's original value back after the base call:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Identity;
using Volo.Abp.Identity.Emailing;
using Volo.Abp.Identity.UserInvitations;
using Volo.Abp.Identity.UserSharing;
using Volo.Abp.Threading;
namespace MyCompanyName.MyProjectName.Identity;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IIdentityUserAppService))]
public class MyIdentityUserAppService : IdentityUserAppService
{
public MyIdentityUserAppService(
IdentityUserManager userManager,
IIdentityUserRepository userRepository,
IIdentityRoleRepository roleRepository,
IOrganizationUnitRepository organizationUnitRepository,
IIdentityClaimTypeRepository identityClaimTypeRepository,
IdentityProTwoFactorManager identityProTwoFactorManager,
IOptions<IdentityOptions> identityOptions,
IDistributedEventBus distributedEventBus,
IOptions<AbpIdentityOptions> abpIdentityOptions,
IPermissionChecker permissionChecker,
IDistributedCache<IdentityUserDownloadTokenCacheItem, string> downloadTokenCache,
IDistributedCache<ImportInvalidUsersCacheItem, string> importInvalidUsersCache,
IdentitySessionManager identitySessionManager,
IdentityUserTwoFactorChecker identityUserTwoFactorChecker,
ICancellationTokenProvider cancellationTokenProvider,
UserSharingManager userSharingManager,
UserInvitationManager userInvitationManager,
IIdentityUserInvitationRepository userInvitationRepository,
IIdentityEmailSender identityEmailSender)
: base(
userManager,
userRepository,
roleRepository,
organizationUnitRepository,
identityClaimTypeRepository,
identityProTwoFactorManager,
identityOptions,
distributedEventBus,
abpIdentityOptions,
permissionChecker,
downloadTokenCache,
importInvalidUsersCache,
identitySessionManager,
identityUserTwoFactorChecker,
cancellationTokenProvider,
userSharingManager,
userInvitationManager,
userInvitationRepository,
identityEmailSender)
{
}
protected override async Task UpdateUserRolesBasedOnOrganizationUnits(IdentityUser user, IdentityUserCreateOrUpdateDtoBase input)
{
var organizationUnitIds = input.OrganizationUnitIds;
await base.UpdateUserRolesBasedOnOrganizationUnits(user, input);
input.OrganizationUnitIds = organizationUnitIds;
}
}
Drop it into your *.Application project. That constructor is the 10.4 one and it does change between versions, so re-check it if you upgrade before the fix is out.
If you'd rather not replace the service, sending the current ids from the caller works too:
input.OrganizationUnitIds = (await _identityUserAppService.GetOrganizationUnitsAsync(id))
.Select(x => x.Id)
.ToArray();
await _identityUserAppService.UpdateAsync(id, input);
The fix will be in v10.7.0. Your ticket has been refunded.
Thanks