From 20d0ccf34cdc5b47a6d3afa8e8ea6509469c390b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Thu, 1 Feb 2018 16:58:04 +0100 Subject: [PATCH] Add the OpenIddict RC2 migration guide page --- guide/migration.md | 185 +++++++++++++++++++++++++++++++++++++++++++++ guide/toc.yml | 2 + toc.yml | 3 + 3 files changed, 190 insertions(+) create mode 100644 guide/migration.md diff --git a/guide/migration.md b/guide/migration.md new file mode 100644 index 0000000..c37c1d0 --- /dev/null +++ b/guide/migration.md @@ -0,0 +1,185 @@ +# What's new in OpenIddict RC2? + +The full list of changes can be found [here](https://github.com/openiddict/openiddict-core/milestone/8?closed=1). It includes **bug fixes** (including a bug fix in the refresh token handling) and new features like **application permissions**, that allow limiting the OpenID Connect features (endpoints and flows) an application is able to use. + +# Migrate to OpenIddict RC2 + +**Migrating to OpenIddict RC2 (`1.0.0-rc2-*` and `2.0.0-rc2-*`) requires making changes in your database**: existing properties have been reworked (e.g [to work around a MySQL limitation](https://github.com/openiddict/openiddict-core/issues/497)) and new ones have been added to support the new features. This procedure is quite easy and only requires a few minutes. + +> Note: this guide assumes your application uses the OpenIddict Entity Framework Core 2.x stores. If you use a custom store, changes will have to be made manually. A list of added/updated/renamed columns is available at the end of this guide. + +## Ensure migrations are correctly enabled for your project + +**Before migrating to OpenIddict RC2, make sure migrations are already enabled for your application**. If you have a `Migrations` folder in your application root folder and an `__EFMigrationsHistory` table in your database, you're good to go. + +If you don't have these Entity Framework Core artificats, migrations are likely not enabled. To fix that, add the following entries in your `.csproj`: + +```xml + + + + + + + +``` + +Then, open a new command line and add an initial migration using `dotnet ef migrations add InitialMigration` (**but don't apply it!**). + +## Update your packages references + +For that, simply update your `.csproj` file to point to the newest OpenIddict packages: + +### ASP.NET Core 1.x + +```xml + + + + + +``` + +### ASP.NET Core 2.x + +```xml + + + + + +``` + +## Add a new migration + +1. First, open a new command line and run `dotnet ef migrations add MigrateToOpenIddictRc2`. +2. **If you created an initial migration at step 1, remove it from the `Migrations` folder**. +3. Apply the `MigrateToOpenIddictRc2` migration using `dotnet ef database update MigrateToOpenIddictRc2`. + +## Run the migration script to convert columns to the new format + +For that, add the following snippet to your `Startup` class: + +```csharp +private async Task UpdateOpenIddictTablesAsync(IServiceProvider services) +{ + using (var scope = services.GetRequiredService().CreateScope()) + { + // Change ApplicationDbContext to match your context name if you've changed it. + var context = scope.ServiceProvider.GetRequiredService(); + await context.Database.EnsureCreatedAsync(); + + // If you use a different entity type or a custom key, + // change this line (e.g OpenIddictApplication). + foreach (var application in context.Set()) + { + // Convert the space-separated PostLogoutRedirectUris property to JSON. + if (!string.IsNullOrEmpty(application.PostLogoutRedirectUris) && + application.PostLogoutRedirectUris[0] != '[') + { + var addresses = application.PostLogoutRedirectUris.Split( + new[] { " " }, StringSplitOptions.RemoveEmptyEntries); + + application.PostLogoutRedirectUris = + new JArray(addresses).ToString(Formatting.None); + } + + // Convert the space-separated RedirectUris property to JSON. + if (!string.IsNullOrEmpty(application.RedirectUris) && + application.RedirectUris[0] != '[') + { + var addresses = application.RedirectUris.Split( + new[] { " " }, StringSplitOptions.RemoveEmptyEntries); + + application.RedirectUris = new JArray(addresses).ToString(Formatting.None); + } + + // Grant the application all the permissions. Don't hesitate to update + // the list to only grant the permissions really needed by the application. + if (string.IsNullOrEmpty(application.Permissions)) + { + var permissions = new[] + { + OpenIddictConstants.Permissions.Endpoints.Authorization, + OpenIddictConstants.Permissions.Endpoints.Introspection, + OpenIddictConstants.Permissions.Endpoints.Logout, + OpenIddictConstants.Permissions.Endpoints.Revocation, + OpenIddictConstants.Permissions.Endpoints.Token, + + OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, + OpenIddictConstants.Permissions.GrantTypes.ClientCredentials, + OpenIddictConstants.Permissions.GrantTypes.Implicit, + OpenIddictConstants.Permissions.GrantTypes.Password, + OpenIddictConstants.Permissions.GrantTypes.RefreshToken + }; + + application.Permissions = new JArray(permissions).ToString(Formatting.None); + } + } + + // If you use a different entity type or a custom key, + // change this line (e.g OpenIddictAuthorization). + foreach (var authorization in context.Set()) + { + // Convert the space-separated Scopes property to JSON. + if (!string.IsNullOrEmpty(authorization.Scopes) && authorization.Scopes[0] != '[') + { + var scopes = authorization.Scopes.Split( + new[] { " " }, StringSplitOptions.RemoveEmptyEntries); + + authorization.Scopes = new JArray(scopes).ToString(Formatting.None); + } + } + + await context.SaveChangesAsync(); + } +} +``` + +Then, at the end of the `public void Configure(IApplicationBuilder app)` method, add the following line: + +```csharp +public void Configure(IApplicationBuilder app) +{ + app.UseDeveloperExceptionPage(); + + app.UseStaticFiles(); + + app.UseStatusCodePagesWithReExecute("/error"); + + app.UseAuthentication(); + + app.UseMvcWithDefaultRoute(); + + // Run the migration script synchronously. + UpdateOpenIddictTablesAsync(app.ApplicationServices).GetAwaiter().GetResult(); +} + +``` + +Run your application. Once it's correctly started, stop it and remove the migration script. + +## List of changes (for applications using custom stores) + +### Renamed properties + +| Table | Old column name | New column name | Observations | +|--------------------------|-----------------|------------------|----------------------------------------------------------------------------| +| OpenIddictApplications | Timestamp | ConcurrencyToken | The column type was changed to nvarchar to work around a MySQL limitation. | +| OpenIddictAuthorizations | Timestamp | ConcurrencyToken | The column type was changed to nvarchar to work around a MySQL limitation. | +| OpenIddictScopes | Timestamp | ConcurrencyToken | The column type was changed to nvarchar to work around a MySQL limitation. | +| OpenIddictTokens | Timestamp | ConcurrencyToken | The column type was changed to nvarchar to work around a MySQL limitation. | +| OpenIddictTokens | Ciphertext | Payload | | +| OpenIddictTokens | Hash | ReferenceId | | + +### Added properties + +| Table | Column name | Type | Nullable | +|--------------------------|-------------|---------------|----------| +| OpenIddictApplications | Properties | nvarchar(max) | Yes | +| OpenIddictApplications | Permissions | nvarchar(max) | Yes | +| OpenIddictAuthorizations | Properties | nvarchar(max) | Yes | +| OpenIddictScopes | Properties | nvarchar(max) | Yes | +| OpenIddictTokens | Properties | nvarchar(max) | Yes | \ No newline at end of file diff --git a/guide/toc.yml b/guide/toc.yml index 806603b..0790f98 100644 --- a/guide/toc.yml +++ b/guide/toc.yml @@ -2,5 +2,7 @@ href: index.md - name: Getting started href: getting-started.md +- name: Migration guide + href: migration.md - name: Samples href: samples.md \ No newline at end of file diff --git a/toc.yml b/toc.yml index 4d30452..c23aaac 100644 --- a/toc.yml +++ b/toc.yml @@ -1,2 +1,5 @@ - name: User guide href: guide/index.md + +- name: Migration guide + href: guide/migration.md \ No newline at end of file