04. PART 3 IdentityServer4 ASP.NET Core Identity .NET Core 3.1
You can find the project here.
Test data
In order to start playing with the IdentityServer4, later on, we must populate test config and user data into our database tables. Without it, we can’t start using the IdentityServer4. Changes are pretty straight forward and require adding the seed data in code and adding a setting in appsettings. When seeding is enabled the application will start, create the database, run the migrations to create both IdentityServer4 and ASP.NET Core Identity tables and populate the test data for configuration (resources and clients) and user data (users and claims).
Add test configuration and users
I will continue with the “Quickstart” solution from the previous tutorial. Open the solution and navigate to the “Data” folder. Open “IdentityDbContext.cs” and below “OnModelCreating” method create “UserSeed” method like so:
private void UsersSeed(ModelBuilder builder) { var password = "My long 123$ password"; var alice = new ApplicationUser { Id = "1", UserName = "alice", NormalizedUserName = "ALICE", Email = "AliceSmith@email.com", NormalizedEmail = "AliceSmith@email.com".ToUpper(), EmailConfirmed = true }; alice.PasswordHash = new PasswordHasher<ApplicationUser>().HashPassword(alice, password); var bob = new ApplicationUser { Id = "2", UserName = "bob", NormalizedUserName = "BOB", Email = "BobSmith@email.com", NormalizedEmail = "bobsmith@email.com".ToUpper(), EmailConfirmed = true, }; bob.PasswordHash = new PasswordHasher<ApplicationUser>().HashPassword(bob, password); builder.Entity<ApplicationUser>() .HasData(alice, bob); builder.Entity<IdentityUserClaim<string>>() .HasData( new IdentityUserClaim<string> { Id = 1, UserId = "1", ClaimType = "name", ClaimValue = "Alice Smith" }, new IdentityUserClaim<string> { Id = 2, UserId = "1", ClaimType = "given_name", ClaimValue = "Alice" }, new IdentityUserClaim<string> { Id = 3, UserId = "1", ClaimType = "family_name", ClaimValue = "Smith" }, new IdentityUserClaim<string> { Id = 4, UserId = "1", ClaimType = "email", ClaimValue = "AliceSmith@email.com" }, new IdentityUserClaim<string> { Id = 5, UserId = "1", ClaimType = "website", ClaimValue = "http://alice.com" }, new IdentityUserClaim<string> { Id = 6, UserId = "2", ClaimType = "name", ClaimValue = "Bob Smith" }, new IdentityUserClaim<string> { Id = 7, UserId = "2", ClaimType = "given_name", ClaimValue = "Bob" }, new IdentityUserClaim<string> { Id = 8, UserId = "2", ClaimType = "family_name", ClaimValue = "Smith" }, new IdentityUserClaim<string> { Id = 9, UserId = "2", ClaimType = "email", ClaimValue = "BobSmith@email.com" }, new IdentityUserClaim<string> { Id = 10, UserId = "2", ClaimType = "website", ClaimValue = "http://bob.com" }, new IdentityUserClaim<string> { Id = 11, UserId = "1", ClaimType = "email_verified", ClaimValue = true.ToString() }, new IdentityUserClaim<string> { Id = 12, UserId = "2", ClaimType = "email_verified", ClaimValue = true.ToString() }, new IdentityUserClaim<string> { Id = 13, UserId = "1", ClaimType = "address", ClaimValue = @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }" }, new IdentityUserClaim<string> { Id = 14, UserId = "2", ClaimType = "address", ClaimValue = @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }" }, new IdentityUserClaim<string> { Id = 15, UserId = "1", ClaimType = "location", ClaimValue = "somewhere" }); }
After this we need to call “UserSeed” method in “OnModelCreating” like so:
protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); //seed data UsersSeed(builder); }
and also we need to add migration:
Add-Migration SeedIdentityDbMigration -c IdentityDbContext -o Data/Migrations/AspNetIdentity/AspNetIdentityDb
For Client data seed we need to create our own class that will inherit from IdentityServer4 “ConfigurationDbContext” class. Navigate to “Data” folder and add new class called “ConfigurationDbContext” like :
using IdentityModel; using IdentityServer4.EntityFramework.Entities; using IdentityServer4.EntityFramework.Extensions; using IdentityServer4.EntityFramework.Options; using Microsoft.EntityFrameworkCore; using System; namespace IdentityServer.Data { public class ConfigurationDbContext : IdentityServer4.EntityFramework.DbContexts.ConfigurationDbContext<ConfigurationDbContext> { private readonly ConfigurationStoreOptions _storeOptions; public ConfigurationDbContext(DbContextOptions<ConfigurationDbContext> options, ConfigurationStoreOptions storeOptions) : base(options, storeOptions) { _storeOptions = storeOptions; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.ConfigureClientContext(_storeOptions); modelBuilder.ConfigureResourcesContext(_storeOptions); base.OnModelCreating(modelBuilder); } } }
After this we need to register our “ConfigurationDbContext” in “Startup.cs”. Add this below “IdentityDbContext” registration :
services.AddDbContext<Data.ConfigurationDbContext>(options => options.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly)));
Because we will use our child class “ConfigurationDbContext” instead of parent one coming from IdentityServer4 directly we need to drop the existing local database “IdentityServerQuickstart.NetCore3.1” to avoid possible table collisions. We also need to navigate to “Data/Migrations/IdentityServer” and delete “ConfigurationDb” folder. Next step is to add new configuration migration using our “ConfigurationDbContext” class like so:
Add-Migration InitialConfigurationMigration -c IdentityServer.Data.ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
Next step is to add “ClientSeed” method. In “ConfigurationDbContext.cs” file right below “OnModelCreating” method add new method “ClientSeed” like:
private void ClientSeed(ModelBuilder builder) { builder.Entity<ApiResource>() .HasData( new ApiResource { Id = 1, Name = "web_api", DisplayName = "My Web API" } ); builder.Entity<ApiScope>() .HasData( new ApiScope { Id = 1, Name = "web_api", DisplayName = "web_api", Description = null, Required = false, Emphasize = false, ShowInDiscoveryDocument = true, ApiResourceId = 1 } ); builder.Entity<IdentityResource>().HasData ( new IdentityResource() { Id = 1, Enabled = true, Name = "openid", DisplayName = "Your user identifier", Description = null, Required = true, Emphasize = false, ShowInDiscoveryDocument = true, Created = DateTime.UtcNow, Updated = null, NonEditable = false }, new IdentityResource() { Id = 2, Enabled = true, Name = "profile", DisplayName = "User profile", Description = "Your user profile information (first name, last name, etc.)", Required = false, Emphasize = true, ShowInDiscoveryDocument = true, Created = DateTime.UtcNow, Updated = null, NonEditable = false }); builder.Entity<IdentityClaim>() .HasData( new IdentityClaim { Id = 1, IdentityResourceId = 1, Type = "sub" }, new IdentityClaim { Id = 2, IdentityResourceId = 2, Type = "email" }, new IdentityClaim { Id = 3, IdentityResourceId = 2, Type = "website" }, new IdentityClaim { Id = 4, IdentityResourceId = 2, Type = "given_name" }, new IdentityClaim { Id = 5, IdentityResourceId = 2, Type = "family_name" }, new IdentityClaim { Id = 6, IdentityResourceId = 2, Type = "name" }); builder.Entity<Client>() .HasData( new Client { Id = 1, Enabled = true, ClientId = "client", ProtocolType = "oidc", RequireClientSecret = true, RequireConsent = true, ClientName = null, Description = null, AllowRememberConsent = true, AlwaysIncludeUserClaimsInIdToken = false, RequirePkce = false, AllowAccessTokensViaBrowser = false, AllowOfflineAccess = false }, new Client { Id = 2, Enabled = true, ClientId = "ro.client", ProtocolType = "oidc", RequireClientSecret = true, RequireConsent = true, ClientName = null, Description = null, AllowRememberConsent = true, AlwaysIncludeUserClaimsInIdToken = false, RequirePkce = false, AllowAccessTokensViaBrowser = false, AllowOfflineAccess = false }, new Client { Id = 3, Enabled = true, ClientId = "mvc", ProtocolType = "oidc", RequireClientSecret = true, RequireConsent = true, ClientName = "MVC Client", Description = null, AllowRememberConsent = true, AlwaysIncludeUserClaimsInIdToken = false, RequirePkce = false, AllowAccessTokensViaBrowser = false, AllowOfflineAccess = true }, new Client { Id = 4, Enabled = true, ClientId = "js", ProtocolType = "oidc", RequireClientSecret = false, RequireConsent = true, ClientName = "JavaScript client", Description = null, AllowRememberConsent = true, AlwaysIncludeUserClaimsInIdToken = false, RequirePkce = true, AllowAccessTokensViaBrowser = false, AllowOfflineAccess = false }); builder.Entity<ClientGrantType>() .HasData( new ClientGrantType { Id = 1, GrantType = "client_credentials", ClientId = 1 }, new ClientGrantType { Id = 2, GrantType = "password", ClientId = 2 }, new ClientGrantType { Id = 3, GrantType = "hybrid", ClientId = 3 }, new ClientGrantType { Id = 4, GrantType = "authorization_code", ClientId = 4 }); builder.Entity<ClientScope>() .HasData( new ClientScope { Id = 1, Scope = "profile", ClientId = 3 }, new ClientScope { Id = 2, Scope = "profile", ClientId = 4 }, new ClientScope { Id = 3, Scope = "openid", ClientId = 3 }, new ClientScope { Id = 4, Scope = "openid", ClientId = 4 }, new ClientScope { Id = 5, Scope = "web_api", ClientId = 1 } , new ClientScope { Id = 6, Scope = "web_api", ClientId = 2 } , new ClientScope { Id = 7, Scope = "web_api", ClientId = 3 } , new ClientScope { Id = 8, Scope = "web_api", ClientId = 4 }); builder.Entity<ClientSecret>() .HasData( new ClientSecret { Id = 1, Value = "secret".ToSha256(), Type = "SharedSecret", ClientId = 1 }, new ClientSecret { Id = 2, Value = "secret".ToSha256(), Type = "SharedSecret", ClientId = 2 }, new ClientSecret { Id = 3, Value = "secret".ToSha256(), Type = "SharedSecret", ClientId = 3 }); builder.Entity<ClientPostLogoutRedirectUri>() .HasData( new ClientPostLogoutRedirectUri { Id = 1, PostLogoutRedirectUri = "http://localhost:5002/signout-callback-oidc", ClientId = 3 }, new ClientPostLogoutRedirectUri { Id = 2, PostLogoutRedirectUri = "http://localhost:5003/index.html", ClientId = 4 }); builder.Entity<ClientRedirectUri>() .HasData( new ClientRedirectUri { Id = 1, RedirectUri = "http://localhost:5002/signin-oidc", ClientId = 3 }, new ClientRedirectUri { Id = 2, RedirectUri = "http://localhost:5003/callback.html", ClientId = 4 }); builder.Entity<ClientCorsOrigin>() .HasData( new ClientCorsOrigin { Id = 1, Origin = "http://localhost:5003", ClientId = 4 }); }
and call “ClientSeed” method in “OnModelCreating” :
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.ConfigureClientContext(_storeOptions); modelBuilder.ConfigureResourcesContext(_storeOptions); base.OnModelCreating(modelBuilder); ClientSeed(modelBuilder); }
We need one more step to finish our client seed.
Add-Migration SeedConfigurationMigration -c IdentityServer.Data.ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
The database was dropped in previous steps so we need to re-create all tables and re-seed data for all db contexts
Update-Database -Context IdentityServer.Data.ConfigurationDbContext Update-Database -Context PersistedGrantDbContext Update-Database -Context IdentityDbContext
Run the application to log in
Run the IdentityServer4 and navigate to http://localhost:5000/Account/Login
You should be able to login now with user “alice” and password “My long 123$ password”. After login, you should be redirected back to the IdentityServer4 home page with the name “Alice Smith” displayed in the upper left corner.
Explore the database
I encourage you to take a look at the “IdentityServerQuickstart.NetCore3.1” database. You will see it is re-created will all the tables, migrations and data. Explore the data in tables and compare it to data in “Users.cs” and “Config.cs” in the “Data/Seed” folder to learn how and where the data is stored. In the next tutorial we will take a look at the custom properties we can add to extend the “User” model.
You can find the project here.
Support
For direct assistance schedule a technical meeting with Ivan to talk about your requirements.
For a general overview of our services and a live demo schedule a meeting with Maja.
Hi, Thank you for a great tutorial, i am getting an issue when i run below migration command
Add-Migration InitialConfigurationMigration -c IdentityServer.Data.ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
Unable to create an object of type ‘ConfigurationDbContext’. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
please help me
Hi,
We will update the tutorial to fix this problem today. Please add to Startup.cs this line after the first “services.AddDbContext”:(options => options.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly)));”
“services.AddDbContext
Just as a side not you might want to mention to add this to Startup.cs
services.AddDbContext(options =>
options.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly))
);
Otherwise it will not run the migration
Another thing I have also noticed is that you have to drop the entire db and run the migrations again, as the configuration migrations are conflicting on table names that already existed and they were never first removed before the you mention to delete the configuration folder.
Hi. You are right again. Seems like we need to revisit this particular tutorial and add all updates. Thank you.
Hi,
Thank you. You are right, we will update the tutorial.
Hi,
I am getting this error on successful login:
SqlException: Invalid object name ‘PersistedGrants’.
It is coming from IdentityServer.GrantsController.BuildViewModelAsync() in GrantsController.cs:
var grants = await _interaction.GetAllUserConsentsAsync();
Also, not sure if Users.cs referred to in the last section exists since update.
Hi Serg,
Please make sure of a couple of things:
I really don’t understand this last part, before this section this was a great tutorial. This feels rushed and untested.
When I try to migrate I keep getting errors like “More than one DbContext named ‘ConfigurationDbContext’ was found” or “No DbContext named ‘ConfigurationDbContext’ was found”. Does this really work? Other than this last part, this has been a great tutorial.
Thank you for your feedback. We actually take great care to explain each step properly. Upon your feedback we updated this tutorial to make it easier to follow and understand. Please check it out. ConfigurationDbContext changes are now better outlined in the tutorial as I see that is where your confusion is. Thanks.
Question – After finishing this tutorial my database has a few groups of tables that are nearly identical. One example, I have a table called dbo.IdentityResource and another called dbo.IdentityResources. They have the same columns and both have records for openid and profile. The only difference I’m finding (besides one table being named plural and one not) is that dbo.IdentityResource has another record for email. I had dropped all tables in the database before recreating it again near the end of the database. Is this how it is supposed to turn out?
Hi Katie,
There was a minor issue with the “UsersSeed” migration. We updated the tutorial to fix it.
Because you already created the migrations and updated the database there are a couple of extra steps you need to perform. Please drop the database, manually remove all migrations (delete “Migrations” folder), add all migrations using “Add-Migration” and run “Update-database” for all 3 db contexts. This will re-create the migrations and database properly. Sorry for the confusion and thank you for reporting.
All tutorials up to this point have been pretty good.
I had to edit about all the commands to replace -o with -OutputDir and then they have mostly worked.
ON this step.
How do I accomplisth
“Because we will use our child class “ConfigurationDbContext” instead of parent one coming from IdentityServer4 directly we need to drop the existing local database “IdentityServerQuickstart.NetCore3.1” to avoid possible table collisions. We also need to navigate to “Data/Migrations/IdentityServer” and delete “ConfigurationDb” folder.”
I tried several things, but I still receive.
SQLite Error 1: ‘table “ApiResources” already exists’.
when I issue the Update-database -c IdentityServer.Data.ConfiguratinoDbContext.
Hi Karen. Just drop the database directly using db admin tools.
I tried Drop-database IdentityServerQuickstart.NetCore3.1. nope
I tried Drop-database -c IdentityDbContext
I tried drop-database -c IdentityServer.Data.ConfigurationDbContext
I tried drop-database -c IdentityServer.Data.ConfigurationDbContext
I get the following error:
The process cannot access the file ‘c:\sqlite\UsersDB.db’ because it is being used by another process.
PM> add-migration SeedIdentityDbMigration -c IdentityDbContext -OutputDir Data/migrations/AspNetIdentity/AspNetIdentityDb
Build started…
Build succeeded.
The name ‘SeedIdentityDbMigration’ is used by an existing migration.
I also tried
Remove-migration -c each of 3 contexts
ok
Add-Migration again for all 3 contexts
ok
Update-Database -c IdentityServer.Data.ConfigurationDbContext
says “Error 1: ‘table “ApiResources” already exists’.
Update-Database -c PersistedGrantDbContext
Update-Databae -c IdentityDbContext
says AspNetRoles already exists.
No data loads into the database.
Hy Deblokt,
I have to say that this blog aboubt IdentityServer4 + Asp.Net Core Identity is exactly what I was looking for.
This is a really great blog and guid+explanation of this really huge and complex topic. Thank you very much.
I still have 2 questions:
– Is there an AdminUI provided from IdentityServer4 to manage all the clients, scopes, etc… via UI?
– Is there a big effort for production to switch to HTTPS or just the little change in the launchSettings and getting a certificate?
Thank you.
1. Official Admin UI is not free and you can find it on the https://identityserver.io website. Open-source alternative is here: https://github.com/skoruba/IdentityServer4.Admin
2. Not a big effort just setup HSTS, add a certificate and change the port. Done.
Hi DeBlokt,
Thanks for this amazing tutorial. I managed to get everything up and running.
I only got 1 problem and I got stuck with it for almost a week already.
When I’m building an api and I want to validate the token I always get the next message:
Bearer error=”invalid_token”, error_description=”The signature key was not found”
Only when I remove the Authority from .AddJwtBearer I got a successful response, but then the token isn’t validated by the IssuerSigningKey.
I read something like “Probably your token may not have a private key signature” but I have no idea how to add it. Do you have any clue?
Thanks in advance
Hi Robin,
You are probably using temp developer signing certificate. Take a look at this it might help https://github.com/IdentityServer/IdentityServer4/issues/399
Hi,
Great tutorial but im unable to access /Account/Register endpoints (I guess this are handling by Identity). Manage etc. endpoints are not working too.
Best,
Hi Evren. Use our example on GitHub (you can get the link at the top of every tutorial) and compare it with your code. Thanks
Hi Deblokt,
Great tutorial!
I’m having the same issue as Evren, I tried downloading the tutorial and also got the same issue.
*Could this be happening because the endpoint needs to be declared similar to login page? (options.UserInteraction.LoginUrl = “/Account/Login”;)
*Could this be related to Microsoft having move WindowsPrincipal, WindowsIdentity to new package?(System.Security.Principal.Windows needs to be added to the project to compile)
Best Regards
Please head over to tutorial http://debloktc.wwwnl1-ts3.a2hosted.com/2020/01/24/07-identityserver4-mfa-totp-net-core-3-1/ where we start adding MFA and take a look at Startup to find the razor pages registration. It should have been done sooner but we don’t use the Identity pages until that point in the tutorial and that is where we set it up.
Please head over to tutorial http://debloktc.wwwnl1-ts3.a2hosted.com/2020/01/24/07-identityserver4-mfa-totp-net-core-3-1/ where we start adding MFA and take a look at Startup to find the razor pages registration. It should have been done sooner but we don’t use the Identity pages until that point in the tutorial and that is where we set it up. Correct URL is “/identity/account/register”.
Hi,
This tutorial is the best Identity Server 4 material I’ve ever seen.
Some small issues occured to me though.
I tried 3 browsers:
1- Computer A: Chrome (76.0.3809.100) (x86)
2-Computer B: Chrome (80.0.3987.162) (x64)
3- Computer B: Edge (44.17763.831.0)
Alice can not login on 2-Chrome 80, and I found that the cookies did not contain the Asp.NetCore.Identity value.
Do you have some suggestions?
Please run localhost in HTTPS and it will work. Chrome is dropping samesite:none cookies from HTTP need to use HTTPS.
Hi Deblokt, nice tutorial,
I’m having same issue with the GitHub version
Regards
Please head over to tutorial http://debloktc.wwwnl1-ts3.a2hosted.com/2020/01/24/07-identityserver4-mfa-totp-net-core-3-1/ where we start adding MFA and take a look at Startup to find the razor pages registration. It should have been done sooner but we don’t use the Identity pages until that point in the tutorial and that is where we set it up.
Hi,
Does anyone know how I can request for refresh_token? I’m trying to get refresh_token when requesting for access_token. At the moment I’m getting this output.
“{
“access_token”: “eyJhbGciOiJSU…Zp1eS1WLY2KW2cLvEHhfDfikAYhPEDbAHTvtQu_yBgRsRxhTTPA”,
“refresh_token”: null,
“expires_in”: “3600”,
“token_type”: “Bearer”,
“scope”: “app.api.whatever.full”
}”
Hence refresh_token is null. Now I know you can’t have refresh token with grant type of client credentials. Therefore I have created another two users one with grant type of password and other of grant type of hybrid. I also set the scope for both to offline access. When requesting for a token I get invalid_client. I’m stuck and I have no idea how to resolve this issue.
This is how I’m requesting for token:
public async Task GetUserToken(string client_id, string client_secret, string username, string password, string scope)
{
var client = new HttpClient();
var dict = new Dictionary();
dict.Add(“client_id”, client_id);
dict.Add(“client_secret”, client_secret);
dict.Add(“grant_type”, “password”);
dict.Add(“scope”, scope);
dict.Add(“username”, username);
dict.Add(“password”, password);
client.BaseAddress = new Uri($”{Request.Scheme}://{Request.Host.Value}”);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));
var req = new HttpRequestMessage(HttpMethod.Post, “/connect/token”) { Content = new FormUrlEncodedContent(dict) };
var res = await client.SendAsync(req).ConfigureAwait(false);
if (res.IsSuccessStatusCode)
{
return Ok(res.Content.ReadAsStringAsync().Result);
}
return BadRequest();
}
Hi Deblokt.
I try to run the Migration: ” Update-Database -Context IdentityServer.Data.ConfigurationDbContext ” there is error ” There is already an object named ‘ApiResources’ in the database. ” and the same with ” Update-Database -Context IdentityDbContext ” -> ” There is already an object named ‘AspNetRoles’ in the database “. I can’t drop that table because it’s foreign key.
I ignore that error and running project, It’s logging fail with message ” Invalid username or password “.
Any sugguestion?
Thanks.
Hi Sy. Just drop the database and run migrations again.
Hi Deblokt,
Can we reuse Client Seed from method InitializeDatabase in older post (http://debloktc.wwwnl1-ts3.a2hosted.com/2019/09/26/04-part-3-identityserver4-asp-net-core-identity/) and combine with method for User Seed in this post?
Thanks
Hi. The seed methods are a bit different in 2.x and 3.x .net core versions. You can change it however you see fit but the old way will not work with .net core 3.x.
Thank you a lot for your great tutorial!
After running the last migration script
Update-Database -Context PersistedGrantDbContext
I get the following error:
There is already an object named ‘AspNetRoles’ in the database.
Drop the database first.
Update-Database -Context IdentityServer.Data.ConfigurationDbContext
while doing the above comment im getting this following error
System.InvalidOperationException: To change the IDENTITY property of a column, the column needs to be dropped and recreated.
at Microsoft.EntityFrameworkCore.Migrations.SqlServerMigrationsSqlGenerator.Generate(AlterColumnOperation operation, IModel model, MigrationCommandListBuilder builder)
at Microsoft.EntityFrameworkCore.Migrations.MigrationsSqlGenerator.c.b__71_4(MigrationsSqlGenerator g, MigrationOperation o, IModel m, MigrationCommandListBuilder b)
at Microsoft.EntityFrameworkCore.Migrations.MigrationsSqlGenerator.Generate(MigrationOperation operation, IModel model, MigrationCommandListBuilder builder)
at Microsoft.EntityFrameworkCore.Migrations.SqlServerMigrationsSqlGenerator.Generate(MigrationOperation operation, IModel model, MigrationCommandListBuilder builder)
at Microsoft.EntityFrameworkCore.Migrations.MigrationsSqlGenerator.Generate(IReadOnlyList`1 operations, IModel model)
at Microsoft.EntityFrameworkCore.Migrations.SqlServerMigrationsSqlGenerator.Generate(IReadOnlyList`1 operations, IModel model)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.GenerateUpSql(Migration migration)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.c__DisplayClass15_2.b__2()
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.c__DisplayClass0_0.b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
To change the IDENTITY property of a column, the column needs to be dropped and recreated.
Drop the database and try again.
First of all: great tutorials!
I noticed one thing with the migrations. The first seed migrations works good but if I add a migration immediately afterwards I get an update for the Created property because of this ‘DateTime.UtcNow’. Every add of a migration this value is different. So I have set the Created date to new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day) so that I don’t have a conflict anymore.
Hi Deblokt,
Appreciated for your efforts to keep this tutorial up to date. I see this tutorial and the code samples are based on IdentityServer4 v3.1.4 and it looks like there are breaking changes in .net core 3.1 and IdentityServer4 v4.0 or later. Initially I tried using this with latest versions but hit with many issues later I tried with the same versions as your samples using and worked fine. Especially client seeding part (ClientSeed method in ConfigurationDbContext.cs) doesn’t work as there are breaking changes in IdentityServer4.EntityFramework.Entities. In case you get a chance to look into it please update once again as the users like me mostly try to use the latest versions.
Regards,
SreeRam
+1
We currently don’t have available resources to update the tutorials. If you would like to contribute by creating the tutorials for the latest ID4 version please get in touch and we can publish your post or add a link to your blog post. Thank you.
Hi, i tried to access account/login url but i got 404 error.
Hello there, I dropped all the database and updated again but encountered an error while logging in. This chapter of the tutorial seems to be confusing, otherwise is a great tutorial. Thanks a lot for your effort.
An unhandled exception occurred while processing the request.
SqlException: Invalid object name ‘AspNetUsers’.
Microsoft.Data.SqlClient.SqlCommand+c.b__164_0(Task result)
SqlException: Invalid object name ‘AspNetUsers’.
Microsoft.Data.SqlClient.SqlCommand+c.b__164_0(Task result)
System.Threading.Tasks.ContinuationResultTaskFromResultTask.InnerInvoke()
System.Threading.Tasks.Task+c.b__274_0(object obj)
System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, object state)
System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, object state)
System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref Task currentTaskSlot, Thread threadPoolThread)
Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable+AsyncEnumerator.InitializeReaderAsync(DbContext _, bool result, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync(TState state, Func<DbContext, TState, CancellationToken, Task> operation, Func<DbContext, TState, CancellationToken, Task<ExecutionResult>> verifySucceeded, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable+AsyncEnumerator.MoveNextAsync()
System.Runtime.CompilerServices.ValueTaskAwaiter.GetResult()
Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync(IAsyncEnumerable asyncEnumerable, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync(IAsyncEnumerable asyncEnumerable, CancellationToken cancellationToken)
Microsoft.AspNetCore.Identity.UserManager.FindByNameAsync(string userName)
Microsoft.AspNetCore.Identity.SignInManager.PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure)
IdentityServer.AccountController.Login(LoginInputModel model, string button) in AccountController.cs
var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberLogin, lockoutOnFailure: true);
Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask.get_Result()
System.Runtime.CompilerServices.ValueTaskAwaiter.GetResult()
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask actionResultValueTask)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events)
IdentityServer4.Hosting.MutualTlsTokenEndpointMiddleware.Invoke(HttpContext context, IAuthenticationSchemeProvider schemes)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Thanks a lot in advance.
Check the generated table names. Do they have the “AspNet” prefix? Thanks
Comments are closed.