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

Removal of OpenIddict.Models in OpenIddict RC3 #608

Closed
kevinchalet opened this issue May 28, 2018 · 11 comments
Closed

Removal of OpenIddict.Models in OpenIddict RC3 #608

kevinchalet opened this issue May 28, 2018 · 11 comments

Comments

@kevinchalet
Copy link
Member

Starting with RC3, OpenIddict will no longer come with a default set of entities and stores base classes.

Why?

In the previous iterations of OpenIddict, an important effort was made to create a shared set of entities (contained in the OpenIddict.Models package) that could be used not only by the official Entity Framework 6.x and Entity Framework Core stores, but also by third-party/custom stores.

This pattern had many pros - like avoiding code duplication or having base classes that simplify the development of custom stores (which is why it was also eventually adopted by the ASP.NET team for ASP.NET Core Identity in 2.0).

Unfortunately, this approach had also a major issue: we had to design the default entities as "lowest common denominators", so that they could be used by all/most ORMs or document databases. In practice, this meant that things like OpenIddictApplication.RedirectUris or OpenIddictApplication.PostLogoutRedirectUris had to be represented as JSON-serialized strings for SQL-oriented ORMs like EF 6.x and EF Core to work natively.

In the document databases world, entities are generally schema-less, which offers a greater flexibility. A NoSQL database like MongoDB can easily store and efficiently index JSON arrays, which means OpenIddictApplication.RedirectUris/PostLogoutRedirectUris are best represented as arrays of strings (string[]).

The conclusion was clear: we couldn't have the best performance by using non-optimized entities.

What will change?

In RC3, each stores package will come with its own models you'll be able to use exactly like in the previous iterations.

How do I update my code?

First, make sure you don't reference the obsolete OpenIddict.Models or OpenIddict.Stores packages. The new models are automatically referenced by the stores packages they belong to and you don't need to add any reference to use them.

Then, update your Startup.ConfigureServices() method to use the new helpers. For instance:

services.AddOpenIddict()

    // Register the OpenIddict core services.
    .AddCore(options =>
    {
        options.UseEntityFrameworkCore()
               .UseDbContext<ApplicationDbContext>();
    });

If you prefer using long as the key type (with the default entities), use ReplaceDefaultEntities:

services.AddOpenIddict()

    // Register the OpenIddict core services.
    .AddCore(options =>
    {
        options.UseEntityFrameworkCore()
               .UseDbContext<ApplicationDbContext>()
               .ReplaceDefaultEntities<long>();
    })

If you want to use your own entities instead of the default EF Core ones:

services.AddOpenIddict()

    // Register the OpenIddict core services.
    .AddCore(options =>
    {
        options.UseEntityFrameworkCore()
               .UseDbContext<ApplicationDbContext>()
               .ReplaceDefaultEntities<MyApp, MyAuth, MyScope, MyToken, long>();
    })
@daveyjay
Copy link

Just wondering when will the samples be updated to reflect this change?

I am having some trouble migration from rc2 - when calling services.AddOpenIddict, where do I put the additional calls to methods such as AddMvcBinders, RegisterScopes, SetAccessTokenLifetime etc.?

These methods are not available on the options object inside the the AddOpenIddict method or the AddCore method.

For example, inside of AddOpenIddict it used to look like this:

{               
                // options.AddEntityFrameworkCoreStores<MyDbContext>();   old code replaced in rc3 with example above


                // Register the ASP.NET Core MVC binder used by OpenIddict.
                // Note: if you don't call this method, you won't be able to
                // bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
                options.AddMvcBinders();

                options.EnableAuthorizationEndpoint("/connect/authorize")
                    .EnableLogoutEndpoint("/connect/logout")
                    .EnableIntrospectionEndpoint("/connect/introspect")
                    .EnableUserinfoEndpoint("/connect/userinfo");

                // Mark the "email", "profile" and "roles" scopes as supported scopes.
                options.RegisterScopes(OpenIdConnectConstants.Scopes.Email,
                    OpenIdConnectConstants.Scopes.Profile,
                    OpenIdConnectConstants.Scopes.OpenId);

                // Enable scope validation, so that authorization and token requests
                // that specify unregistered scopes are automatically rejected.
                options.EnableScopeValidation();

                options.SetAccessTokenLifetime(TimeSpan.FromMinutes(20)); 

                options.AllowImplicitFlow();

                // During development, you can disable the HTTPS requirement.
                options.DisableHttpsRequirement();
                // On production, using a X.509 certificate stored in the machine store is recommended.
                // You can generate a self-signed certificate using Pluralsight's self-cert utility:
                // https://s3.amazonaws.com/pluralsight-free/keith-brown/samples/SelfCert.zip
                //
                // services.AddOpenIddict()
                //     .AddSigningCertificate("7D2A741FE34CC2C7369237A5F2078988E17A6A75");
                //
                // Alternatively, you can also store the certificate as an embedded .pfx resource
                // directly in this assembly or in a file published alongside this project:
                //
                // services.AddOpenIddict()
                //     .AddSigningCertificate(
                //          assembly: typeof(Startup).GetTypeInfo().Assembly,
                //          resource: "AuthorizationServer.Certificate.pfx",
                //          password: "OpenIddict");

                // Register a new ephemeral key, that is discarded when the application
                // shuts down. Tokens signed using this key are automatically invalidated.
                // This method should only be used during development.
                options.AddEphemeralSigningKey();
                // Note: to use JWT access tokens instead of the default
                // encrypted format, the following line is required:
                options.UseJsonWebTokens();
            });```

@kevinchalet
Copy link
Member Author

kevinchalet commented May 29, 2018

@daveyjay the samples will be updated as soon as RC3 is on NuGet.org.

Don't miss #593, it includes all the details you need to migrate to the new builders APIs.

@kevinchalet
Copy link
Member Author

Note that the samples hosted in this repository target RC3: https://github.com/openiddict/openiddict-core/blob/dev/samples/Mvc.Server/Startup.cs

@daveyjay
Copy link

Thank you! I had missed #593 and the sample code helped as well. I was able to get everything to work. (I'm using the implicit flow and JWTs). I will check back to see the updated sample code for implicit flow when it is available later.

FYI - one difference I noted in the sample code as compared with #593 is that the line:
options.AddMvcBinders();
is now changed to:
options.UseMvc();

@sethen
Copy link

sethen commented May 30, 2018

@PinpointTownes What do you make of this error? This is happening on dotnet run after a successful build:

Unhandled Exception: System.InvalidOperationException: No service for type 'OpenIddict.Core.OpenIddictApplicationManager`1[OpenIddict.EntityFrameworkCore.Models.OpenIddictApplication]' has been registered.

My code looks pretty identical to the example you've shared as well.

@kevinchalet
Copy link
Member Author

@daveyjay nice catch. I'll update #593.

@sethen did you forget to call services.AddOpenIddict().AddCore()?

@sethen
Copy link

sethen commented May 30, 2018

@PinpointTownes That certainly got me closer because I wasn't calling it. After adding that bit of code that you suggested and running I am getting another error that reads like this:

Time Elapsed 00:00:02.24
fail: Microsoft.EntityFrameworkCore.Database.Command[200102]
      Failed executing DbCommand (20ms) [Parameters=[@__identifier='?'], CommandType='Text', CommandTimeout='30']
      SELECT "application"."Id", "application"."ClientId", "application"."ClientSecret", "application"."ConcurrencyToken", "application"."ConsentType", "application"."DisplayName", "application"."Permissions", "application"."PostLogoutRedirectUris", "application"."Properties", "application"."RedirectUris", "application"."Type"
      FROM "OpenIddictApplications" AS "application"
      WHERE "application"."ClientId" = @__identifier
      LIMIT 1
Npgsql.PostgresException (0x80004005): 42703: column application.ConsentType does not exist

Is there some option I am missing?

@kevinchalet
Copy link
Member Author

Is there some option I am missing?

Are you migrating from an old OpenIddict version (e.g RC1?). If so, you'll have to update your DB schema. Read https://openiddict.github.io/openiddict-documentation/guide/migration.html for more information.

@sethen
Copy link

sethen commented May 30, 2018

Ohhhhh, yeah I am. Thanks.

@sethen
Copy link

sethen commented May 31, 2018

@PinpointTownes All I did was make the migrations, run the migrations and all is well -- there are additional steps... are these necessary? It looks like everything is working properly without them.

@kevinchalet
Copy link
Member Author

kevinchalet commented Jun 1, 2018

@sethen you should run the migration script to convert existing DB entries to the new denormalized JSON model. If you don't do that, you may see exceptions at runtime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants