Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OpenIddict module. #12084

Merged
merged 39 commits into from
May 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
2428741
Initialize the project.
maliming Mar 25, 2022
530a365
Add MongoDB Repositories
realLiangshiwei Mar 29, 2022
ec6f972
Add Demo Apps.
maliming Mar 29, 2022
b1f9cc3
Rename modules.
maliming Mar 30, 2022
f63fc29
Add ng and blazor demo.
maliming Apr 1, 2022
b195d48
Add localized texts.
maliming Apr 1, 2022
6cc8ffa
Rename to lowercase.
maliming Apr 1, 2022
f766e84
Add `IAbpOpenIddictClaimDestinationsProvider`.
maliming Apr 1, 2022
556c326
Update common.ps1
maliming Apr 1, 2022
5c57850
Add `includeDetails`.
maliming Apr 2, 2022
4992895
Add OpenIddict document.
maliming Apr 2, 2022
5a30a8f
Merge branch 'Module-OpenIddict' of github.com:abpframework/abp into …
maliming Apr 2, 2022
c8a8f99
Update AbpOpenIddictTenantResolveContributor.cs
maliming Apr 2, 2022
8575bcc
`EnableStatusCodePagesIntegration`.
maliming Apr 3, 2022
c7bf5a4
Update OpenIddict.md
maliming Apr 3, 2022
eb5c79b
Add `TokenCleanupBackgroundWorker`.
maliming Apr 3, 2022
5ccc801
Update OpenIddict document.
maliming Apr 3, 2022
6b4c470
Merge branch 'Module-OpenIddict' of github.com:abpframework/abp into …
maliming Apr 3, 2022
cbdf333
Reviewed the domain layer of the OpenIddict module
hikalkan Apr 4, 2022
eff4690
Merge branch 'rel-6.0' into Module-OpenIddict
hikalkan Apr 4, 2022
afa47af
Create temp-notes.md
hikalkan Apr 4, 2022
15b9e4a
Refactor.
maliming Apr 5, 2022
49d7941
Add Cache feature.
maliming Apr 6, 2022
91193c6
Add `Volo.Abp.Account.Web.OpenIddict` package.
maliming Apr 7, 2022
c57d2bc
Add `WildcardDomainSupport`.
maliming Apr 8, 2022
6953e9c
Remove redundant localization.
maliming Apr 11, 2022
0f53ca8
Refactor
maliming Apr 11, 2022
a6014e5
Refactor
maliming Apr 15, 2022
7166e19
Merge branch 'rel-6.0' into Module-OpenIddict
hikalkan Apr 19, 2022
9817220
Upgrade IdentityModel to 6.0.
maliming Apr 20, 2022
b75c90a
Add `GetListAsync` and `GetCountAsync`.
maliming Apr 21, 2022
407d5db
Add `Volo.Abp.PermissionManagement.Domain.OpenIddict`.
maliming Apr 21, 2022
a5ce947
Refactor SkipIf and TakeIf methods.
maliming Apr 21, 2022
15f8951
Update model after Create or Update.
maliming Apr 22, 2022
c3f13c8
Support ExtensibleObject.
maliming Apr 25, 2022
e4733b3
Add Object Extension feature.
maliming Apr 25, 2022
a4317b5
Remove `IsUnique`.
maliming Apr 25, 2022
714cdae
Add AbpOpenIddictApplicationStore_Tests
realLiangshiwei May 5, 2022
6363b59
Merge branch 'rel-6.0' into Module-OpenIddict
hikalkan May 6, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions build/common.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ $solutionPaths = @(
"../modules/feature-management",
"../modules/identity",
"../modules/identityserver",
"../modules/openiddict",
"../modules/tenant-management",
"../modules/audit-logging",
"../modules/background-jobs",
Expand Down
240 changes: 240 additions & 0 deletions docs/en/Modules/OpenIddict.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
## ABP OpenIddict Modules

## How to Install

TODO:

## User Interface

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.

## Relations to Other Modules

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).

## The module

### Demo projects

In the module's `app` directory there are six projects(including `angular`)

* `OpenIddict.Demo.Server`: An abp application with integrated modules (has two `clients` and a `scope`).
* `OpenIddict.Demo.API`: ASP NET Core API application using JwtBearer authentication
* `OpenIddict.Demo.Client.Mvc`: ASP NET Core MVC application using `OpenIdConnect` for authentication
* `OpenIddict.Demo.Client.Console`: Use `IdentityModel` to test OpenIddict's various endpoints, and call the api of `OpenIddict.Demo.API`
* `OpenIddict.Demo.Client.BlazorWASM:` ASP NET Core Blazor application using `OidcAuthentication` for authentication
* `angular`: An angular application that integrates the abp ng modules and uses oauth for authentication

#### How to run?

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.
After running the `OpenIddict.Demo.API` project, then you can run the rest of the projects to test.

### Domain module

There are four main entities included in this module.

* OpenIddictApplication: **Represents applications(client)**
* OpenIddictScope: **Represents scopes**
* OpenIddictAuthorization: **Represents authorizations, Track of logical chains of tokens and user consent..**
* OpenIddictToken: **Represents various tokens.**

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.


```cs
//Manager
OpenIddictApplicationManager
OpenIddictScopeManager
OpenIddictAuthorizationManager
OpenIddictTokenManager

//Store
IOpenIddictApplicationStore
IOpenIddictScopeStore
IOpenIddictAuthorizationStore
IOpenIddictTokenStore

//Repository
IOpenIddictApplicationRepository
IOpenIddictScopeRepository
IOpenIddictAuthorizationRepository
IOpenIddictTokenRepository
```

We enabled most of OpenIddict's features in the `AddOpenIddict` method, You can change OpenIddict's related builder options via `PreConfigure`.

```cs
PreConfigure<OpenIddictBuilder>(builder =>
{
//builder
});

PreConfigure<OpenIddictCoreBuilder>(builder =>
{
//builder
});

PreConfigure<OpenIddictServerBuilder>(builder =>
{
//builder
});
```

#### AbpOpenIddictOptions

`UpdateAbpClaimTypes(default: true)`: Updates AbpClaimTypes to be compatible with identity server claims.
`AddDevelopmentEncryptionAndSigningCertificate(default: true)`: Registers (and generates if necessary) a user-specific development encryption/development signing certificate.

You can also change this options via `PreConfigure`.

#### Automatically removing orphaned tokens/authorizations

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.

### ASP NET Core module

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).

```cs
AuthorizeController -> connect/authorize
TokenController -> connect/token
LogoutController -> connect/logout
UserInfoController -> connect/userinfo
```

> We will implement the related functions of **device flow** in the PRO module..

#### How to control claims in access_token and id_token

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`.

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`.

You can create a service that inherits from `IAbpOpenIddictClaimDestinationsProvider` and add it to DI to fully control the destinations of claims

```cs
public class MyClaimDestinationsProvider : IAbpOpenIddictClaimDestinationsProvider, ITransientDependency
{
public virtual Task SetDestinationsAsync(AbpOpenIddictClaimDestinationsProviderContext context)
{
// ...
return Task.CompletedTask;
}
}

Configure<AbpOpenIddictClaimDestinationsOptions>(options =>
{
options.ClaimDestinationsProvider.Add<MyClaimDestinationsProvider>();
});
```

For detailed information, please refer to: [OpenIddict claim destinations](https://documentation.openiddict.com/configuration/claim-destinations.html)

#### About Validation

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.


### EF Core module

Implements the above four repository interfaces.

### MongoDB module

Implements the above four repository interfaces.


## OpenIddict

### Documentation

For more details about OpenIddict, please refer to its official documentation and Github.

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<OpenIddictServerBuilder>(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<OpenIddictServerBuilder>(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

### Request/Response process

I will briefly introduce the principle of OpenIddict so that everyone can quickly understand it.

The `OpenIddict.Server.AspNetCore` adds an authentication scheme(`Name: OpenIddict.Server.AspNetCore, handler: OpenIddictServerAspNetCoreHandler`) and implements the `IAuthenticationRequestHandler` interface.

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.

`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.

Example a token request:

```
POST /connect/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=password&
client_id=AbpApp&
client_secret=1q2w3e*&
username=admin&
password=1q2w3E*&
scope=AbpAPI offline_access
```

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.

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.

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.

`OpenIddictServerAspNetCoreHandler` do some checks to generate json and replace the http response content.

The `ForbidResult` `ChallengeResult` are all the above types of processing.

If you need to customize OpenIddict, you need to replace/delete/add new handlers and make it execute in the correct order.

Please refer to:
https://documentation.openiddict.com/guides/index.html#events-model

## Sponsor

Please consider sponsoring this project: https://github.com/sponsors/kevinchalet
4 changes: 4 additions & 0 deletions docs/en/docs-nav.json
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,10 @@
{
"text": "IdentityServer",
"path": "Modules/IdentityServer.md"
},
{
"text": "OpenIddict",
"path": "Modules/OpenIddict.md"
},
{
"text": "Permission Management",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="IdentityModel" Version="5.1.0" />
<PackageReference Include="IdentityModel" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="$(MicrosoftPackageVersion)" />
<ProjectReference Include="..\Volo.Abp.Caching\Volo.Abp.Caching.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
Expand Down
7 changes: 7 additions & 0 deletions modules/account/Volo.Abp.Account.sln
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Account.Blazor", "
EndProject
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}"
EndProject
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}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -67,6 +69,10 @@ Global
{EAAB416C-9113-486D-9B54-4DCF78FDC6AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EAAB416C-9113-486D-9B54-4DCF78FDC6AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EAAB416C-9113-486D-9B54-4DCF78FDC6AB}.Release|Any CPU.Build.0 = Release|Any CPU
{53DA9051-4C76-4264-A1E1-2810DC685CB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53DA9051-4C76-4264-A1E1-2810DC685CB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53DA9051-4C76-4264-A1E1-2810DC685CB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53DA9051-4C76-4264-A1E1-2810DC685CB2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -81,6 +87,7 @@ Global
{356EAC51-5D55-4852-A8A5-2F90EAC8DAE3} = {12FAE513-7575-4235-89DF-277BA1A3B098}
{EE8858B3-A638-481B-8EB9-74F5E7D43D80} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E}
{EAAB416C-9113-486D-9B54-4DCF78FDC6AB} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E}
{53DA9051-4C76-4264-A1E1-2810DC685CB2} = {B5881429-EFF7-4F30-8C0B-0AC41E36B74E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2B054393-D2B2-4EA8-8A15-D60CBCF3E7A9}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using Volo.Abp.OpenIddict;
using Volo.Abp.VirtualFileSystem;

namespace Volo.Abp.Account.Web;

[DependsOn(
typeof(AbpAccountWebModule),
typeof(AbpOpenIddictAspNetCoreModule)
)]
public class AbpAccountWebOpenIddictModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountWebOpenIddictModule).Assembly);
});
}

public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAccountWebOpenIddictModule>();
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
Loading