Skip to content

Commit e499f40

Browse files
authored
Merge pull request #12084 from abpframework/Module-OpenIddict
Add OpenIddict module.
2 parents 8973c86 + 6363b59 commit e499f40

File tree

740 files changed

+203104
-33
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

740 files changed

+203104
-33
lines changed

build/common.ps1

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ $solutionPaths = @(
1414
"../modules/feature-management",
1515
"../modules/identity",
1616
"../modules/identityserver",
17+
"../modules/openiddict",
1718
"../modules/tenant-management",
1819
"../modules/audit-logging",
1920
"../modules/background-jobs",

docs/en/Modules/OpenIddict.md

+240
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
## ABP OpenIddict Modules
2+
3+
## How to Install
4+
5+
TODO:
6+
7+
## User Interface
8+
9+
This module implements the domain logic and database integrations, but not provides any UI. Management UI is useful if you need to add applications and scopes on the fly. In this case, you may build the management UI yourself or consider to purchase the [ABP Commercial](https://commercial.abp.io/) which provides the management UI for this module.
10+
11+
## Relations to Other Modules
12+
13+
This module is based on the [Identity Module](Identity.md) and have an [integration package](https://www.nuget.org/packages/Volo.Abp.Account.Web.IdentityServer) with the [Account Module](Account.md).
14+
15+
## The module
16+
17+
### Demo projects
18+
19+
In the module's `app` directory there are six projects(including `angular`)
20+
21+
* `OpenIddict.Demo.Server`: An abp application with integrated modules (has two `clients` and a `scope`).
22+
* `OpenIddict.Demo.API`: ASP NET Core API application using JwtBearer authentication
23+
* `OpenIddict.Demo.Client.Mvc`: ASP NET Core MVC application using `OpenIdConnect` for authentication
24+
* `OpenIddict.Demo.Client.Console`: Use `IdentityModel` to test OpenIddict's various endpoints, and call the api of `OpenIddict.Demo.API`
25+
* `OpenIddict.Demo.Client.BlazorWASM:` ASP NET Core Blazor application using `OidcAuthentication` for authentication
26+
* `angular`: An angular application that integrates the abp ng modules and uses oauth for authentication
27+
28+
#### How to run?
29+
30+
Confirm the connection string of `appsettings.json` in the `OpenIddict.Demo.Server` project. Running the project will automatically create the database and initialize the data.
31+
After running the `OpenIddict.Demo.API` project, then you can run the rest of the projects to test.
32+
33+
### Domain module
34+
35+
There are four main entities included in this module.
36+
37+
* OpenIddictApplication: **Represents applications(client)**
38+
* OpenIddictScope: **Represents scopes**
39+
* OpenIddictAuthorization: **Represents authorizations, Track of logical chains of tokens and user consent..**
40+
* OpenIddictToken: **Represents various tokens.**
41+
42+
Domain also implements four store interfaces in OpenIddict, OpenIddict uses store to manage entities, corresponding to the above four entities, Custom entity repository is used in the store.
43+
44+
45+
```cs
46+
//Manager
47+
OpenIddictApplicationManager
48+
OpenIddictScopeManager
49+
OpenIddictAuthorizationManager
50+
OpenIddictTokenManager
51+
52+
//Store
53+
IOpenIddictApplicationStore
54+
IOpenIddictScopeStore
55+
IOpenIddictAuthorizationStore
56+
IOpenIddictTokenStore
57+
58+
//Repository
59+
IOpenIddictApplicationRepository
60+
IOpenIddictScopeRepository
61+
IOpenIddictAuthorizationRepository
62+
IOpenIddictTokenRepository
63+
```
64+
65+
We enabled most of OpenIddict's features in the `AddOpenIddict` method, You can change OpenIddict's related builder options via `PreConfigure`.
66+
67+
```cs
68+
PreConfigure<OpenIddictBuilder>(builder =>
69+
{
70+
//builder
71+
});
72+
73+
PreConfigure<OpenIddictCoreBuilder>(builder =>
74+
{
75+
//builder
76+
});
77+
78+
PreConfigure<OpenIddictServerBuilder>(builder =>
79+
{
80+
//builder
81+
});
82+
```
83+
84+
#### AbpOpenIddictOptions
85+
86+
`UpdateAbpClaimTypes(default: true)`: Updates AbpClaimTypes to be compatible with identity server claims.
87+
`AddDevelopmentEncryptionAndSigningCertificate(default: true)`: Registers (and generates if necessary) a user-specific development encryption/development signing certificate.
88+
89+
You can also change this options via `PreConfigure`.
90+
91+
#### Automatically removing orphaned tokens/authorizations
92+
93+
There is a background task in the `Domain` module (`enabled by default`) that automatically removes orphaned tokens/authorizations, you can configure `TokenCleanupOptions` to manage it.
94+
95+
### ASP NET Core module
96+
97+
This module integrates ASP NET Core, with built-in MVC controllers for four protocols. It uses OpenIddict's [Pass-through mode](https://documentation.openiddict.com/guides/index.html#pass-through-mode).
98+
99+
```cs
100+
AuthorizeController -> connect/authorize
101+
TokenController -> connect/token
102+
LogoutController -> connect/logout
103+
UserInfoController -> connect/userinfo
104+
```
105+
106+
> We will implement the related functions of **device flow** in the PRO module..
107+
108+
#### How to control claims in access_token and id_token
109+
110+
You can use the [Claims Principal Factory](https://docs.abp.io/en/abp/latest/Authorization#claims-principal-factory) to add/remove claims to the `ClaimsPrincipal`.
111+
112+
The `AbpDefaultOpenIddictClaimDestinationsProvider` service will add `Name`, `Email` and `Role` types of Claims to `access_token` and `id_token`, other claims are only added to `access_token` by default, and remove the `SecurityStampClaimType` secret claim of `Identity`.
113+
114+
You can create a service that inherits from `IAbpOpenIddictClaimDestinationsProvider` and add it to DI to fully control the destinations of claims
115+
116+
```cs
117+
public class MyClaimDestinationsProvider : IAbpOpenIddictClaimDestinationsProvider, ITransientDependency
118+
{
119+
public virtual Task SetDestinationsAsync(AbpOpenIddictClaimDestinationsProviderContext context)
120+
{
121+
// ...
122+
return Task.CompletedTask;
123+
}
124+
}
125+
126+
Configure<AbpOpenIddictClaimDestinationsOptions>(options =>
127+
{
128+
options.ClaimDestinationsProvider.Add<MyClaimDestinationsProvider>();
129+
});
130+
```
131+
132+
For detailed information, please refer to: [OpenIddict claim destinations](https://documentation.openiddict.com/configuration/claim-destinations.html)
133+
134+
#### About Validation
135+
136+
The `OpenIddict.Validation.AspNetCore` and `OpenIddict.Validation` are not integrated in the module, we use the authentication component provided by Microsoft. If you are more familiar with it, you can use it in your project.
137+
138+
139+
### EF Core module
140+
141+
Implements the above four repository interfaces.
142+
143+
### MongoDB module
144+
145+
Implements the above four repository interfaces.
146+
147+
148+
## OpenIddict
149+
150+
### Documentation
151+
152+
For more details about OpenIddict, please refer to its official documentation and Github.
153+
154+
https://documentation.openiddict.com
155+
156+
https://github.com/openiddict/openiddict-core#resources
157+
158+
### Token encryption
159+
160+
https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html
161+
162+
> 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.
163+
164+
```cs
165+
PreConfigure<OpenIddictServerBuilder>(builder =>
166+
{
167+
builder.DisableAccessTokenEncryption();
168+
});
169+
```
170+
171+
An example of using `SecurityKey`
172+
173+
> In production, it is recommended to use two RSA certificates, distinct from the certificate(s) used for HTTPS: one for encryption, one for signing.
174+
175+
```cs
176+
// In OpenIddict Server
177+
PreConfigure<OpenIddictServerBuilder>(builder =>
178+
{
179+
builder.AddSigningKey(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_C40DBB176E78")));
180+
builder.AddEncryptionKey(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_87E33FC57D80")));
181+
});
182+
183+
//In Client AddJwtBearer
184+
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
185+
.AddJwtBearer(options =>
186+
{
187+
//Other configuration
188+
189+
options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_C40DBB176E78"));
190+
options.TokenValidationParameters.TokenDecryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_87E33FC57D80"));
191+
});
192+
```
193+
194+
195+
### PKCE
196+
197+
https://documentation.openiddict.com/configuration/proof-key-for-code-exchange.html
198+
199+
### Request/Response process
200+
201+
I will briefly introduce the principle of OpenIddict so that everyone can quickly understand it.
202+
203+
The `OpenIddict.Server.AspNetCore` adds an authentication scheme(`Name: OpenIddict.Server.AspNetCore, handler: OpenIddictServerAspNetCoreHandler`) and implements the `IAuthenticationRequestHandler` interface.
204+
205+
It will be executed first in `AuthenticationMiddleware` and can short-circuit the current request. Otherwise, `DefaultAuthenticateScheme` will be called and continue to execute the pipeline.
206+
207+
`OpenIddictServerAspNetCoreHandler` will call various built-in handlers(Handling requests and responses), And the handler will process according to the context or skip logic that has nothing to do with it.
208+
209+
Example a token request:
210+
211+
```
212+
POST /connect/token HTTP/1.1
213+
Content-Type: application/x-www-form-urlencoded
214+
215+
grant_type=password&
216+
client_id=AbpApp&
217+
client_secret=1q2w3e*&
218+
username=admin&
219+
password=1q2w3E*&
220+
scope=AbpAPI offline_access
221+
```
222+
223+
This request will be processed by various handlers. They will confirm the endpoint type of the request, check `http/https`, verify that the request parameters (`client. scope etc`) are valid and exist in the database, etc. Various protocol checks. And build a `OpenIddictRequest` object, If there are any errors, the response content may be set and directly short-circuit the current request.
224+
225+
If everything is ok, the request will go to our processing controller(eg `TokenController`), we can get an `OpenIddictRequest` from the http request at this time. The rest of our work will be based on this object.
226+
227+
We may check the `username` and `password` in the request. If it is correct we create a `ClaimsPrincipal` object and return a `SignInResult`, which uses the `OpenIddict.Validation.AspNetCore` authentication scheme name, will calls `OpenIddictServerAspNetCoreHandler` for processing.
228+
229+
`OpenIddictServerAspNetCoreHandler` do some checks to generate json and replace the http response content.
230+
231+
The `ForbidResult` `ChallengeResult` are all the above types of processing.
232+
233+
If you need to customize OpenIddict, you need to replace/delete/add new handlers and make it execute in the correct order.
234+
235+
Please refer to:
236+
https://documentation.openiddict.com/guides/index.html#events-model
237+
238+
## Sponsor
239+
240+
Please consider sponsoring this project: https://github.com/sponsors/kevinchalet

docs/en/docs-nav.json

+4
Original file line numberDiff line numberDiff line change
@@ -1289,6 +1289,10 @@
12891289
{
12901290
"text": "IdentityServer",
12911291
"path": "Modules/IdentityServer.md"
1292+
},
1293+
{
1294+
"text": "OpenIddict",
1295+
"path": "Modules/OpenIddict.md"
12921296
},
12931297
{
12941298
"text": "Permission Management",

framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
</PropertyGroup>
1616

1717
<ItemGroup>
18-
<PackageReference Include="IdentityModel" Version="5.1.0" />
18+
<PackageReference Include="IdentityModel" Version="6.0.0" />
1919
<PackageReference Include="Microsoft.Extensions.Http" Version="$(MicrosoftPackageVersion)" />
2020
<ProjectReference Include="..\Volo.Abp.Caching\Volo.Abp.Caching.csproj" />
2121
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />

modules/account/Volo.Abp.Account.sln

+7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Account.Blazor", "
2525
EndProject
2626
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Account.Installer", "src\Volo.Abp.Account.Installer\Volo.Abp.Account.Installer.csproj", "{EAAB416C-9113-486D-9B54-4DCF78FDC6AB}"
2727
EndProject
28+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Account.Web.OpenIddict", "src\Volo.Abp.Account.Web.OpenIddict\Volo.Abp.Account.Web.OpenIddict.csproj", "{53DA9051-4C76-4264-A1E1-2810DC685CB2}"
29+
EndProject
2830
Global
2931
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3032
Debug|Any CPU = Debug|Any CPU
@@ -67,6 +69,10 @@ Global
6769
{EAAB416C-9113-486D-9B54-4DCF78FDC6AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
6870
{EAAB416C-9113-486D-9B54-4DCF78FDC6AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
6971
{EAAB416C-9113-486D-9B54-4DCF78FDC6AB}.Release|Any CPU.Build.0 = Release|Any CPU
72+
{53DA9051-4C76-4264-A1E1-2810DC685CB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
73+
{53DA9051-4C76-4264-A1E1-2810DC685CB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
74+
{53DA9051-4C76-4264-A1E1-2810DC685CB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
75+
{53DA9051-4C76-4264-A1E1-2810DC685CB2}.Release|Any CPU.Build.0 = Release|Any CPU
7076
EndGlobalSection
7177
GlobalSection(SolutionProperties) = preSolution
7278
HideSolutionNode = FALSE
@@ -81,6 +87,7 @@ Global
8187
{356EAC51-5D55-4852-A8A5-2F90EAC8DAE3} = {12FAE513-7575-4235-89DF-277BA1A3B098}
8288
{EE8858B3-A638-481B-8EB9-74F5E7D43D80} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E}
8389
{EAAB416C-9113-486D-9B54-4DCF78FDC6AB} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E}
90+
{53DA9051-4C76-4264-A1E1-2810DC685CB2} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E}
8491
EndGlobalSection
8592
GlobalSection(ExtensibilityGlobals) = postSolution
8693
SolutionGuid = {2B054393-D2B2-4EA8-8A15-D60CBCF3E7A9}

modules/account/src/Volo.Abp.Account.Web.IdentityServer/Properties/launchSettings.json

-27
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Volo.Abp.Modularity;
3+
using Volo.Abp.OpenIddict;
4+
using Volo.Abp.VirtualFileSystem;
5+
6+
namespace Volo.Abp.Account.Web;
7+
8+
[DependsOn(
9+
typeof(AbpAccountWebModule),
10+
typeof(AbpOpenIddictAspNetCoreModule)
11+
)]
12+
public class AbpAccountWebOpenIddictModule : AbpModule
13+
{
14+
public override void PreConfigureServices(ServiceConfigurationContext context)
15+
{
16+
PreConfigure<IMvcBuilder>(mvcBuilder =>
17+
{
18+
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountWebOpenIddictModule).Assembly);
19+
});
20+
}
21+
22+
public override void ConfigureServices(ServiceConfigurationContext context)
23+
{
24+
Configure<AbpVirtualFileSystemOptions>(options =>
25+
{
26+
options.FileSets.AddEmbedded<AbpAccountWebOpenIddictModule>();
27+
});
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
2+
<ConfigureAwait ContinueOnCapturedContext="false" />
3+
</Weavers>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3+
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
4+
<xs:element name="Weavers">
5+
<xs:complexType>
6+
<xs:all>
7+
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
8+
<xs:complexType>
9+
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
10+
</xs:complexType>
11+
</xs:element>
12+
</xs:all>
13+
<xs:attribute name="VerifyAssembly" type="xs:boolean">
14+
<xs:annotation>
15+
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
16+
</xs:annotation>
17+
</xs:attribute>
18+
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
19+
<xs:annotation>
20+
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
21+
</xs:annotation>
22+
</xs:attribute>
23+
<xs:attribute name="GenerateXsd" type="xs:boolean">
24+
<xs:annotation>
25+
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
26+
</xs:annotation>
27+
</xs:attribute>
28+
</xs:complexType>
29+
</xs:element>
30+
</xs:schema>

0 commit comments

Comments
 (0)