diff --git a/docs/en/Modules/OpenIddict.md b/docs/en/Modules/OpenIddict.md index f315ed1cd4..d7386afe5f 100644 --- a/docs/en/Modules/OpenIddict.md +++ b/docs/en/Modules/OpenIddict.md @@ -172,6 +172,43 @@ https://documentation.openiddict.com https://github.com/openiddict/openiddict-core#resources +### Token encryption + +https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html + +> By default, OpenIddict enforces encryption for all the token types it supports. While this enforcement cannot be disabled for authorization codes, refresh tokens and device codes for security reasons, it can be relaxed for access tokens when integration with third-party APIs/resource servers is desired. Access token encryption can also be disabled if the resource servers receiving the access tokens don't fully support JSON Web Encryption. + +```cs +PreConfigure(builder => +{ + builder.DisableAccessTokenEncryption(); +}); +``` + +An example of using `SecurityKey` + +> In production, it is recommended to use two RSA certificates, distinct from the certificate(s) used for HTTPS: one for encryption, one for signing. + +```cs +// In OpenIddict Server +PreConfigure(builder => +{ + builder.AddSigningKey(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_C40DBB176E78"))); + builder.AddEncryptionKey(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_87E33FC57D80"))); +}); + +//In Client AddJwtBearer +builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(options => + { + //Other configuration + + options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_C40DBB176E78")); + options.TokenValidationParameters.TokenDecryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_87E33FC57D80")); + }); +``` + + ### PKCE https://documentation.openiddict.com/configuration/proof-key-for-code-exchange.html diff --git a/modules/openiddict/app/OpenIddict.Demo.API/Program.cs b/modules/openiddict/app/OpenIddict.Demo.API/Program.cs index 0411958484..eb6516c44c 100644 --- a/modules/openiddict/app/OpenIddict.Demo.API/Program.cs +++ b/modules/openiddict/app/OpenIddict.Demo.API/Program.cs @@ -1,4 +1,10 @@ +using System.Text; using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.IdentityModel.Tokens; var builder = WebApplication.CreateBuilder(args); builder.Logging.ClearProviders(); @@ -16,6 +22,10 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) { options.Authority = "https://localhost:44301"; options.Audience = "AbpAPIResource"; + + // See OpenIddictServerModule`s PreConfigureServices method. + options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_C40DBB176E78")); + options.TokenValidationParameters.TokenDecryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_87E33FC57D80")); }); var app = builder.Build(); @@ -34,4 +44,4 @@ app.UseAuthorization(); app.MapControllers(); -app.Run(); \ No newline at end of file +app.Run(); diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220331065901_Initial.Designer.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220405034203_Initial.Designer.cs similarity index 98% rename from modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220331065901_Initial.Designer.cs rename to modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220405034203_Initial.Designer.cs index 105d2664a7..bba3a86a72 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220331065901_Initial.Designer.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220405034203_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace OpenIddict.Demo.Server.Migrations { [DbContext(typeof(ServerDbContext))] - [Migration("20220331065901_Initial")] + [Migration("20220405034203_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -757,7 +757,7 @@ namespace OpenIddict.Demo.Server.Migrations .IsUnique() .HasFilter("[ClientId] IS NOT NULL"); - b.ToTable("AbpOpenIddictApplications", (string)null); + b.ToTable("OpenIddictApplications", (string)null); }); modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => @@ -794,6 +794,10 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("datetime2") .HasColumnName("DeletionTime"); + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") @@ -830,7 +834,7 @@ namespace OpenIddict.Demo.Server.Migrations b.HasIndex("ApplicationId", "Status", "Subject", "Type"); - b.ToTable("AbpOpenIddictAuthorizations", (string)null); + b.ToTable("OpenIddictAuthorizations", (string)null); }); modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => @@ -907,7 +911,7 @@ namespace OpenIddict.Demo.Server.Migrations .IsUnique() .HasFilter("[Name] IS NOT NULL"); - b.ToTable("AbpOpenIddictScopes", (string)null); + b.ToTable("OpenIddictScopes", (string)null); }); modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => @@ -950,6 +954,10 @@ namespace OpenIddict.Demo.Server.Migrations b.Property("ExpirationDate") .HasColumnType("datetime2"); + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") @@ -999,7 +1007,7 @@ namespace OpenIddict.Demo.Server.Migrations b.HasIndex("ApplicationId", "Status", "Subject", "Type"); - b.ToTable("AbpOpenIddictTokens", (string)null); + b.ToTable("OpenIddictTokens", (string)null); }); modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => @@ -1237,18 +1245,18 @@ namespace OpenIddict.Demo.Server.Migrations modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => { b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) - .WithMany("Authorizations") + .WithMany() .HasForeignKey("ApplicationId"); }); modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => { b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) - .WithMany("Tokens") + .WithMany() .HasForeignKey("ApplicationId"); b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) - .WithMany("Tokens") + .WithMany() .HasForeignKey("AuthorizationId"); }); @@ -1284,18 +1292,6 @@ namespace OpenIddict.Demo.Server.Migrations b.Navigation("Roles"); }); - modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => - { - b.Navigation("Authorizations"); - - b.Navigation("Tokens"); - }); - - modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => - { - b.Navigation("Tokens"); - }); - modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => { b.Navigation("ConnectionStrings"); diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220331065901_Initial.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220405034203_Initial.cs similarity index 95% rename from modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220331065901_Initial.cs rename to modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220405034203_Initial.cs index 82519277b4..6f16fc8f58 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220331065901_Initial.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20220405034203_Initial.cs @@ -59,64 +59,6 @@ namespace OpenIddict.Demo.Server.Migrations table.PrimaryKey("PK_AbpLinkUsers", x => x.Id); }); - migrationBuilder.CreateTable( - name: "AbpOpenIddictApplications", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - ClientId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), - ClientSecret = table.Column(type: "nvarchar(max)", nullable: true), - ConsentType = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), - DisplayName = table.Column(type: "nvarchar(max)", nullable: true), - DisplayNames = table.Column(type: "nvarchar(max)", nullable: true), - Permissions = table.Column(type: "nvarchar(max)", nullable: true), - PostLogoutRedirectUris = table.Column(type: "nvarchar(max)", nullable: true), - Properties = table.Column(type: "nvarchar(max)", nullable: true), - RedirectUris = table.Column(type: "nvarchar(max)", nullable: true), - Requirements = table.Column(type: "nvarchar(max)", nullable: true), - Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), - ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - CreatorId = table.Column(type: "uniqueidentifier", nullable: true), - LastModificationTime = table.Column(type: "datetime2", nullable: true), - LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), - IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), - DeleterId = table.Column(type: "uniqueidentifier", nullable: true), - DeletionTime = table.Column(type: "datetime2", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpOpenIddictApplications", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AbpOpenIddictScopes", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - Description = table.Column(type: "nvarchar(max)", nullable: true), - Descriptions = table.Column(type: "nvarchar(max)", nullable: true), - DisplayName = table.Column(type: "nvarchar(max)", nullable: true), - DisplayNames = table.Column(type: "nvarchar(max)", nullable: true), - Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), - Properties = table.Column(type: "nvarchar(max)", nullable: true), - Resources = table.Column(type: "nvarchar(max)", nullable: true), - ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), - CreationTime = table.Column(type: "datetime2", nullable: false), - CreatorId = table.Column(type: "uniqueidentifier", nullable: true), - LastModificationTime = table.Column(type: "datetime2", nullable: true), - LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), - IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), - DeleterId = table.Column(type: "uniqueidentifier", nullable: true), - DeletionTime = table.Column(type: "datetime2", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AbpOpenIddictScopes", x => x.Id); - }); - migrationBuilder.CreateTable( name: "AbpOrganizationUnits", columns: table => new @@ -280,18 +222,23 @@ namespace OpenIddict.Demo.Server.Migrations }); migrationBuilder.CreateTable( - name: "AbpOpenIddictAuthorizations", + name: "OpenIddictApplications", columns: table => new { Id = table.Column(type: "uniqueidentifier", nullable: false), - ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), - ApplicationId = table.Column(type: "uniqueidentifier", nullable: true), - CreationDate = table.Column(type: "datetime2", nullable: true), + ClientId = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + ClientSecret = table.Column(type: "nvarchar(max)", nullable: true), + ConsentType = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + DisplayName = table.Column(type: "nvarchar(max)", nullable: true), + DisplayNames = table.Column(type: "nvarchar(max)", nullable: true), + Permissions = table.Column(type: "nvarchar(max)", nullable: true), + PostLogoutRedirectUris = table.Column(type: "nvarchar(max)", nullable: true), Properties = table.Column(type: "nvarchar(max)", nullable: true), - Scopes = table.Column(type: "nvarchar(max)", nullable: true), - Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), - Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true), + RedirectUris = table.Column(type: "nvarchar(max)", nullable: true), + Requirements = table.Column(type: "nvarchar(max)", nullable: true), Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), LastModificationTime = table.Column(type: "datetime2", nullable: true), @@ -302,12 +249,34 @@ namespace OpenIddict.Demo.Server.Migrations }, constraints: table => { - table.PrimaryKey("PK_AbpOpenIddictAuthorizations", x => x.Id); - table.ForeignKey( - name: "FK_AbpOpenIddictAuthorizations_AbpOpenIddictApplications_ApplicationId", - column: x => x.ApplicationId, - principalTable: "AbpOpenIddictApplications", - principalColumn: "Id"); + table.PrimaryKey("PK_OpenIddictApplications", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictScopes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Description = table.Column(type: "nvarchar(max)", nullable: true), + Descriptions = table.Column(type: "nvarchar(max)", nullable: true), + DisplayName = table.Column(type: "nvarchar(max)", nullable: true), + DisplayNames = table.Column(type: "nvarchar(max)", nullable: true), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Properties = table.Column(type: "nvarchar(max)", nullable: true), + Resources = table.Column(type: "nvarchar(max)", nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictScopes", x => x.Id); }); migrationBuilder.CreateTable( @@ -493,11 +462,42 @@ namespace OpenIddict.Demo.Server.Migrations }); migrationBuilder.CreateTable( - name: "AbpOpenIddictTokens", + name: "OpenIddictAuthorizations", columns: table => new { Id = table.Column(type: "uniqueidentifier", nullable: false), + ApplicationId = table.Column(type: "uniqueidentifier", nullable: true), + CreationDate = table.Column(type: "datetime2", nullable: true), + Properties = table.Column(type: "nvarchar(max)", nullable: true), + Scopes = table.Column(type: "nvarchar(max)", nullable: true), + Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true), + Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id); + table.ForeignKey( + name: "FK_OpenIddictAuthorizations_OpenIddictApplications_ApplicationId", + column: x => x.ApplicationId, + principalTable: "OpenIddictApplications", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictTokens", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), ApplicationId = table.Column(type: "uniqueidentifier", nullable: true), AuthorizationId = table.Column(type: "uniqueidentifier", nullable: true), CreationDate = table.Column(type: "datetime2", nullable: true), @@ -509,6 +509,8 @@ namespace OpenIddict.Demo.Server.Migrations Status = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), Subject = table.Column(type: "nvarchar(400)", maxLength: 400, nullable: true), Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), CreationTime = table.Column(type: "datetime2", nullable: false), CreatorId = table.Column(type: "uniqueidentifier", nullable: true), LastModificationTime = table.Column(type: "datetime2", nullable: true), @@ -519,16 +521,16 @@ namespace OpenIddict.Demo.Server.Migrations }, constraints: table => { - table.PrimaryKey("PK_AbpOpenIddictTokens", x => x.Id); + table.PrimaryKey("PK_OpenIddictTokens", x => x.Id); table.ForeignKey( - name: "FK_AbpOpenIddictTokens_AbpOpenIddictApplications_ApplicationId", + name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId", column: x => x.ApplicationId, - principalTable: "AbpOpenIddictApplications", + principalTable: "OpenIddictApplications", principalColumn: "Id"); table.ForeignKey( - name: "FK_AbpOpenIddictTokens_AbpOpenIddictAuthorizations_AuthorizationId", + name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId", column: x => x.AuthorizationId, - principalTable: "AbpOpenIddictAuthorizations", + principalTable: "OpenIddictAuthorizations", principalColumn: "Id"); }); @@ -546,42 +548,6 @@ namespace OpenIddict.Demo.Server.Migrations unique: true, filter: "[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); - migrationBuilder.CreateIndex( - name: "IX_AbpOpenIddictApplications_ClientId", - table: "AbpOpenIddictApplications", - column: "ClientId", - unique: true, - filter: "[ClientId] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_AbpOpenIddictAuthorizations_ApplicationId_Status_Subject_Type", - table: "AbpOpenIddictAuthorizations", - columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpOpenIddictScopes_Name", - table: "AbpOpenIddictScopes", - column: "Name", - unique: true, - filter: "[Name] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_AbpOpenIddictTokens_ApplicationId_Status_Subject_Type", - table: "AbpOpenIddictTokens", - columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); - - migrationBuilder.CreateIndex( - name: "IX_AbpOpenIddictTokens_AuthorizationId", - table: "AbpOpenIddictTokens", - column: "AuthorizationId"); - - migrationBuilder.CreateIndex( - name: "IX_AbpOpenIddictTokens_ReferenceId", - table: "AbpOpenIddictTokens", - column: "ReferenceId", - unique: true, - filter: "[ReferenceId] IS NOT NULL"); - migrationBuilder.CreateIndex( name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", table: "AbpOrganizationUnitRoles", @@ -685,6 +651,42 @@ namespace OpenIddict.Demo.Server.Migrations name: "IX_AbpUsers_UserName", table: "AbpUsers", column: "UserName"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictApplications_ClientId", + table: "OpenIddictApplications", + column: "ClientId", + unique: true, + filter: "[ClientId] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictAuthorizations_ApplicationId_Status_Subject_Type", + table: "OpenIddictAuthorizations", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictScopes_Name", + table: "OpenIddictScopes", + column: "Name", + unique: true, + filter: "[Name] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ApplicationId_Status_Subject_Type", + table: "OpenIddictTokens", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_AuthorizationId", + table: "OpenIddictTokens", + column: "AuthorizationId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ReferenceId", + table: "OpenIddictTokens", + column: "ReferenceId", + unique: true, + filter: "[ReferenceId] IS NOT NULL"); } protected override void Down(MigrationBuilder migrationBuilder) @@ -698,12 +700,6 @@ namespace OpenIddict.Demo.Server.Migrations migrationBuilder.DropTable( name: "AbpLinkUsers"); - migrationBuilder.DropTable( - name: "AbpOpenIddictScopes"); - - migrationBuilder.DropTable( - name: "AbpOpenIddictTokens"); - migrationBuilder.DropTable( name: "AbpOrganizationUnitRoles"); @@ -738,7 +734,10 @@ namespace OpenIddict.Demo.Server.Migrations name: "AbpUserTokens"); migrationBuilder.DropTable( - name: "AbpOpenIddictAuthorizations"); + name: "OpenIddictScopes"); + + migrationBuilder.DropTable( + name: "OpenIddictTokens"); migrationBuilder.DropTable( name: "AbpTenants"); @@ -753,7 +752,10 @@ namespace OpenIddict.Demo.Server.Migrations name: "AbpUsers"); migrationBuilder.DropTable( - name: "AbpOpenIddictApplications"); + name: "OpenIddictAuthorizations"); + + migrationBuilder.DropTable( + name: "OpenIddictApplications"); } } } diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs index d0cbf7a47d..f438960970 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs @@ -755,7 +755,7 @@ namespace OpenIddict.Demo.Server.Migrations .IsUnique() .HasFilter("[ClientId] IS NOT NULL"); - b.ToTable("AbpOpenIddictApplications", (string)null); + b.ToTable("OpenIddictApplications", (string)null); }); modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => @@ -792,6 +792,10 @@ namespace OpenIddict.Demo.Server.Migrations .HasColumnType("datetime2") .HasColumnName("DeletionTime"); + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") @@ -828,7 +832,7 @@ namespace OpenIddict.Demo.Server.Migrations b.HasIndex("ApplicationId", "Status", "Subject", "Type"); - b.ToTable("AbpOpenIddictAuthorizations", (string)null); + b.ToTable("OpenIddictAuthorizations", (string)null); }); modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => @@ -905,7 +909,7 @@ namespace OpenIddict.Demo.Server.Migrations .IsUnique() .HasFilter("[Name] IS NOT NULL"); - b.ToTable("AbpOpenIddictScopes", (string)null); + b.ToTable("OpenIddictScopes", (string)null); }); modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => @@ -948,6 +952,10 @@ namespace OpenIddict.Demo.Server.Migrations b.Property("ExpirationDate") .HasColumnType("datetime2"); + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + b.Property("IsDeleted") .ValueGeneratedOnAdd() .HasColumnType("bit") @@ -997,7 +1005,7 @@ namespace OpenIddict.Demo.Server.Migrations b.HasIndex("ApplicationId", "Status", "Subject", "Type"); - b.ToTable("AbpOpenIddictTokens", (string)null); + b.ToTable("OpenIddictTokens", (string)null); }); modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => @@ -1235,18 +1243,18 @@ namespace OpenIddict.Demo.Server.Migrations modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => { b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) - .WithMany("Authorizations") + .WithMany() .HasForeignKey("ApplicationId"); }); modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => { b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) - .WithMany("Tokens") + .WithMany() .HasForeignKey("ApplicationId"); b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) - .WithMany("Tokens") + .WithMany() .HasForeignKey("AuthorizationId"); }); @@ -1282,18 +1290,6 @@ namespace OpenIddict.Demo.Server.Migrations b.Navigation("Roles"); }); - modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => - { - b.Navigation("Authorizations"); - - b.Navigation("Tokens"); - }); - - modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => - { - b.Navigation("Tokens"); - }); - modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => { b.Navigation("ConnectionStrings"); diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddict.Demo.Server.csproj b/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddict.Demo.Server.csproj index f3ab960524..d2af33ab2e 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddict.Demo.Server.csproj +++ b/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddict.Demo.Server.csproj @@ -4,6 +4,7 @@ net6.0 enable enable + OpenIddict.Demo.Server1 diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs b/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs index a6b7261da2..3efe112ab2 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs @@ -1,5 +1,7 @@ -using Microsoft.AspNetCore.Authentication; +using System.Text; +using Microsoft.AspNetCore.Authentication; using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; using OpenIddict.Abstractions; using OpenIddict.Demo.Server.EntityFrameworkCore; using Volo.Abp; @@ -75,8 +77,24 @@ namespace OpenIddict.Demo.Server; )] public class OpenIddictServerModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(builder => + { + //https://documentation.openiddict.com/configuration/token-formats.html#disabling-jwt-access-token-encryption + //https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html + builder.AddSigningKey(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_C40DBB176E78"))); + builder.AddEncryptionKey(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_87E33FC57D80"))); + }); + } + public override void ConfigureServices(ServiceConfigurationContext context) { + Configure(options => + { + options.AddDevelopmentEncryptionAndSigningCertificate = false; + }); + context.Services.AddAbpDbContext(options => { options.AddDefaultRepositories(includeAllEntities: true); diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/Program.cs b/modules/openiddict/app/OpenIddict.Demo.Server/Program.cs index eb528c5933..a990d3dbc5 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/Program.cs +++ b/modules/openiddict/app/OpenIddict.Demo.Server/Program.cs @@ -1,3 +1,5 @@ +using System.Text; +using Microsoft.IdentityModel.Tokens; using OpenIddict.Demo.Server; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; using Volo.Abp.Localization; @@ -35,6 +37,10 @@ builder.Services.AddAuthentication() options.Audience = "AbpAPIResource"; options.MapInboundClaims = false; + + // See OpenIddictServerModule`s PreConfigureServices method. + options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_C40DBB176E78")); + options.TokenValidationParameters.TokenDecryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_87E33FC57D80")); }); await builder.AddApplicationAsync(); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/AbpOpenIddictQueryableExtensions.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo/Abp/OpenIddict/AbpOpenIddictQueryableExtensions.cs similarity index 92% rename from modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/AbpOpenIddictQueryableExtensions.cs rename to modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo/Abp/OpenIddict/AbpOpenIddictQueryableExtensions.cs index 2bea2427e1..1a960c18b8 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/AbpOpenIddictQueryableExtensions.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo/Abp/OpenIddict/AbpOpenIddictQueryableExtensions.cs @@ -3,7 +3,7 @@ using JetBrains.Annotations; namespace Volo.Abp.OpenIddict; -internal static class AbpOpenIddictQueryableExtensions +public static class AbpOpenIddictQueryableExtensions { public static TQueryable SkipIf([NotNull] this TQueryable query, bool condition, int count) where TQueryable : IQueryable diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDbProperties.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDbProperties.cs index 1de1a4de15..935fba20a5 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDbProperties.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDbProperties.cs @@ -2,9 +2,9 @@ public static class AbpOpenIddictDbProperties { - public static string DbTablePrefix { get; set; } = "AbpOpenIddict"; //TODO: Rename to "OpenIddict" + public static string DbTablePrefix { get; set; } = "OpenIddict"; public static string DbSchema { get; set; } = null; - public const string ConnectionStringName = "AbpOpenIddict"; //TODO: Rename to "OpenIddict" + public const string ConnectionStringName = "OpenIddict"; } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs index 0812a45d5b..0c3ec3b11b 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/AbpOpenIddictDomainModule.cs @@ -70,13 +70,12 @@ public class AbpOpenIddictDomainModule : AbpModule .SetDefaultScopeEntity() .SetDefaultTokenEntity(); + builder.DisableEntityCaching(); + services.ExecutePreConfiguredActions(builder); }) .AddServer(builder => { - // Access token encryption can only be disabled when using JWT tokens. - builder.DisableAccessTokenEncryption(); //TODO: Should we always disable this? - builder .SetAuthorizationEndpointUris("/connect/authorize") // /.well-known/oauth-authorization-server diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs index c9430d9fad..0205238cfc 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/AbpOpenIddictApplicationStore.cs @@ -16,11 +16,6 @@ using Volo.Abp.Uow; namespace Volo.Abp.OpenIddict.Applications; -//https://github.com/abpframework/abp/pull/12094 -[ExposeServices( - typeof(IOpenIddictApplicationStore), - typeof(AbpOpenIddictApplicationStore) -)] public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase, IOpenIddictApplicationStore, IScopedDependency { protected IOpenIddictTokenRepository TokenRepository { get; } @@ -60,16 +55,7 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase x.Tokens).ToList(); - if (tokens.Any()) - { - await TokenRepository.DeleteManyAsync(tokens, cancellationToken: cancellationToken); - } + await TokenRepository.DeleteManyByApplicationIdAsync(application.Id, cancellationToken: cancellationToken); await Repository.DeleteAsync(application, cancellationToken: cancellationToken); @@ -81,21 +67,21 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase FindByClientIdAsync(string identifier, CancellationToken cancellationToken) { Check.NotNullOrEmpty(identifier, nameof(identifier)); - return await Repository.FindByClientIdAsync(identifier, includeDetails: true, cancellationToken: cancellationToken); + return await Repository.FindByClientIdAsync(identifier, cancellationToken: cancellationToken); } public async IAsyncEnumerable FindByPostLogoutRedirectUriAsync(string address, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(address, nameof(address)); - var applications = await Repository.FindByPostLogoutRedirectUriAsync(address, includeDetails: true, cancellationToken); + var applications = await Repository.FindByPostLogoutRedirectUriAsync(address, cancellationToken); foreach (var application in applications) { @@ -111,7 +97,7 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase GetClientIdAsync(OpenIddictApplication application, CancellationToken cancellationToken) @@ -400,7 +386,7 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) { - var applications = await Repository.ListAsync(count, offset, includeDetails: true, cancellationToken); + var applications = await Repository.ListAsync(count, offset, cancellationToken); foreach (var application in applications) { yield return application; @@ -411,7 +397,7 @@ public class AbpOpenIddictApplicationStore : AbpOpenIddictStoreBase CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default); - Task FindByClientIdAsync(string clientId, bool includeDetails = true, CancellationToken cancellationToken = default); + Task FindByClientIdAsync(string clientId, CancellationToken cancellationToken = default); - Task> FindByPostLogoutRedirectUriAsync(string address, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken = default); - Task> FindByRedirectUriAsync(string address, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindByRedirectUriAsync(string address, CancellationToken cancellationToken = default); - Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default); + Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default); - Task> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplication.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplication.cs index 681038c8f7..fc477a4714 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplication.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Applications/OpenIddictApplication.cs @@ -1,18 +1,10 @@ using System; -using System.Collections.Generic; using Volo.Abp.Domain.Entities.Auditing; -using Volo.Abp.OpenIddict.Authorizations; -using Volo.Abp.OpenIddict.Tokens; namespace Volo.Abp.OpenIddict.Applications; public class OpenIddictApplication : FullAuditedAggregateRoot { - /// - /// Gets the list of the authorizations associated with this application. - /// - public virtual ICollection Authorizations { get; } = new HashSet(); - /// /// Gets or sets the client identifier associated with the current application. /// @@ -72,11 +64,6 @@ public class OpenIddictApplication : FullAuditedAggregateRoot /// public virtual string Requirements { get; set; } - /// - /// Gets the list of the tokens associated with this application. - /// - public virtual ICollection Tokens { get; } = new HashSet(); - /// /// Gets or sets the application type associated with the current application. /// diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs index a96f109d13..dfd67a8877 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/AbpOpenIddictAuthorizationStore.cs @@ -16,10 +16,6 @@ using Volo.Abp.Uow; namespace Volo.Abp.OpenIddict.Authorizations; -[ExposeServices( - typeof(IOpenIddictAuthorizationStore), - typeof(AbpOpenIddictAuthorizationStore) -)] public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase, IOpenIddictAuthorizationStore, IScopedDependency { protected IOpenIddictApplicationRepository ApplicationRepository { get; } @@ -62,10 +58,7 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase FindBySubjectAsync(string subject, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(subject, nameof(subject)); - var authorizations = await Repository.FindBySubjectAsync(subject, includeDetails: true, cancellationToken); + var authorizations = await Repository.FindBySubjectAsync(subject, cancellationToken); foreach (var authorization in authorizations) { yield return authorization; @@ -172,7 +165,7 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase GetCreationDateAsync(OpenIddictAuthorization authorization, CancellationToken cancellationToken) @@ -294,7 +287,7 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) { - var authorizations = await Repository.ListAsync(count, offset, includeDetails: true, cancellationToken); + var authorizations = await Repository.ListAsync(count, offset, cancellationToken); foreach (var authorization in authorizations) { yield return authorization; @@ -303,7 +296,7 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase ListAsync(Func, TState, IQueryable> query, TState state, [EnumeratorCancellation] CancellationToken cancellationToken) { - var authorizations = await Repository.ListAsync(query, state, includeDetails: true, cancellationToken); + var authorizations = await Repository.ListAsync(query, state, cancellationToken); foreach (var authorization in authorizations) { yield return authorization; @@ -320,7 +313,7 @@ public class AbpOpenIddictAuthorizationStore : AbpOpenIddictStoreBase CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default); - Task> FindAsync(string subject, Guid client, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default); - Task> FindAsync(string subject, Guid client, string status, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindAsync(string subject, Guid client, string status, CancellationToken cancellationToken = default); - Task> FindAsync(string subject, Guid client, string status, string type, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindAsync(string subject, Guid client, string status, string type, CancellationToken cancellationToken = default); - Task> FindByApplicationIdAsync(Guid applicationId, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindByApplicationIdAsync(Guid applicationId, CancellationToken cancellationToken = default); - Task FindByIdAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default); + Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default); - Task> FindBySubjectAsync(string subject, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default); - Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default); + Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default); - Task> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> GetPruneListAsync(DateTime date, int count, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorization.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorization.cs index fe53fb11a8..7dbb31aace 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorization.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorization.cs @@ -1,17 +1,10 @@ using System; -using System.Collections.Generic; -using Volo.Abp.Auditing; -using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities.Auditing; -using Volo.Abp.OpenIddict.Tokens; namespace Volo.Abp.OpenIddict.Authorizations; -public class OpenIddictAuthorization : FullAuditedEntity, IHasConcurrencyStamp +public class OpenIddictAuthorization : FullAuditedAggregateRoot { - [DisableAuditing] - public virtual string ConcurrencyStamp { get; set; } - /// /// Gets or sets the application associated with the current authorization. /// @@ -44,11 +37,6 @@ public class OpenIddictAuthorization : FullAuditedEntity, IHasConcurrencyS /// public virtual string Subject { get; set; } - /// - /// Gets the list of tokens associated with the current authorization. - /// - public virtual ICollection Tokens { get; } = new HashSet(); - /// /// Gets or sets the type of the current authorization. /// diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeStore.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeStore.cs index 56c3b20375..c538c21170 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeStore.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeStore.cs @@ -14,10 +14,6 @@ using Volo.Abp.Uow; namespace Volo.Abp.OpenIddict.Scopes; -[ExposeServices( - typeof(IOpenIddictScopeStore), - typeof(AbpOpenIddictScopeStore) -)] public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase, IOpenIddictScopeStore, IScopedDependency { public AbpOpenIddictScopeStore( @@ -59,14 +55,14 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase FindByNameAsync(string name, CancellationToken cancellationToken) { Check.NotNullOrEmpty(name, nameof(name)); - return await Repository.FindByNameAsync(name, includeDetails: true, cancellationToken); + return await Repository.FindByNameAsync(name, cancellationToken); } public virtual async IAsyncEnumerable FindByNamesAsync(ImmutableArray names, [EnumeratorCancellation] CancellationToken cancellationToken) @@ -77,7 +73,7 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) { - return await Repository.GetAsync(query, state, includeDetails: true, cancellationToken); + return await Repository.GetAsync(query, state, cancellationToken); } public virtual ValueTask GetDescriptionAsync(OpenIddictScope scope, CancellationToken cancellationToken) @@ -288,7 +284,7 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) { - var scopes = await Repository.ListAsync(count, offset, includeDetails: true, cancellationToken); + var scopes = await Repository.ListAsync(count, offset, cancellationToken); foreach (var scope in scopes) { yield return scope; @@ -299,7 +295,7 @@ public class AbpOpenIddictScopeStore : AbpOpenIddictStoreBase CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default); - Task FindByIdAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default); + Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default); - Task FindByNameAsync(string name, bool includeDetails = true, CancellationToken cancellationToken = default); + Task FindByNameAsync(string name, CancellationToken cancellationToken = default); - Task> FindByNamesAsync(string[] names, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindByNamesAsync(string[] names, CancellationToken cancellationToken = default); - Task> FindByResourceAsync(string resource, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindByResourceAsync(string resource, CancellationToken cancellationToken = default); - Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default); + Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default); - Task> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenStore.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenStore.cs index 71345e4087..3a22e727f5 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenStore.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/AbpOpenIddictTokenStore.cs @@ -16,10 +16,6 @@ using Volo.Abp.Uow; namespace Volo.Abp.OpenIddict.Tokens; -[ExposeServices( - typeof(IOpenIddictTokenStore), - typeof(AbpOpenIddictTokenStore) -)] public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase, IOpenIddictTokenStore, IScopedDependency { protected IOpenIddictApplicationRepository ApplicationRepository { get; } @@ -66,7 +62,7 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase FindByReferenceIdAsync(string identifier, CancellationToken cancellationToken) { Check.NotNullOrEmpty(identifier, nameof(identifier)); - return await Repository.FindByReferenceIdAsync(identifier, includeDetails: true, cancellationToken); + return await Repository.FindByReferenceIdAsync(identifier, cancellationToken); } public virtual async IAsyncEnumerable FindBySubjectAsync(string subject, [EnumeratorCancellation] CancellationToken cancellationToken) { Check.NotNullOrEmpty(subject, nameof(subject)); - var tokens = await Repository.FindBySubjectAsync(subject, includeDetails: true, cancellationToken); + var tokens = await Repository.FindBySubjectAsync(subject, cancellationToken); foreach (var token in tokens) { yield return token; @@ -160,7 +156,7 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase GetAuthorizationIdAsync(OpenIddictToken token, CancellationToken cancellationToken) @@ -295,7 +291,7 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase ListAsync(int? count, int? offset, [EnumeratorCancellation] CancellationToken cancellationToken) { - var tokens = await Repository.ListAsync(count, offset, includeDetails: true, cancellationToken); + var tokens = await Repository.ListAsync(count, offset, cancellationToken); foreach (var token in tokens) { yield return token; @@ -306,7 +302,7 @@ public class AbpOpenIddictTokenStore : AbpOpenIddictStoreBase { + Task DeleteManyByApplicationIdAsync(Guid applicationId, bool autoSave = false, CancellationToken cancellationToken = default); + + Task DeleteManyByAuthorizationIdAsync(Guid authorizationId, bool autoSave = false, CancellationToken cancellationToken = default); + Task CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default); - Task> FindAsync(string subject, Guid client, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default); - Task> FindAsync(string subject, Guid client, string status, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindAsync(string subject, Guid client, string status, CancellationToken cancellationToken = default); - Task> FindAsync(string subject, Guid client, string status, string type, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindAsync(string subject, Guid client, string status, string type, CancellationToken cancellationToken = default); - Task> FindByApplicationIdAsync(Guid applicationId, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindByApplicationIdAsync(Guid applicationId, CancellationToken cancellationToken = default); - Task> FindByAuthorizationIdAsync(Guid authorizationId, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindByAuthorizationIdAsync(Guid authorizationId, CancellationToken cancellationToken = default); - Task FindByIdAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default); + Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default); - Task FindByReferenceIdAsync(string referenceId, bool includeDetails = true, CancellationToken cancellationToken = default); + Task FindByReferenceIdAsync(string referenceId, CancellationToken cancellationToken = default); - Task> FindBySubjectAsync(string subject, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default); - Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default); + Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default); - Task> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default); - Task> GetPruneListAsync(DateTime date, int count, bool includeDetails = true, CancellationToken cancellationToken = default); + Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictToken.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictToken.cs index 3dd7da3233..eb49651e2f 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictToken.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/OpenIddictToken.cs @@ -1,27 +1,10 @@ using System; -using JetBrains.Annotations; -using Volo.Abp.Auditing; -using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities.Auditing; -using Volo.Abp.OpenIddict.Applications; -using Volo.Abp.OpenIddict.Authorizations; namespace Volo.Abp.OpenIddict.Tokens; -/* TODO: Reconsider the entity designs - * - * Entity structure seems incorrectly designed: - * `OpenIddictToken` is an entity (not aggregate root) but have its own repository. - * `OpenIddictAuthorization` is also same. - * If they have repositories, they should be aggregate roots and should not be used as navigation properties in other entities (e.g. `OpenIddictApplication`). - * I think this will be the correct way since they are independently queried from database. - */ - -public class OpenIddictToken : FullAuditedEntity, IHasConcurrencyStamp +public class OpenIddictToken : FullAuditedAggregateRoot { - [DisableAuditing] - public virtual string ConcurrencyStamp { get; set; } - /// /// Gets or sets the application associated with the current token. /// diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/TokenCleanupBackgroundWorker.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/TokenCleanupBackgroundWorker.cs index 440ad60896..c89ac256d0 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/TokenCleanupBackgroundWorker.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Tokens/TokenCleanupBackgroundWorker.cs @@ -19,12 +19,6 @@ public class TokenCleanupBackgroundWorker : AsyncPeriodicBackgroundWorkerBase protected async override Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) { - /* TODO: Should we use distributed locking here? - * Because, multiple instances of the application may work in parallel, and only one - * of them should work in a time. If you can't obtain the lock, it is good to wait for a longer time. - * I suggest to check https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/InboxProcessor.cs - * for a good implementation, then apply a similar principle here. - */ await workerContext .ServiceProvider .GetRequiredService() diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/AbpOpenIddictEfCoreQueryableExtensions.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/AbpOpenIddictEfCoreQueryableExtensions.cs deleted file mode 100644 index e4d7cbd9e3..0000000000 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/AbpOpenIddictEfCoreQueryableExtensions.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Linq; -using Microsoft.EntityFrameworkCore; -using Volo.Abp.OpenIddict.Applications; -using Volo.Abp.OpenIddict.Authorizations; - -namespace Volo.Abp.OpenIddict; - -public static class AbpOpenIddictEfCoreQueryableExtensions -{ - public static IQueryable IncludeDetails(this IQueryable queryable, bool include = true) - { - if (!include) - { - return queryable; - } - - return queryable - .Include(x => x.Authorizations).ThenInclude(x => x.Tokens) - .Include(x => x.Tokens); - } - - public static IQueryable IncludeDetails(this IQueryable queryable, bool include = true) - { - if (!include) - { - return queryable; - } - - return queryable.Include(x => x.Tokens); - } -} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/AbpOpenIddictQueryableExtensions.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/AbpOpenIddictQueryableExtensions.cs deleted file mode 100644 index 2bea2427e1..0000000000 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/AbpOpenIddictQueryableExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Linq; -using JetBrains.Annotations; - -namespace Volo.Abp.OpenIddict; - -internal static class AbpOpenIddictQueryableExtensions -{ - public static TQueryable SkipIf([NotNull] this TQueryable query, bool condition, int count) - where TQueryable : IQueryable - { - Check.NotNull(query, nameof(query)); - - return condition - ? (TQueryable)query.Skip(count) - : query; - } - - public static TQueryable TakeIf([NotNull] this TQueryable query, bool condition, int count) - where TQueryable : IQueryable - { - Check.NotNull(query, nameof(query)); - - return condition - ? (TQueryable)query.Take(count) - : query; - } -} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/EfCoreOpenIddictApplicationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/EfCoreOpenIddictApplicationRepository.cs new file mode 100644 index 0000000000..c4300d3fff --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/EfCoreOpenIddictApplicationRepository.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.OpenIddict.EntityFrameworkCore; + +namespace Volo.Abp.OpenIddict.Applications; + +public class EfCoreOpenIddictApplicationRepository : EfCoreRepository, IOpenIddictApplicationRepository +{ + public EfCoreOpenIddictApplicationRepository(IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + + } + + public virtual async Task CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) + { + return await query(await GetDbSetAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task FindByClientIdAsync(string clientId, CancellationToken cancellationToken = default) + { + return await (await GetDbSetAsync()) + .FirstOrDefaultAsync(x => x.ClientId == clientId, GetCancellationToken(cancellationToken)); + } + + public virtual async Task> FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken = default) + { + return await (await GetDbSetAsync()) + .Where(x => x.PostLogoutRedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task> FindByRedirectUriAsync(string address, CancellationToken cancellationToken = default) + { + return await (await GetDbSetAsync()) + .Where(x => x.RedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) + { + return await query(await GetDbSetAsync(), state) + .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) + { + return await (await GetDbSetAsync()) + .OrderBy(x => x.Id) + .SkipIf>(offset.HasValue, offset.Value) + .TakeIf>(count.HasValue, count.Value) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) + { + return await query(await GetDbSetAsync(), state) + .ToListAsync(GetCancellationToken(cancellationToken)); + } +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/OpenIddictApplicationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/OpenIddictApplicationRepository.cs deleted file mode 100644 index 451cb1692d..0000000000 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Applications/OpenIddictApplicationRepository.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Volo.Abp.Domain.Repositories.EntityFrameworkCore; -using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.OpenIddict.EntityFrameworkCore; - -namespace Volo.Abp.OpenIddict.Applications; - -public class OpenIddictApplicationRepository : EfCoreRepository, IOpenIddictApplicationRepository -{ - public OpenIddictApplicationRepository(IDbContextProvider dbContextProvider) - : base(dbContextProvider) - { - - } - - public virtual async Task CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) - { - return await query(await GetDbSetAsync()).LongCountAsync(cancellationToken); - } - - public virtual async Task FindByClientIdAsync(string clientId, bool includeDetails = true, CancellationToken cancellationToken = default) - { - return await (await GetDbSetAsync()) - .IncludeDetails(includeDetails) - .FirstOrDefaultAsync(x => x.ClientId == clientId, cancellationToken); - } - - public virtual async Task> FindByPostLogoutRedirectUriAsync(string address, bool includeDetails = true, CancellationToken cancellationToken = default) - { - return await (await GetDbSetAsync()) - .IncludeDetails(includeDetails) - .Where(x => x.PostLogoutRedirectUris.Contains(address)).ToListAsync(cancellationToken); - } - - public virtual async Task> FindByRedirectUriAsync(string address, bool includeDetails = true, CancellationToken cancellationToken = default) - { - return await (await GetDbSetAsync()) - .IncludeDetails(includeDetails) - .Where(x => x.RedirectUris.Contains(address)).ToListAsync(cancellationToken); - } - - public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) - { - return await query((await GetDbSetAsync()) - .IncludeDetails(includeDetails), state) - .FirstOrDefaultAsync(cancellationToken); - } - - public virtual async Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default) - { - return await (await GetDbSetAsync()) - .IncludeDetails(includeDetails) - .OrderBy(x => x.Id) - .SkipIf>(offset.HasValue, offset.Value) - .TakeIf>(count.HasValue, count.Value) - .ToListAsync(cancellationToken); - } - - public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) - { - return await query((await GetDbSetAsync()) - .IncludeDetails(includeDetails), state) - .ToListAsync(cancellationToken); - } - - [Obsolete("Use WithDetailsAsync method.")] - public override IQueryable WithDetails() - { - return GetQueryable().IncludeDetails(); - } - - public async override Task> WithDetailsAsync() - { - return (await GetQueryableAsync()).IncludeDetails(); - } -} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Authorizations/EfCoreOpenIddictAuthorizationRepository.cs similarity index 51% rename from modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationRepository.cs rename to modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Authorizations/EfCoreOpenIddictAuthorizationRepository.cs index 09bfec1385..b61770c3e1 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Authorizations/EfCoreOpenIddictAuthorizationRepository.cs @@ -11,9 +11,9 @@ using Volo.Abp.OpenIddict.EntityFrameworkCore; namespace Volo.Abp.OpenIddict.Authorizations; -public class OpenIddictAuthorizationRepository : EfCoreRepository, IOpenIddictAuthorizationRepository +public class EfCoreOpenIddictAuthorizationRepository : EfCoreRepository, IOpenIddictAuthorizationRepository { - public OpenIddictAuthorizationRepository(IDbContextProvider dbContextProvider) + public EfCoreOpenIddictAuthorizationRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) { @@ -21,67 +21,59 @@ public class OpenIddictAuthorizationRepository : EfCoreRepository CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) { - return await query(await GetQueryableAsync()).LongCountAsync(cancellationToken); + return await query(await GetQueryableAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) - .IncludeDetails(includeDetails) .Where(x => x.Subject == subject && x.ApplicationId == client) - .ToListAsync(cancellationToken); + .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, string status, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, string status, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) - .IncludeDetails(includeDetails) .Where(x => x.Subject == subject && x.Status == status && x.ApplicationId == client) - .ToListAsync(cancellationToken); + .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, string status, string type, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, string status, string type, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) - .IncludeDetails(includeDetails) .Where(x => x.Subject == subject && x.Status == status && x.Type == type && x.ApplicationId == client) - .ToListAsync(cancellationToken); + .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByApplicationIdAsync(Guid applicationId, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindByApplicationIdAsync(Guid applicationId, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) - .IncludeDetails(includeDetails) .Where(x => x.ApplicationId == applicationId) - .ToListAsync(cancellationToken); + .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task FindByIdAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) - .IncludeDetails(includeDetails) - .FirstOrDefaultAsync(x => x.Id == id, cancellationToken); + .FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } - public virtual async Task> FindBySubjectAsync(string subject, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) - .IncludeDetails(includeDetails) .Where(x => x.Subject == subject) - .ToListAsync(cancellationToken); + .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query((await GetDbSetAsync()) - .IncludeDetails(includeDetails), state) - .FirstOrDefaultAsync(cancellationToken); + return await query(await GetDbSetAsync(), state) + .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { var query = (await GetDbSetAsync()) - .IncludeDetails(includeDetails) .OrderBy(authorization => authorization.Id!) .AsTracking(); @@ -95,35 +87,24 @@ public class OpenIddictAuthorizationRepository : EfCoreRepository> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query((await GetDbSetAsync()) - .IncludeDetails(includeDetails), state) - .ToListAsync(cancellationToken); + return await query(await GetDbSetAsync(), state) + .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> GetPruneListAsync(DateTime date, int count, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default) { + var tokenQueryable = (await GetDbContextAsync()).Tokens.AsQueryable(); return await (await GetDbSetAsync()) - .IncludeDetails(includeDetails) .Where(x => x.CreationDate < date) - .Where(x => x.Status != OpenIddictConstants.Statuses.Valid || (x.Type == OpenIddictConstants.AuthorizationTypes.AdHoc && !x.Tokens.Any())) + .Where(x => x.Status != OpenIddictConstants.Statuses.Valid || + (x.Type == OpenIddictConstants.AuthorizationTypes.AdHoc && tokenQueryable.Any(t => t.AuthorizationId == x.Id))) .OrderBy(x => x.Id) .Take(count) - .ToListAsync(cancellationToken); - } - - [Obsolete("Use WithDetailsAsync method.")] - public override IQueryable WithDetails() - { - return GetQueryable().IncludeDetails(); - } - - public async override Task> WithDetailsAsync() - { - return (await GetQueryableAsync()).IncludeDetails(); + .ToListAsync(GetCancellationToken(cancellationToken)); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/AbpOpenIddictEntityFrameworkCoreModule.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/AbpOpenIddictEntityFrameworkCoreModule.cs index fcd5903efe..9ef08d5f2e 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/AbpOpenIddictEntityFrameworkCoreModule.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/AbpOpenIddictEntityFrameworkCoreModule.cs @@ -20,10 +20,10 @@ public class AbpOpenIddictEntityFrameworkCoreModule : AbpModule { options.AddDefaultRepositories(); - options.AddRepository(); - options.AddRepository(); - options.AddRepository(); - options.AddRepository(); + options.AddRepository(); + options.AddRepository(); + options.AddRepository(); + options.AddRepository(); }); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictDbContextModelCreatingExtensions.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictDbContextModelCreatingExtensions.cs index 7a198882d0..f03203b155 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictDbContextModelCreatingExtensions.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/EntityFrameworkCore/OpenIddictDbContextModelCreatingExtensions.cs @@ -38,16 +38,6 @@ public static class OpenIddictDbContextModelCreatingExtensions b.Property(x => x.Type) .HasMaxLength(OpenIddictApplicationConsts.TypeMaxLength); - b.HasMany(x => x.Authorizations) - .WithOne() - .HasForeignKey(x => x.ApplicationId) - .IsRequired(required: false); - - b.HasMany(x => x.Tokens) - .WithOne() - .HasForeignKey(x => x.ApplicationId) - .IsRequired(required: false); - b.ApplyObjectExtensionMappings(); }); @@ -74,10 +64,7 @@ public static class OpenIddictDbContextModelCreatingExtensions b.Property(x => x.Type) .HasMaxLength(OpenIddictAuthorizationConsts.TypeMaxLength); - b.HasMany(x => x.Tokens) - .WithOne() - .HasForeignKey(x => x.AuthorizationId) - .IsRequired(required: false); + b.HasOne().WithMany().HasForeignKey(x => x.ApplicationId).IsRequired(false); b.ApplyObjectExtensionMappings(); }); @@ -126,6 +113,9 @@ public static class OpenIddictDbContextModelCreatingExtensions b.Property(x => x.Type) .HasMaxLength(OpenIddictTokenConsts.TypeMaxLength); + b.HasOne().WithMany().HasForeignKey(x => x.ApplicationId).IsRequired(false); + b.HasOne().WithMany().HasForeignKey(x => x.AuthorizationId).IsRequired(false); + b.ApplyObjectExtensionMappings(); }); diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/OpenIddictScopeRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs similarity index 61% rename from modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/OpenIddictScopeRepository.cs rename to modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs index b7bae9af4e..73537cd7c8 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/OpenIddictScopeRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Scopes/EfCoreOpenIddictScopeRepository.cs @@ -10,9 +10,9 @@ using Volo.Abp.OpenIddict.EntityFrameworkCore; namespace Volo.Abp.OpenIddict.Scopes; -public class OpenIddictScopeRepository : EfCoreRepository, IOpenIddictScopeRepository +public class EfCoreOpenIddictScopeRepository : EfCoreRepository, IOpenIddictScopeRepository { - public OpenIddictScopeRepository(IDbContextProvider dbContextProvider) + public EfCoreOpenIddictScopeRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) { @@ -20,45 +20,45 @@ public class OpenIddictScopeRepository : EfCoreRepository CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) { - return await query(await GetQueryableAsync()).LongCountAsync(cancellationToken); + return await query(await GetQueryableAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task FindByIdAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).FirstOrDefaultAsync(x => x.Id == id, cancellationToken); + return await (await GetQueryableAsync()).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } - public virtual async Task FindByNameAsync(string name, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task FindByNameAsync(string name, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).FirstOrDefaultAsync(x => x.Name == name, cancellationToken); + return await (await GetQueryableAsync()).FirstOrDefaultAsync(x => x.Name == name, GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByNamesAsync(string[] names, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindByNamesAsync(string[] names, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).Where(x => names.Contains(x.Name)).ToListAsync(cancellationToken); + return await (await GetQueryableAsync()).Where(x => names.Contains(x.Name)).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByResourceAsync(string resource, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindByResourceAsync(string resource, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).Where(x => x.Resources.Contains(resource)).ToListAsync(cancellationToken); + return await (await GetQueryableAsync()).Where(x => x.Resources.Contains(resource)).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetQueryableAsync(), state).FirstOrDefaultAsync(cancellationToken); + return await query(await GetQueryableAsync(), state).FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { return await (await GetQueryableAsync()) .OrderBy(x => x.Id) .SkipIf>(offset.HasValue, offset.Value) .TakeIf>(count.HasValue, count.Value) - .ToListAsync(cancellationToken); + .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetQueryableAsync(), state).ToListAsync(cancellationToken); + return await query(await GetQueryableAsync(), state).ToListAsync(GetCancellationToken(cancellationToken)); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Tokens/EfCoreOpenIddictTokenRepository.cs similarity index 54% rename from modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenRepository.cs rename to modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Tokens/EfCoreOpenIddictTokenRepository.cs index ae595f1ec2..6642899c63 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Tokens/OpenIddictTokenRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.EntityFrameworkCore/Volo/Abp/OpenIddict/Tokens/EfCoreOpenIddictTokenRepository.cs @@ -12,81 +12,98 @@ using Volo.Abp.OpenIddict.EntityFrameworkCore; namespace Volo.Abp.OpenIddict.Tokens; -public class OpenIddictTokenRepository : EfCoreRepository, IOpenIddictTokenRepository +public class EfCoreOpenIddictTokenRepository : EfCoreRepository, IOpenIddictTokenRepository { - public OpenIddictTokenRepository(IDbContextProvider dbContextProvider) + public EfCoreOpenIddictTokenRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) { } + public async Task DeleteManyByApplicationIdAsync(Guid applicationId, bool autoSave = false, CancellationToken cancellationToken = default) + { + var tokens = await (await GetDbSetAsync()) + .Where(x => x.ApplicationId == applicationId) + .ToListAsync(GetCancellationToken(cancellationToken)); + + await DeleteManyAsync(tokens, autoSave, cancellationToken); + } + + public async Task DeleteManyByAuthorizationIdAsync(Guid authorizationId, bool autoSave = false, CancellationToken cancellationToken = default) + { + var tokens = await (await GetDbSetAsync()) + .Where(x => x.AuthorizationId == authorizationId) + .ToListAsync(GetCancellationToken(cancellationToken)); + + await DeleteManyAsync(tokens, autoSave, GetCancellationToken(cancellationToken)); + } + public virtual async Task CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).LongCountAsync(cancellationToken); + return await (await GetQueryableAsync()).LongCountAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).Where(x => x.Subject == subject && x.ApplicationId == client).ToListAsync(cancellationToken); + return await (await GetQueryableAsync()).Where(x => x.Subject == subject && x.ApplicationId == client).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, string status, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, string status, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).Where(x => x.Subject == subject && x.ApplicationId == client && x.Status == status).ToListAsync(cancellationToken); + return await (await GetQueryableAsync()).Where(x => x.Subject == subject && x.ApplicationId == client && x.Status == status).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, string status, string type, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, string status, string type, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).Where(x => x.Subject == subject && x.ApplicationId == client && x.Status == status && x.Type == type).ToListAsync(cancellationToken); + return await (await GetQueryableAsync()).Where(x => x.Subject == subject && x.ApplicationId == client && x.Status == status && x.Type == type).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByApplicationIdAsync(Guid applicationId, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindByApplicationIdAsync(Guid applicationId, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).Where(x => x.ApplicationId == applicationId).ToListAsync(cancellationToken); + return await (await GetQueryableAsync()).Where(x => x.ApplicationId == applicationId).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByAuthorizationIdAsync(Guid authorizationId, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindByAuthorizationIdAsync(Guid authorizationId, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).Where(x => x.AuthorizationId == authorizationId).ToListAsync(cancellationToken); + return await (await GetQueryableAsync()).Where(x => x.AuthorizationId == authorizationId).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task FindByIdAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).FirstOrDefaultAsync(x => x.Id == id, cancellationToken); + return await (await GetQueryableAsync()).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } - public virtual async Task FindByReferenceIdAsync(string referenceId, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task FindByReferenceIdAsync(string referenceId, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).FirstOrDefaultAsync(x => x.ReferenceId == referenceId, cancellationToken); + return await (await GetQueryableAsync()).FirstOrDefaultAsync(x => x.ReferenceId == referenceId, GetCancellationToken(cancellationToken)); } - public virtual async Task> FindBySubjectAsync(string subject, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default) { - return await (await GetQueryableAsync()).Where(x => x.Subject == subject).ToListAsync(cancellationToken); + return await (await GetQueryableAsync()).Where(x => x.Subject == subject).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetQueryableAsync(), state).FirstOrDefaultAsync(cancellationToken); + return await query(await GetQueryableAsync(), state).FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { return await (await GetQueryableAsync()) .OrderBy(x => x.Id) .SkipIf>(offset.HasValue, offset.Value) .TakeIf>(count.HasValue, count.Value) - .ToListAsync(cancellationToken); + .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetQueryableAsync(), state).ToListAsync(cancellationToken); + return await query(await GetQueryableAsync(), state).ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetPruneListAsync(DateTime date, int count, bool includeDetails = true, CancellationToken cancellationToken = default) + public async Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default) { - //TODO: Test & Improve? return await (from token in await GetQueryableAsync() join authorization in (await GetDbContextAsync()).Set().AsQueryable() on token.AuthorizationId equals authorization.Id into ta @@ -97,6 +114,7 @@ public class OpenIddictTokenRepository : EfCoreRepository FindByClientIdAsync(string clientId, bool includeDetails = true, CancellationToken cancellationToken = default) + public async Task FindByClientIdAsync(string clientId, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) .FirstOrDefaultAsync(x => x.ClientId == clientId, cancellationToken); } - public async Task> FindByPostLogoutRedirectUriAsync(string address, bool includeDetails = true, CancellationToken cancellationToken = default) + public async Task> FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.PostLogoutRedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> FindByRedirectUriAsync(string address, bool includeDetails = true, CancellationToken cancellationToken = default) + public async Task> FindByRedirectUriAsync(string address, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.RedirectUris.Contains(address)).ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { return await query(await GetMongoQueryableAsync(cancellationToken), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); } - public async Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default) + public async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) .OrderBy(x => x.Id) @@ -55,7 +55,7 @@ public class MongoOpenIddictApplicationRepository : MongoDbRepository> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { return await query(await GetMongoQueryableAsync(cancellationToken), state).As>().ToListAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs index e8ed66e782..d99ea059f5 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Authorizations/MongoOpenIddictAuthorizationRepository.cs @@ -9,6 +9,7 @@ using OpenIddict.Abstractions; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; using Volo.Abp.OpenIddict.MongoDB; +using Volo.Abp.OpenIddict.Tokens; namespace Volo.Abp.OpenIddict.Authorizations; @@ -23,68 +24,70 @@ public class MongoOpenIddictAuthorizationRepository : MongoDbRepository>().LongCountAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.Subject == subject && x.ApplicationId == client) .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, string status, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, string status, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.Subject == subject && x.Status == status && x.ApplicationId == client) .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, string status, string type, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, string status, string type, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) .Where(x => x.Subject == subject && x.Status == status && x.Type == type && x.ApplicationId == client) .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByApplicationIdAsync(Guid applicationId, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindByApplicationIdAsync(Guid applicationId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.ApplicationId == applicationId).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).Where(x => x.ApplicationId == applicationId).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task FindByIdAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); + return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } - public virtual async Task> FindBySubjectAsync(string subject, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.Subject == subject).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).Where(x => x.Subject == subject).ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetMongoQueryableAsync(cancellationToken), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) .OrderBy(authorization => authorization.Id!) .SkipIf>(offset.HasValue, offset.Value) .TakeIf>(count.HasValue, count.Value) .As>().ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetMongoQueryableAsync(cancellationToken), state).As>().ToListAsync(cancellationToken); + return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> GetPruneListAsync(DateTime date, int count, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)) + var tokenQueryable = await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)); + return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) .Where(x => x.CreationDate < date) - .Where(x => x.Status != OpenIddictConstants.Statuses.Valid || (x.Type == OpenIddictConstants.AuthorizationTypes.AdHoc && !x.Tokens.Any())) + .Where(x => x.Status != OpenIddictConstants.Statuses.Valid || + (x.Type == OpenIddictConstants.AuthorizationTypes.AdHoc && tokenQueryable.Any(t => t.AuthorizationId == x.Id))) .OrderBy(x => x.Id) .Take(count) - .ToListAsync(cancellationToken); + .ToListAsync(GetCancellationToken(cancellationToken)); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs index 7eba36cd21..5e2c7ec884 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Scopes/MongoOpenIddictScopeRepository.cs @@ -22,46 +22,46 @@ public class MongoOpenIddictScopeRepository : MongoDbRepository>().LongCountAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task FindByIdAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } - public virtual async Task FindByNameAsync(string name, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task FindByNameAsync(string name, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Name == name, GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByNamesAsync(string[] names, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindByNamesAsync(string[] names, CancellationToken cancellationToken = default) { return await Queryable.Where((await GetMongoQueryableAsync(cancellationToken)), x => names.Contains(x.Name)) .As>() .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByResourceAsync(string resource, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindByResourceAsync(string resource, CancellationToken cancellationToken = default) { return await Queryable.Where((await GetMongoQueryableAsync(cancellationToken)), x => x.Resources.Contains(resource)) .As>() .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); } - public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetMongoQueryableAsync(cancellationToken), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { - return await Queryable.OrderBy((await GetMongoQueryableAsync(cancellationToken)), x => x.Id) + return await Queryable.OrderBy((await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))), x => x.Id) .SkipIf>(offset.HasValue, offset.Value) .TakeIf>(count.HasValue, count.Value) .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetMongoQueryableAsync(cancellationToken), state).As>().ToListAsync(GetCancellationToken(cancellationToken)); + return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().ToListAsync(GetCancellationToken(cancellationToken)); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs index bf6f76aef3..cfc7dae015 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.MongoDB/Volo/Abp/OpenIddict/Tokens/MongoOpenIddictTokenRepository.cs @@ -19,86 +19,105 @@ public class MongoOpenIddictTokenRepository : MongoDbRepository x.ApplicationId == applicationId) + .ToListAsync(GetCancellationToken(cancellationToken)); + + await DeleteManyAsync(tokens, autoSave, cancellationToken); + } + + public async Task DeleteManyByAuthorizationIdAsync(Guid authorizationId, bool autoSave = false, + CancellationToken cancellationToken = default) + { + var tokens = await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))) + .Where(x => x.ApplicationId == authorizationId) + .ToListAsync(GetCancellationToken(cancellationToken)); + + await DeleteManyAsync(tokens, autoSave, GetCancellationToken(cancellationToken)); + } + public virtual async Task CountAsync(Func, IQueryable> query, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).LongCountAsync(GetCancellationToken(cancellationToken)); + return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).LongCountAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, CancellationToken cancellationToken = default) { return await Queryable.Where((await GetMongoQueryableAsync(cancellationToken)), x => x.Subject == subject && x.ApplicationId == client) .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, string status, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, string status, CancellationToken cancellationToken = default) { - return await Queryable.Where((await GetMongoQueryableAsync(cancellationToken)), x => x.Subject == subject && x.ApplicationId == client && x.Status == status) + return await Queryable.Where((await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))), x => x.Subject == subject && x.ApplicationId == client && x.Status == status) .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindAsync(string subject, Guid client, string status, string type, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindAsync(string subject, Guid client, string status, string type, CancellationToken cancellationToken = default) { - return await Queryable.Where((await GetMongoQueryableAsync(cancellationToken)), x => x.Subject == subject && x.ApplicationId == client && x.Status == status && x.Type == type) + return await Queryable.Where((await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))), x => x.Subject == subject && x.ApplicationId == client && x.Status == status && x.Type == type) .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByApplicationIdAsync(Guid applicationId, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindByApplicationIdAsync(Guid applicationId, CancellationToken cancellationToken = default) { - return await Queryable.Where((await GetMongoQueryableAsync(cancellationToken)), x => x.ApplicationId == applicationId) + return await Queryable.Where((await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))), x => x.ApplicationId == applicationId) .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> FindByAuthorizationIdAsync(Guid authorizationId, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindByAuthorizationIdAsync(Guid authorizationId, CancellationToken cancellationToken = default) { - return await Queryable.Where((await GetMongoQueryableAsync(cancellationToken)), x => x.AuthorizationId == authorizationId) + return await Queryable.Where((await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))), x => x.AuthorizationId == authorizationId) .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task FindByIdAsync(Guid id, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task FindByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); + return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.Id == id, GetCancellationToken(cancellationToken)); } - public virtual async Task FindByReferenceIdAsync(string referenceId, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task FindByReferenceIdAsync(string referenceId, CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).FirstOrDefaultAsync(x => x.ReferenceId == referenceId, GetCancellationToken(cancellationToken)); + return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))).FirstOrDefaultAsync(x => x.ReferenceId == referenceId, GetCancellationToken(cancellationToken)); } - public virtual async Task> FindBySubjectAsync(string subject, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> FindBySubjectAsync(string subject, CancellationToken cancellationToken = default) { - return await Queryable.Where((await GetMongoQueryableAsync(cancellationToken)), x => x.Subject == subject) + return await Queryable.Where((await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))), x => x.Subject == subject) .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetMongoQueryableAsync(cancellationToken), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(int? count, int? offset, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(int? count, int? offset, CancellationToken cancellationToken = default) { - return await Queryable.OrderBy((await GetMongoQueryableAsync(cancellationToken)), x => x.Id) + return await Queryable.OrderBy((await GetMongoQueryableAsync(GetCancellationToken(cancellationToken))), x => x.Id) .SkipIf>(offset.HasValue, offset.Value) .TakeIf>(count.HasValue, count.Value) .As>() .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, bool includeDetails = true, CancellationToken cancellationToken = default) + public virtual async Task> ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken = default) { - return await query(await GetMongoQueryableAsync(cancellationToken), state).As>().ToListAsync(GetCancellationToken(cancellationToken)); + return await query(await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)), state).As>().ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetPruneListAsync(DateTime date, int count, bool includeDetails = true, CancellationToken cancellationToken = default) + public async Task> GetPruneListAsync(DateTime date, int count, CancellationToken cancellationToken = default) { - //TODO: Test & Improve? - return await (from token in await GetMongoQueryableAsync(cancellationToken) + return await (from token in await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)) join authorization in (await GetMongoQueryableAsync(cancellationToken)) on token.AuthorizationId equals authorization.Id into ta from a in ta diff --git a/modules/openiddict/temp-notes.md b/modules/openiddict/temp-notes.md deleted file mode 100644 index 79bd3d60db..0000000000 --- a/modules/openiddict/temp-notes.md +++ /dev/null @@ -1,3 +0,0 @@ -* AbpOpenIddictStoreBase.Cache is IMemoryCache. Is that proper? -* As I see, we've implemented all the flows, but we intended to make some of these with abp commercial? Don't make any change yet, but we will consider it again. -