mirror of
https://gitee.com/dcren/openiddict-documentation.git
synced 2025-09-19 01:57:56 +08:00
Add documentation for Entity Framework Core and MongoDB integrations
This commit is contained in:
210
guides/choosing-the-right-flow.md
Normal file
210
guides/choosing-the-right-flow.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# Choosing the right flow
|
||||
|
||||
OpenIddict offers built-in support for all the standard flows defined by the
|
||||
[OAuth 2.0](https://tools.ietf.org/html/rfc6749) and [OpenID Connect](https://openid.net/specs/openid-connect-core-1_0.html) core specifications:
|
||||
[the authorization code flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth),
|
||||
[the implicit flow](https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth),
|
||||
[the hybrid flow](https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth) (which is basically a mix between the first two flows),
|
||||
[the resource owner password credentials grant](https://tools.ietf.org/html/rfc6749#section-4.3) and
|
||||
[the client credentials grant](https://tools.ietf.org/html/rfc6749#section-4.4).
|
||||
|
||||
While not specific to OpenIddict, choosing the best flow(s) for your application is an **important prerequisite**
|
||||
when implementing your own authorization server ; so here's a quick overview of the different OAuth 2.0/OpenID Connect flows:
|
||||
|
||||
------------------------
|
||||
## Non-interactive flows
|
||||
|
||||
### Resource owner password credentials flow (not recommended for new applications)
|
||||
|
||||
Directly inspired by [basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication), the resource owner password credentials grant
|
||||
(abbreviated *ROPC*) is conceptually **the simplest OAuth 2.0 flow**: the client application asks the user his username/password, sends a token request
|
||||
to the authorization server with the user credentials (and depending on the client authentication policy defined by the authorization server,
|
||||
its own client credentials) and gets back an access token it can use to retrieve the user's resources.
|
||||
|
||||

|
||||
|
||||
```http
|
||||
POST /connect/token HTTP/1.1
|
||||
Host: server.example.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
grant_type=password&username=johndoe&password=A3ddj3w
|
||||
```
|
||||
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
Cache-Control: no-store
|
||||
Pragma: no-cache
|
||||
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> This flow is **not recommended by the OAuth 2.0 specification** as it's the only grant type where **the user password is directly exposed to the client application**,
|
||||
> which breaks the principle of least privilege and **makes it unsuitable for third-party client applications that can't be fully trusted by the authorization server**.
|
||||
|
||||
> While popular and trivial to implement (as it doesn't involve any redirection or consent form and unlike interactive flows, doesn't require implementing
|
||||
> cross-site request forgery (XSRF) countermeasures to prevent session fixation attacks), **its use in new applications is not recommended**. Instead,
|
||||
> users are encouraged to use the authorization code flow, that doesn't expose passwords to client applications and is not limited to password authentication.
|
||||
|
||||
<!-- more -->
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
### Client credentials grant (recommended for machine-to-machine communication)
|
||||
|
||||
The client credentials grant is almost identical to the resource owner password credentials grant, except it's been specifically designed for **client-to-server scenarios**
|
||||
(no user is involved in this flow): the client application sends a token request containing its credentials and gets back an access token it can use to query its own resources.
|
||||
|
||||

|
||||
|
||||
```http
|
||||
POST /connect/token HTTP/1.1
|
||||
Host: server.example.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
grant_type=client_credentials&client_id=s6BhdRkqt3&client_secret=gX1fBat3bV
|
||||
```
|
||||
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
Cache-Control: no-store
|
||||
Pragma: no-cache
|
||||
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Unlike the resource owner password credentials grant, **client authentication is not optional** when using the client credentials grant and
|
||||
> **OpenIddict will always reject unauthenticated token requests**, [as required by the OAuth 2.0 specification](https://tools.ietf.org/html/rfc6749#section-4.4.2).
|
||||
>
|
||||
> This means that **you CAN'T use the client credentials grant with public applications** like browser,
|
||||
> mobile or desktop applications, as they are not able to keep their credentials secret.
|
||||
|
||||
--------------------
|
||||
## Interactive flows
|
||||
|
||||
### Authorization code flow (recommended for new applications)
|
||||
|
||||
While the authorization code flow is probably the most complicated flow (as it involves both **user-agent redirections and backchannel communication**), it's
|
||||
**the recommended flow for any scenario involving end users, whether they log in using a password, a PIN, a smart card or even an external provider**.
|
||||
In return for its complexity, this flow has a great advantage when used in server-side applications: the `access_token` cannot be intercepted by the user agent.
|
||||
|
||||
There are basically 2 steps in the authorization code flow: the authorization request/response and the token request/response.
|
||||
|
||||

|
||||
|
||||
- **Step 1: the authorization request**
|
||||
|
||||
In this flow, the client application always initiates the authentication process by generating an authorization request including
|
||||
the mandatory `response_type=code` parameter, its `client_id`, its `redirect_uri` and optionally, a `scope` and a `state` parameter
|
||||
[that allows flowing custom data and helps mitigate XSRF attacks](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).
|
||||
|
||||
> [!NOTE]
|
||||
> In most cases, the client application will simply return a 302 response with a `Location` header to redirect the user agent to the authorization endpoint,
|
||||
> but depending on the OpenID Connect client you're using, POST requests might also be supported to allow you to send large authorization requests.
|
||||
> This feature [is usually implemented using an auto-post HTML form](https://github.com/aspnet/Security/pull/392).
|
||||
|
||||
```http
|
||||
HTTP/1.1 302 Found
|
||||
Location: https://server.example.com/authorize?response_type=code&client_id=s6BhdRkqt3&state=af0ifjsldkj&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
|
||||
```
|
||||
|
||||
```http
|
||||
GET /connect/authorize?response_type=code&client_id=s6BhdRkqt3&state=af0ifjsldkj&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
|
||||
Host: server.example.com
|
||||
```
|
||||
|
||||
The way the identity provider handles the authorization request is implementation-specific but in most cases, a consent form
|
||||
is displayed to ask the user if he or she agrees to share his/her personal data with the client application.
|
||||
|
||||

|
||||
|
||||
When the consent is given, the user agent is redirected back to the client application with **a unique and short-lived token**
|
||||
named *authorization code* that the client will be able to exchange with an access token by sending a token request.
|
||||
|
||||
```http
|
||||
HTTP/1.1 302 Found
|
||||
Location: https://client.example.org/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> To prevent XSRF/session fixation attacks, **the client application MUST ensure that the `state` parameter returned by the identity provider
|
||||
> corresponds to the original `state`** and stop processing the authorization response if the two values don't match.
|
||||
> [This is usually done by generating a non-guessable string and a corresponding correlation cookie](https://tools.ietf.org/html/rfc6749#section-10.12).
|
||||
|
||||
- **Step 2: the token request**
|
||||
|
||||
When the client application gets back an authorization code, it must immediately reedem it for an access token by sending a `grant_type=authorization_code` token request.
|
||||
|
||||
> [!NOTE]
|
||||
> To help the identity provider [mitigate counterfeit clients attacks](https://tools.ietf.org/html/rfc6819#section-4.4.1.7), the original `redirect_uri` must also be sent.
|
||||
>
|
||||
> If the client application is a confidential application (i.e an application that has been assigned client credentials), authentication is required.
|
||||
|
||||
```http
|
||||
POST /connect/token HTTP/1.1
|
||||
Host: server.example.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb&client_id=s6BhdRkqt3&client_secret=gX1fBat3bV&scope=openid
|
||||
```
|
||||
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
Cache-Control: no-store
|
||||
Pragma: no-cache
|
||||
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> To increase security, additional parameters such as `code_challenge` and `code_challenge_method` can be specified to bind the authorization code
|
||||
> that will be returned by the authorization endpoint to the original authorization request. This mechanism is known as
|
||||
> [Proof Key for Code Exchange](../configuration/proof-key-for-code-exchange.md) and is fully supported by OpenIddict.
|
||||
|
||||
--------------------------------------------------------
|
||||
### Implicit flow (not recommended for new applications)
|
||||
|
||||
The implicit flow is similar to the authorization code flow, **except there's no token request/response step**: the access token is directly returned
|
||||
to the client application as part of the authorization response in the URI fragment (or in the request form when using `response_mode=form_post`).
|
||||
|
||||

|
||||
|
||||
```http
|
||||
GET /connect/authorize?response_type=token&client_id=s6BhdRkqt3&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb&scope=openid&state=af0ifjsldkj&nonce=n-0S6_WzA2Mj HTTP/1.1
|
||||
Host: server.example.com
|
||||
```
|
||||
|
||||
```http
|
||||
HTTP/1.1 302 Found
|
||||
Location: https://client.example.org/cb#access_token=SlAV32hkKG&token_type=bearer&expires_in=3600&state=af0ifjsldkj
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> Initially designed for browser applications, this flow is inherently less secure than the authorization code flow and doesn't support
|
||||
> [Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636). As such, using it in new applications is not recommended.
|
||||
|
||||
> [!WARNING]
|
||||
> To prevent XSRF/session fixation attacks, **the client application MUST ensure that the `state` parameter returned by the identity provider
|
||||
> corresponds to the original `state`** and stop processing the authorization response if the two values don't match.
|
||||
> [This is usually done by generating a non-guessable string and a corresponding value stored in the local storage](https://tools.ietf.org/html/rfc6749#section-10.12).
|
||||
>
|
||||
> When using the implicit flow, **the client application MUST also ensure that the access token was not issued
|
||||
> to another application to prevent [confused deputy attacks](https://stackoverflow.com/a/17439317/542757).**
|
||||
> With OpenID Connect, this can be done by using `response_type=id_token token` and checking the `aud` claim
|
||||
> of the JWT identity token, that must correspond or contain the `client_id` of the client application.
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> Initially designed for browser applications, this flow is inherently less secure than the authorization code flow and doesn't support
|
||||
> [Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636). As such, using it in new applications is not recommended.
|
||||
|
||||
> [!WARNING]
|
||||
> To prevent XSRF/session fixation attacks, **the client application MUST ensure that the `state` parameter returned by the identity provider
|
||||
> corresponds to the original `state`** and stop processing the authorization response if the two values don't match.
|
||||
> [This is usually done by generating a non-guessable string and a corresponding value stored in the local storage](https://tools.ietf.org/html/rfc6749#section-10.12).
|
||||
>
|
||||
> When using the implicit flow, **the client application MUST also ensure that the access token was not issued
|
||||
> to another application to prevent [confused deputy attacks](https://stackoverflow.com/a/17439317/542757).**
|
||||
> With OpenID Connect, this can be done by using `response_type=id_token token` and checking the `aud` claim
|
||||
> of the JWT identity token, that must correspond or contain the `client_id` of the client application.
|
BIN
guides/choosing-the-right-flow/authorization-code-flow.png
Normal file
BIN
guides/choosing-the-right-flow/authorization-code-flow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
guides/choosing-the-right-flow/client-credentials-flow.png
Normal file
BIN
guides/choosing-the-right-flow/client-credentials-flow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
BIN
guides/choosing-the-right-flow/consent-form.png
Normal file
BIN
guides/choosing-the-right-flow/consent-form.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
guides/choosing-the-right-flow/implicit-flow.png
Normal file
BIN
guides/choosing-the-right-flow/implicit-flow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
guides/choosing-the-right-flow/resource-owner-password-flow.png
Normal file
BIN
guides/choosing-the-right-flow/resource-owner-password-flow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
207
guides/getting-started.md
Normal file
207
guides/getting-started.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# Getting started
|
||||
|
||||
**To implement a custom OpenID Connect server using OpenIddict, the simplest option is to clone one of the official samples** from the [openiddict-samples repository](https://github.com/openiddict/openiddict-samples).
|
||||
|
||||
If you don't want to start from one of the recommended samples, you'll need to:
|
||||
|
||||
- **Install the [.NET Core 3.1 (or later) tooling](https://www.microsoft.com/net/download)**.
|
||||
|
||||
- **Have an existing project or create a new one**: when creating a new project using Visual Studio's default ASP.NET Core template,
|
||||
using **individual user accounts authentication** is strongly recommended as it automatically includes the default ASP.NET Core Identity UI, based on Razor Pages.
|
||||
|
||||
- **Update your `.csproj` file** to reference the latest `OpenIddict` packages:
|
||||
|
||||
```xml
|
||||
<PackageReference Include="OpenIddict.AspNetCore" Version="3.1.1" />
|
||||
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="3.1.1" />
|
||||
```
|
||||
|
||||
- **Configure the OpenIddict core, server and validation services** in `Startup.ConfigureServices`.
|
||||
Here's an example for the client credentials grant, used in machine-to-machine scenarios:
|
||||
|
||||
```csharp
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddControllersWithViews();
|
||||
|
||||
services.AddDbContext<ApplicationDbContext>(options =>
|
||||
{
|
||||
// Configure Entity Framework Core to use Microsoft SQL Server.
|
||||
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
|
||||
|
||||
// Register the entity sets needed by OpenIddict.
|
||||
// Note: use the generic overload if you need to replace the default OpenIddict entities.
|
||||
options.UseOpenIddict();
|
||||
});
|
||||
|
||||
services.AddOpenIddict()
|
||||
|
||||
// Register the OpenIddict core components.
|
||||
.AddCore(options =>
|
||||
{
|
||||
// Configure OpenIddict to use the Entity Framework Core stores and models.
|
||||
// Note: call ReplaceDefaultEntities() to replace the default entities.
|
||||
options.UseEntityFrameworkCore()
|
||||
.UseDbContext<ApplicationDbContext>();
|
||||
})
|
||||
|
||||
// Register the OpenIddict server components.
|
||||
.AddServer(options =>
|
||||
{
|
||||
// Enable the token endpoint.
|
||||
options.SetTokenEndpointUris("/connect/token");
|
||||
|
||||
// Enable the client credentials flow.
|
||||
options.AllowClientCredentialsFlow();
|
||||
|
||||
// Register the signing and encryption credentials.
|
||||
options.AddDevelopmentEncryptionCertificate()
|
||||
.AddDevelopmentSigningCertificate();
|
||||
|
||||
// Register the ASP.NET Core host and configure the ASP.NET Core options.
|
||||
options.UseAspNetCore()
|
||||
.EnableTokenEndpointPassthrough();
|
||||
})
|
||||
|
||||
// Register the OpenIddict validation components.
|
||||
.AddValidation(options =>
|
||||
{
|
||||
// Import the configuration from the local OpenIddict server instance.
|
||||
options.UseLocalServer();
|
||||
|
||||
// Register the ASP.NET Core host.
|
||||
options.UseAspNetCore();
|
||||
});
|
||||
|
||||
// Register the worker responsible of seeding the database with the sample clients.
|
||||
// Note: in a real world application, this step should be part of a setup script.
|
||||
services.AddHostedService<Worker>();
|
||||
}
|
||||
```
|
||||
|
||||
- **Make sure the ASP.NET Core authentication middleware is correctly registered at the right place**:
|
||||
|
||||
```csharp
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseEndpoints(options =>
|
||||
{
|
||||
options.MapControllers();
|
||||
options.MapDefaultControllerRoute();
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
- **Update your Entity Framework Core context registration to register the OpenIddict entities**:
|
||||
|
||||
```csharp
|
||||
services.AddDbContext<ApplicationDbContext>(options =>
|
||||
{
|
||||
// Configure Entity Framework Core to use Microsoft SQL Server.
|
||||
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
|
||||
|
||||
// Register the entity sets needed by OpenIddict.
|
||||
// Note: use the generic overload if you need to replace the default OpenIddict entities.
|
||||
options.UseOpenIddict();
|
||||
});
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> By default, the OpenIddict Entity Framework Core integration uses `string` as the default type for primary keys.
|
||||
> To use a different type, read [Entity Framework Core integration : Use a custom primary key type](~/integrations/entity-framework-core.md#use-a-custom-primary-key-type).
|
||||
|
||||
- **Create your own authorization controller:**
|
||||
Implementing a custom authorization controller is required to allow OpenIddict to create tokens based on the identities and claims you provide.
|
||||
Here's an example for the client credentials grant:
|
||||
|
||||
```csharp
|
||||
public class AuthorizationController : Controller
|
||||
{
|
||||
private readonly IOpenIddictApplicationManager _applicationManager;
|
||||
|
||||
public AuthorizationController(IOpenIddictApplicationManager applicationManager)
|
||||
=> _applicationManager = applicationManager;
|
||||
|
||||
[HttpPost("~/connect/token"), Produces("application/json")]
|
||||
public async Task<IActionResult> Exchange()
|
||||
{
|
||||
var request = HttpContext.GetOpenIddictServerRequest();
|
||||
if (!request.IsClientCredentialsGrantType())
|
||||
{
|
||||
throw new NotImplementedException("The specified grant is not implemented.");
|
||||
}
|
||||
|
||||
// Note: the client credentials are automatically validated by OpenIddict:
|
||||
// if client_id or client_secret are invalid, this action won't be invoked.
|
||||
|
||||
var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ??
|
||||
throw new InvalidOperationException("The application cannot be found.");
|
||||
|
||||
// Create a new ClaimsIdentity containing the claims that
|
||||
// will be used to create an id_token, a token or a code.
|
||||
var identity = new ClaimsIdentity(TokenValidationParameters.DefaultAuthenticationType, Claims.Name, Claims.Role);
|
||||
|
||||
// Use the client_id as the subject identifier.
|
||||
identity.AddClaim(Claims.Subject,
|
||||
await _applicationManager.GetClientIdAsync(application),
|
||||
Destinations.AccessToken, Destinations.IdentityToken);
|
||||
|
||||
identity.AddClaim(Claims.Name,
|
||||
await _applicationManager.GetDisplayNameAsync(application),
|
||||
Destinations.AccessToken, Destinations.IdentityToken);
|
||||
|
||||
return SignIn(new ClaimsPrincipal(identity),
|
||||
OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Register your client application** (e.g from an `IHostedService` implementation):
|
||||
|
||||
```csharp
|
||||
public class Worker : IHostedService
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public Worker(IServiceProvider serviceProvider)
|
||||
=> _serviceProvider = serviceProvider;
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
|
||||
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
||||
await context.Database.EnsureCreatedAsync();
|
||||
|
||||
var manager =
|
||||
scope.ServiceProvider.GetRequiredService<IOpenIddictApplicationManager>();
|
||||
|
||||
if (await manager.FindByClientIdAsync("console") is null)
|
||||
{
|
||||
await manager.CreateAsync(new OpenIddictApplicationDescriptor
|
||||
{
|
||||
ClientId = "console",
|
||||
ClientSecret = "388D45FA-B36B-4988-BA59-B187D329C207",
|
||||
DisplayName = "My client application",
|
||||
Permissions =
|
||||
{
|
||||
Permissions.Endpoints.Token,
|
||||
Permissions.GrantTypes.ClientCredentials
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Before running the application, make sure the database is updated with OpenIddict tables by running `Add-Migration` and `Update-Database`.
|
13
guides/index.md
Normal file
13
guides/index.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Introduction
|
||||
|
||||
## What's OpenIddict?
|
||||
|
||||
OpenIddict was born in late 2015 and was initially based on **[AspNet.Security.OpenIdConnect.Server](https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server)**
|
||||
(codenamed ASOS), a low-level OpenID Connect server middleware forked from OWIN/Katana's `OAuthAuthorizationServerMiddleware`. In 2020, ASOS was merged into OpenIddict 3.0
|
||||
to form a unified stack under the OpenIddict umbrella, while still offering an easy-to-use approach for new users and a low-level experience for advanced users.
|
||||
|
||||
## Why an OpenID Connect server?
|
||||
|
||||
Adding an OpenID Connect server to your application **allows you to support token authentication**.
|
||||
It also allows you to manage all your users using local password or an external identity provider (e.g. Facebook or Google) for all your
|
||||
applications in one central place, with the power to control who can access your API and the information that is exposed to each client.
|
217
guides/migration/20-to-30.md
Normal file
217
guides/migration/20-to-30.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# Migrate to OpenIddict 3.0
|
||||
|
||||
## What's new?
|
||||
|
||||
The announcement listing the changes introduced in this milestone can be found [here](https://kevinchalet.com/2020/12/23/openiddict-3-0-general-availability/).
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Migrating to OpenIddict 3.0 requires making changes to your database**: existing properties have been reworked and new ones have been added to support the new features.
|
||||
|
||||
## Update your packages references
|
||||
|
||||
For that, update your `.csproj` file to reference the `OpenIddict.AspNetCore` 3.x metapackage:
|
||||
|
||||
```xml
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenIddict.AspNetCore" Version="3.1.1" />
|
||||
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="3.1.1" />
|
||||
</ItemGroup>
|
||||
```
|
||||
|
||||
## Ensure your application doesn't reference legacy/unsupported packages
|
||||
|
||||
As part of the AspNet.Security.OpenIdConnect.Server/OpenIddict merge, the ASOS packages and 2 OpenIddict packages have been marked as legacy
|
||||
and are no longer supported. Make sure your application (or intermediate libraries) don't reference any of these packages:
|
||||
|
||||
| Package name |
|
||||
|------------------------------------------|
|
||||
| AspNet.Security.OpenIdConnect.Extensions |
|
||||
| AspNet.Security.OpenIdConnect.Primitives |
|
||||
| AspNet.Security.OpenIdConnect.Server |
|
||||
| |
|
||||
| Owin.Security.OpenIdConnect.Extensions |
|
||||
| Owin.Security.OpenIdConnect.Server |
|
||||
| |
|
||||
| AspNet.Security.OAuth.Introspection |
|
||||
| AspNet.Security.OAuth.Validation |
|
||||
| |
|
||||
| Owin.Security.OAuth.Introspection |
|
||||
| Owin.Security.OAuth.Validation |
|
||||
| |
|
||||
| OpenIddict.Models |
|
||||
| OpenIddict.Mvc |
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If your application references the `OpenIdConnectConstants` class, update it to use `OpenIddictConstants` instead.
|
||||
|
||||
## Update the references to the Entity Framework Core/Entity Framework 6/MongoDB models
|
||||
|
||||
If your application references the `OpenIddictApplication`, `OpenIddictAuthorization`, `OpenIddictScope` or `OpenIddictToken` models, update these reference to use
|
||||
their new names: `OpenIddict[provider name]Application`, `OpenIddict[provider name]Authorization`, `OpenIddict[provider name]Scope` and `OpenIddict[provider name]Token`
|
||||
(e.g when using MongoDB: `OpenIddictMongoDbApplication`, `OpenIddictMongoDbAuthorization`, `OpenIddictMongoDbScope` and `OpenIddictMongoDbToken`).
|
||||
|
||||
## Enable ASP.NET Core integration in the server and validation options
|
||||
|
||||
With the base server and validation stacks being decoupled from ASP.NET Core, you now have to explicitly register the ASP.NET Core host in the server/validation options:
|
||||
|
||||
```csharp
|
||||
services.AddOpenIddict()
|
||||
.AddServer(options =>
|
||||
{
|
||||
options.UseAspNetCore();
|
||||
})
|
||||
.AddValidation(options =>
|
||||
{
|
||||
options.UseAspNetCore();
|
||||
});
|
||||
```
|
||||
|
||||
## Enable the authorization, logout and token endpoints pass-through mode
|
||||
|
||||
Unless you're using OpenIddict's events model to handle authorization, logout and token requests, you'll need to enable
|
||||
the pass-through mode for these endpoints, so that requests can reach your authorization controller as in the previous versions:
|
||||
|
||||
```csharp
|
||||
services.AddOpenIddict()
|
||||
.AddServer(options =>
|
||||
{
|
||||
options.UseAspNetCore()
|
||||
.EnableAuthorizationEndpointPassthrough()
|
||||
.EnableLogoutEndpointPassthrough()
|
||||
.EnableTokenEndpointPassthrough();
|
||||
});
|
||||
```
|
||||
|
||||
## Enable ASP.NET Core Data Protection support to ensure existing tokens can still be validated
|
||||
|
||||
For that, call `options.UseDataProtection()` in both the server and validation options:
|
||||
|
||||
```csharp
|
||||
services.AddOpenIddict()
|
||||
.AddServer(options =>
|
||||
{
|
||||
options.UseDataProtection();
|
||||
})
|
||||
.AddValidation(options =>
|
||||
{
|
||||
options.UseDataProtection();
|
||||
});
|
||||
```
|
||||
|
||||
## Use the new request caching APIs, if applicable
|
||||
|
||||
In 3.0, the `OpenIddictServerBuilder.EnableRequestCaching()` API - that enabled request caching for both authorization and logout request -
|
||||
was replaced by 2 separate methods. If your application depends on request caching, don't forget to enable it when migrating to 3.0:
|
||||
|
||||
```csharp
|
||||
services.AddOpenIddict()
|
||||
.AddServer(options =>
|
||||
{
|
||||
options.UseAspNetCore()
|
||||
.EnableAuthorizationRequestCaching()
|
||||
.EnableLogoutRequestCaching();
|
||||
});
|
||||
```
|
||||
|
||||
## Replace JSON.NET by `System.Text.Json`
|
||||
|
||||
If you use JSON.NET to serialize or deserialize `OpenIdConnectMessage`, `OpenIdConnectRequest` or `OpenIdConnectResponse` instances,
|
||||
consider moving to `System.Text.Json` when migrating to OpenIddict 3.0, as 3.0 no longer includes a built-in JSON.NET `JsonConverter` for their
|
||||
equivalent in 3.0 (i.e `OpenIddictMessage`, `OpenIddictRequest` and `OpenIddictResponse`).
|
||||
|
||||
In most cases, this should be as simple as replacing `JsonConvert.SerializeObject()`/`JsonConvert.DeserializeObject()`
|
||||
by their `System.Text.Json` equivalent: `JsonSerializer.Serialize()`/`JsonSerializer.Deserialize()`.
|
||||
|
||||
## Replace calls to the `AuthenticationTicket` extensions by their new `ClaimsPrincipal` equivalent:
|
||||
|
||||
OpenIddict 3.0 no longer uses the `AuthenticationTicket` type provided by ASP.NET Core. Instead, everything is now stored in the `ClaimsPrincipal` instance.
|
||||
If you have calls like `ticket.SetScopes()` or `ticket.SetResources()`, use their new equivalents (e.g `principal.SetScopes()` or `principal.SetResources()`).
|
||||
|
||||
## Use the new authentication schemes
|
||||
|
||||
In 3.0, the constants used as the ASP.NET Core authentication schemes have changed:
|
||||
|
||||
| Old constant name | New constant name (ASP.NET Core host) |
|
||||
|---------------------------------------------------|-------------------------------------------------------------|
|
||||
| OpenIddictServerDefaults.AuthenticationScheme | OpenIddictServerAspNetCoreDefaults.AuthenticationScheme |
|
||||
| OpenIddictValidationDefaults.AuthenticationScheme | OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme |
|
||||
| OAuthValidationDefaults.AuthenticationScheme | OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme |
|
||||
|
||||
> [!NOTE]
|
||||
> In 3.0, the OpenIddict server ASP.NET Core handler supports authenticating userinfo requests. As such, if you use the pass-through mode
|
||||
> to handle userinfo requests in your own userinfo MVC action, consider using `OpenIddictServerAspNetCoreDefaults.AuthenticationScheme`
|
||||
> instead of `OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme` for your userinfo endpoint to avoid validating access tokens twice.
|
||||
|
||||
## Update your application to work with the new `scope` format
|
||||
|
||||
In OpenIddict 3.0, the format of the `scope` claim used in JWT tokens has changed from a JSON array to a single space-separated claim
|
||||
to match [the JWT access token specification](https://datatracker.ietf.org/doc/html/rfc9068). To ensure your authorization policies
|
||||
still work after migrating, consider using the `principal.HasScope()` extension to determine whether a scope has been granted:
|
||||
|
||||
```csharp
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
options.AddPolicy("MyPolicy", builder =>
|
||||
{
|
||||
builder.RequireAuthenticatedUser();
|
||||
builder.RequireAssertion(context => context.User.HasScope("api1"));
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Alternatively, you can use the check the presence of the private OpenIddict `oi_scp` claims that use the same format as in 2.x (i.e one claim per scope value):
|
||||
|
||||
```csharp
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
options.AddPolicy("MyPolicy", builder =>
|
||||
{
|
||||
builder.RequireAuthenticatedUser();
|
||||
builder.RequireClaim(Claims.Private.Scope, "api1");
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> These 2 options only work with the OpenIddict validation handler as the `oi_scp` claims are not populated by the JWT bearer handler developped by Microsoft.
|
||||
> If you can't migrate to the OpenIddict validation handler, consider splitting the standard `scope` claim manually to determine whether it contains a specific value.
|
||||
|
||||
## Add and apply migrations, if necessary
|
||||
|
||||
If your application uses Entity Framework Core or Entity Framework 6, add a migration to react to the schema changes listed below and apply it.
|
||||
|
||||
### Updated properties
|
||||
|
||||
| Table | Column name | Observations |
|
||||
|--------------------------|----------------|-----------------------------------------------------------------------------|
|
||||
| OpenIddictAuthorizations | Subject | The column is now nullable to support the device authorization flow. |
|
||||
| OpenIddictTokens | CreationDate | For broader database support, this column is a now a `DateTime` instance. |
|
||||
| OpenIddictTokens | ExpirationDate | For broader database support, this column is a now a `DateTime` instance. |
|
||||
| OpenIddictTokens | Subject | The column is now nullable to support the device authorization flow. |
|
||||
|
||||
### Added properties
|
||||
|
||||
| Table | Column name | Type | Nullable |
|
||||
|--------------------------|----------------|----------|----------|
|
||||
| OpenIddictAuthorizations | CreationDate | DateTime | Yes |
|
||||
| OpenIddictTokens | RedemptionDate | DateTime | Yes |
|
||||
|
||||
## If necessary, enable hybrid flow support in the server options
|
||||
|
||||
In 2.0, the hybrid flow was automatically enabled if both the authorization code and implicit flows were enabled. In 3.0, this is no longer true
|
||||
and the hybrid flow MUST be explicitly opted in. If you use the hybrid flow, make sure your application calls the `options.AllowHybridFlow()` method:
|
||||
|
||||
```csharp
|
||||
services.AddOpenIddict()
|
||||
.AddServer(options =>
|
||||
{
|
||||
options.AllowHybridFlow();
|
||||
});
|
||||
```
|
||||
|
||||
## Update your applications to grant them the appropriate response type permissions
|
||||
|
||||
New response type permissions - enforced by default - [have been introduced in 3.0](/configuration/application-permissions.html#response-type-permissions).
|
||||
|
||||
If you have many applications to migrate, you can use [this script](https://github.com/openiddict/openiddict-core/issues/1138#issuecomment-713681158)
|
||||
to infer appropriate response type permissions using the already granted grant types.
|
20
guides/toc.yml
Normal file
20
guides/toc.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
- name: Introduction
|
||||
href: index.md
|
||||
|
||||
- name: Getting started
|
||||
href: getting-started.md
|
||||
|
||||
- name: Choosing the right flow
|
||||
href: choosing-the-right-flow.md
|
||||
|
||||
- name: Migration guides
|
||||
items:
|
||||
- name: Migration from 2.0 to 3.0
|
||||
href: migration/20-to-30.md
|
||||
|
||||
- name: External resources
|
||||
items:
|
||||
- name: OAuth 2.0 specification
|
||||
href: https://tools.ietf.org/html/rfc6749
|
||||
- name: OpenID Connect specification
|
||||
href: https://openid.net/specs/openid-connect-core-1_0.html
|
Reference in New Issue
Block a user