Search code examples
c#asp.netopeniddict

Cannot use table 'OpenIddictApplications' in schema '' for entity 'OpenIddictApplication' since it is being used for another entity


I am trying to get a token from asp.net core app using OpenIddict.

When I request a token from my endpoint, I am getting this exception:

System.InvalidOperationException: Cannot use table 'OpenIddictApplications' in schema '' for entity 'OpenIddictApplication' since it is being used for another entity.
   at Microsoft.EntityFrameworkCore.Internal.ModelValidator.ShowError(String message)
   at Microsoft.EntityFrameworkCore.Internal.RelationalModelValidator.EnsureDistinctTableNames(IModel model)
   at Microsoft.EntityFrameworkCore.Internal.RelationalModelValidator.Validate(IModel model)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
   at Microsoft.EntityFrameworkCore.Internal.LazyRef`1.get_Value()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass16_0.<RealizeService>b__0(ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServiceCollectionExtensions.<>c.<AddQuery>b__1_3(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass16_0.<RealizeService>b__0(ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.DbContext.get_QueryProvider()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.<.ctor>b__3_0()
   at Microsoft.EntityFrameworkCore.Internal.LazyRef`1.get_Value()
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Linq.IQueryable.get_Provider()
   at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
   at OpenID.Controllers.AuthorizeController.<Exchange>d__2.MoveNext() in C:\Users\Enrique_Garcia\Desktop\OpenID\OpenID\Controllers\AuthorizeController.cs:line 35
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__25.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextResourceFilter>d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
....

I have already seen this but I am not using Asp.Net Identity.

ConfigureServices:

 public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc();
        services.AddDbContext<UniverContext>(options =>
        {
            options.UseSqlServer(Configuration["Data:ConnectionString"]);
            options.UseOpenIddict();
        });

        services.AddOpenIddict(options =>
        {
            options.AddEntityFrameworkCoreStores<UniverContext>();
            options.AddMvcBinders();
            options.EnableTokenEndpoint("/connect/token");
            options.AllowPasswordFlow().AllowRefreshTokenFlow();
            options.SetAccessTokenLifetime(TimeSpan.FromMinutes(1));
            options.SetRefreshTokenLifetime(TimeSpan.FromMinutes(2));
            options.DisableHttpsRequirement();
            options.UseJsonWebTokens();
            options.AddEphemeralSigningKey();
        });
    }

Configure:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
  ILoggerFactory loggerFactory)
    {
        app.UseDeveloperExceptionPage();
        app.UseOpenIddict();

        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();

        app.UseJwtBearerAuthentication(new JwtBearerOptions
        {
            Authority = "http://localhost:5000",
            Audience = "resource_server",
            RequireHttpsMetadata = false,
            TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = OpenIdConnectConstants.Claims.Subject,
                RoleClaimType = OpenIdConnectConstants.Claims.Role
            }
        });

        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseMvcWithDefaultRoute();
        app.UseWelcomePage();
    }

This is my UniverContext class:

public partial class UniverContext : DbContext
{
    public virtual DbSet<Alumno> Alumno { get; set; }
    public virtual DbSet<AlumnoInscrito> AlumnoInscrito { get; set; }
    public virtual DbSet<Genero> Genero { get; set; }
    public virtual DbSet<OfertaEducativa> OfertaEducativa { get; set; }
    public virtual DbSet<OpenIddictApplications> OpenIddictApplications { get; set; }
    public virtual DbSet<OpenIddictAuthorizations> OpenIddictAuthorizations { get; set; }
    public virtual DbSet<OpenIddictScopes> OpenIddictScopes { get; set; }
    public virtual DbSet<OpenIddictTokens> OpenIddictTokens { get; set; }
    public virtual DbSet<Usuario> Usuario { get; set; }
    public virtual DbSet<UsuarioDetalle> UsuarioDetalle { get; set; }

    public UniverContext(DbContextOptions<UniverContext> options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        //modelBuilder.UseOpenIddict();

        modelBuilder.Entity<Alumno>(entity =>
        {
            entity.HasIndex(e => e.GeneroId)
                .HasName("IX_Alumno_GeneroId");

            entity.Property(e => e.AlumnoId).ValueGeneratedNever();

            entity.Property(e => e.GeneroId).HasDefaultValueSql("0");

            entity.Property(e => e.Nombre).IsRequired();

            entity.HasOne(d => d.Genero)
                .WithMany(p => p.Alumno)
                .HasForeignKey(d => d.GeneroId);
        });

        modelBuilder.Entity<AlumnoInscrito>(entity =>
        {
            entity.HasKey(e => new { e.AlumnoId, e.OfertaEducativaId })
                .HasName("PK_AlumnoInscrito");

            entity.HasIndex(e => e.OfertaEducativaId)
                .HasName("IX_AlumnoInscrito_OfertaEducativaId");

            entity.HasOne(d => d.Alumno)
                .WithMany(p => p.AlumnoInscrito)
                .HasForeignKey(d => d.AlumnoId);

            entity.HasOne(d => d.OfertaEducativa)
                .WithMany(p => p.AlumnoInscrito)
                .HasForeignKey(d => d.OfertaEducativaId);

            entity.HasOne(d => d.Usuario)
                .WithMany(p => p.AlumnoInscrito)
                .HasForeignKey(d => d.UsuarioId)
                .OnDelete(DeleteBehavior.Restrict)
                .HasConstraintName("FK_AlumnoInscrito_Usuario");
        });

        modelBuilder.Entity<Genero>(entity =>
        {
            entity.Property(e => e.GeneroId).ValueGeneratedNever();

            entity.Property(e => e.Descripcion).IsRequired();
        });

        modelBuilder.Entity<OfertaEducativa>(entity =>
        {
            entity.Property(e => e.OfertaEducativaId).ValueGeneratedNever();

            entity.Property(e => e.Descripcion).IsRequired();
        });

        modelBuilder.Entity<OpenIddictApplications>(entity =>
        {
            entity.HasIndex(e => e.ClientId)
                .HasName("IX_OpenIddictApplications_ClientId")
                .IsUnique();

            entity.Property(e => e.Id).HasMaxLength(450);

            entity.Property(e => e.ClientId)
                .IsRequired()
                .HasMaxLength(450);
        });

        modelBuilder.Entity<OpenIddictAuthorizations>(entity =>
        {
            entity.HasIndex(e => e.ApplicationId)
                .HasName("IX_OpenIddictAuthorizations_ApplicationId");

            entity.Property(e => e.Id).HasMaxLength(450);

            entity.Property(e => e.ApplicationId).HasMaxLength(450);

            entity.HasOne(d => d.Application)
                .WithMany(p => p.OpenIddictAuthorizations)
                .HasForeignKey(d => d.ApplicationId);
        });

        modelBuilder.Entity<OpenIddictScopes>(entity =>
        {
            entity.Property(e => e.Id).HasMaxLength(450);
        });

        modelBuilder.Entity<OpenIddictTokens>(entity =>
        {
            entity.HasIndex(e => e.ApplicationId)
                .HasName("IX_OpenIddictTokens_ApplicationId");

            entity.HasIndex(e => e.AuthorizationId)
                .HasName("IX_OpenIddictTokens_AuthorizationId");

            entity.Property(e => e.Id).HasMaxLength(450);

            entity.Property(e => e.ApplicationId).HasMaxLength(450);

            entity.Property(e => e.AuthorizationId).HasMaxLength(450);

            entity.HasOne(d => d.Application)
                .WithMany(p => p.OpenIddictTokens)
                .HasForeignKey(d => d.ApplicationId);

            entity.HasOne(d => d.Authorization)
                .WithMany(p => p.OpenIddictTokens)
                .HasForeignKey(d => d.AuthorizationId);
        });

        modelBuilder.Entity<Usuario>(entity =>
        {
            entity.Property(e => e.UsuarioId).HasDefaultValueSql("0");

            entity.Property(e => e.Nombre).IsRequired();

            entity.Property(e => e.Paterno)
                .IsRequired()
                .HasDefaultValueSql("N''");
        });

        modelBuilder.Entity<UsuarioDetalle>(entity =>
        {
            entity.HasKey(e => e.UsuarioId)
                .HasName("PK_UsuarioDetalle");

            entity.Property(e => e.UsuarioId).ValueGeneratedNever();

            entity.Property(e => e.Password)
                .IsRequired()
                .HasColumnType("varchar(50)");

            entity.HasOne(d => d.Usuario)
                .WithOne(p => p.UsuarioDetalle)
                .HasForeignKey<UsuarioDetalle>(d => d.UsuarioId)
                .OnDelete(DeleteBehavior.Restrict)
                .HasConstraintName("FK_UsuarioDetalle_Usuario");
        });
    }
}

And what my csproj file contains is:

<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<AspNetContribOpenIdExtensionsVersion>1.0.0-*</AspNetContribOpenIdExtensionsVersion>
<OpenIddictVersion>1.0.0-*</OpenIddictVersion>
<PackageTargetFallback>portable-net45+win8</PackageTargetFallback>
</PropertyGroup>

<PackageReference Include="AspNet.Security.OAuth.Validation" Version="1.0.0-rtm-0255" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.1.0" />
<PackageReference Include="OpenIddict" Version="$(OpenIddictVersion)" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="$(OpenIddictVersion)" />
<PackageReference Include="OpenIddict.Mvc" Version="$(OpenIddictVersion)" />

The packages openiddict version's is 1.0.0-beta2-0607

What I was trying and it works is this is my AuthorizationController:

 if (request.Username != "[email protected]")
            {
                return BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The username/password couple is invalid"
                });
            }

            if (request.Password != "123456+")
            {
                return BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The username/password couple is invalid"
                });
            }

But after register my DbContext in Startup class, I am trying to use database user's something like:

 var user = _context.Usuario.SingleOrDefault(x => x.UsuarioId == int.Parse(request.Username));

In this line, I am getting the error described.

I created a repo if you want to see my AuthorizationController.


Solution

  • The exception sounds clear to me: OpenIddict registers the default entities when you call options.AddOpenIddict() but your own DbContext defines different entities that end up using the same table names (OpenIddictApplications/OpenIddictAuthorizations/OpenIddictScopes/OpenIddictTokens), which is considered as an illegal operation by EntityFramework, given that the entity types differ.

    You have two options to fix that:

    • Use the default OpenIddict entities (e.g OpenIddictApplication vs OpenIddictApplications).
    • Tell OpenIddict that you prefer using your own entities instead of the built-in ones:

    // Register the OpenIddict services.
    services.AddOpenIddict(options =>
    {
        options.UseEntityFrameworkCore()
               .UseDbContext<ApplicationDbContext>()
               .ReplaceDefaultEntities<OpenIddictApplications, OpenIddictAuthorizations, OpenIddictScopes, OpenIddictTokens, string>();
    
        // ...
    });