11 KiB
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 which provides the management UI for this module.
Relations to Other Modules
This module is based on the Identity Module and have an integration package with the Account Module.
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 twoclientsand ascope).OpenIddict.Demo.API: ASP NET Core API application using JwtBearer authenticationOpenIddict.Demo.Client.Mvc: ASP NET Core MVC application usingOpenIdConnectfor authenticationOpenIddict.Demo.Client.Console: UseIdentityModelto test OpenIddict's various endpoints, and call the api ofOpenIddict.Demo.APIOpenIddict.Demo.Client.BlazorWASM:ASP NET Core Blazor application usingOidcAuthenticationfor authenticationangular: 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.
//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.
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.
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..
Identity authentication scheme
The default ABP OpenIddict project includes several authentication schemes.
Bearer: Authenticate tokens issued by yourself(angular)OpenIddict.Server.AspNetCore: OpenIddict usesIdentity.Application: Identity default authenticate schemeIdentity.External: Identity external login usesIdentity.TwoFactorRememberMe: Identity TwoFactor login usesIdentity.TwoFactorUserId: Identity TwoFactor login uses
This can break the multi-tenancy feature, Some OAuth requests may be authenticated by OpenIddict but not by Identity.Application.
We have added a top priority AbpOpenIddictTenantResolveContributor service. It will try to get tenant info from OpenIddict authentication scheme.
Please note the difference and usage scenarios between Identity.Application and OpenIddict.Server.AspNetCore.
How to control claims in access_token and id_token
You can use the 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
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
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.
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.
// 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