diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpAspNetCoreUnitOfWorkOptions.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpAspNetCoreUnitOfWorkOptions.cs
index 67bfbfaec5..3784cc9005 100644
--- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpAspNetCoreUnitOfWorkOptions.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpAspNetCoreUnitOfWorkOptions.cs
@@ -33,7 +33,7 @@ public class AbpAspNetCoreUnitOfWorkOptions
/// even when it is globally disabled (for example
/// "/connect" matches "/connect/token" but not "/connections"). A trailing slash is normalized; blank,
/// non-absolute, and root ("/") entries are ignored - use
- /// to enable it for every request.
+ /// to enable it for every request handled by the middleware.
///
public List CompleteUnitOfWorkOnResponseStartingUrls { get; } = new List();
}
diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs
index 36c00208f9..211a5be2cf 100644
--- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs
@@ -37,7 +37,7 @@ public class AbpUnitOfWorkMiddleware : AbpMiddlewareBase, ITransientDependency
using (var uow = _unitOfWorkManager.Reserve(UnitOfWork.UnitOfWorkReservationName))
{
- var completedOnResponseStarting = false;
+ var completionAttemptedOnResponseStarting = false;
if (!context.Response.HasStarted && ShouldCompleteOnResponseStarting(context))
{
@@ -47,7 +47,7 @@ public class AbpUnitOfWorkMiddleware : AbpMiddlewareBase, ITransientDependency
if (_unitOfWorkManager.Current == uow)
{
// Set before completing so a post-commit failure isn't masked by the completion below.
- completedOnResponseStarting = true;
+ completionAttemptedOnResponseStarting = true;
await uow.CompleteAsync(_cancellationTokenProvider.Token);
}
});
@@ -55,7 +55,7 @@ public class AbpUnitOfWorkMiddleware : AbpMiddlewareBase, ITransientDependency
await next(context);
- if (!completedOnResponseStarting)
+ if (!completionAttemptedOnResponseStarting)
{
await uow.CompleteAsync(_cancellationTokenProvider.Token);
}
@@ -84,8 +84,15 @@ public class AbpUnitOfWorkMiddleware : AbpMiddlewareBase, ITransientDependency
// Normalize a trailing slash ("/connect/" behaves like "/connect") and ignore non-absolute entries.
var prefix = url.TrimEnd('/');
- if (prefix.StartsWith("/", StringComparison.Ordinal) &&
- context.Request.Path.StartsWithSegments(prefix, StringComparison.OrdinalIgnoreCase))
+ if (!prefix.StartsWith("/", StringComparison.Ordinal))
+ {
+ continue;
+ }
+
+ // Match both the request path and the path base + path, so an absolute endpoint that includes
+ // the path base still matches when the path base is stripped from Request.Path.
+ if (context.Request.Path.StartsWithSegments(prefix, StringComparison.OrdinalIgnoreCase) ||
+ context.Request.PathBase.Add(context.Request.Path).StartsWithSegments(prefix, StringComparison.OrdinalIgnoreCase))
{
return true;
}
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs
index 0826f7a3ae..09f1001104 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Razor;
@@ -50,7 +51,7 @@ public class AbpOpenIddictAspNetCoreModule : AbpModule
options.RemoveClientIdClaim();
});
- // Commit tokens/authorizations/sessions written during sign-in before the response is flushed.
+ // Complete data written while processing OpenIddict requests before the response starts.
// Derived from the configured OpenIddict server endpoint paths (including the device endpoint).
context.Services.AddOptions()
.Configure>((uowOptions, serverOptions) =>
@@ -65,6 +66,8 @@ public class AbpOpenIddictAspNetCoreModule : AbpModule
});
}
+ private static readonly Uri RootUri = new Uri("http://localhost/");
+
private static IEnumerable GetServerEndpointPaths(OpenIddictServerOptions serverOptions)
{
var endpoints = serverOptions.TokenEndpointUris
@@ -77,10 +80,11 @@ public class AbpOpenIddictAspNetCoreModule : AbpModule
foreach (var uri in endpoints)
{
- var path = uri.IsAbsoluteUri ? uri.AbsolutePath : uri.OriginalString;
- if (!string.IsNullOrWhiteSpace(path))
+ // Resolve relative endpoint URIs (e.g. "connect/token" or "./connect/token") to an absolute path.
+ var path = (uri.IsAbsoluteUri ? uri : new Uri(RootUri, uri)).AbsolutePath;
+ if (!string.IsNullOrWhiteSpace(path) && path != "/")
{
- yield return "/" + path.TrimStart('/');
+ yield return path;
}
}
}
diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.AspNetCore.Tests/Volo/Abp/OpenIddict/Integration/OpenIddictTokenEndpoint_Integration_Tests.cs b/modules/openiddict/test/Volo.Abp.OpenIddict.AspNetCore.Tests/Volo/Abp/OpenIddict/Integration/OpenIddictTokenEndpoint_Integration_Tests.cs
index cf11cffdf3..483e64694b 100644
--- a/modules/openiddict/test/Volo.Abp.OpenIddict.AspNetCore.Tests/Volo/Abp/OpenIddict/Integration/OpenIddictTokenEndpoint_Integration_Tests.cs
+++ b/modules/openiddict/test/Volo.Abp.OpenIddict.AspNetCore.Tests/Volo/Abp/OpenIddict/Integration/OpenIddictTokenEndpoint_Integration_Tests.cs
@@ -34,7 +34,7 @@ public class OpenIddictTokenEndpoint_Integration_Tests : AbpWebApplicationFactor
[Fact]
public async Task Token_Row_Is_Committed_Before_The_Connect_Token_Response_Is_Sent()
{
- // The OpenIddict module opts "/connect" in by default.
+ // The OpenIddict module opts its endpoint paths (including "/connect/token") in by default.
var response = await RequestTokenAsync();
response.StatusCode.ShouldBe(HttpStatusCode.OK);