|
| 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 |
0 commit comments