CreateUserIdenityAsync returns a "UserId not found" exception for a custom IdentityUser

I am following a bittech tutorial on creating identity cards and roles based on JWT. The user of my application is a user table user with int PK.

Currently, the GenerateUserIdentityAsync method just returns a strange error UserId not found . here is my code:

 ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT"); 

and implementation in the User object:

 public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User, int> manager, string authenticationType) { //error on this line: CreateIdentityAsync throws error var userIdentity = await manager.CreateIdentityAsync(this, authenticationType); return userIdentity; } 

My UserManager class is defined as follows:

 public class AppUserManager : UserManager<User, int> 

Oddly enough, when I debug, the this instance in GenerateIdentityAsync has the UserId property, but the base has only id , and I wonder if this is an error? (it doesn't sound right)

I looked at the source code (line 80), but I cannot figure out exactly where the exception is generated.

Exact exception:

  UserId not found. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.InvalidOperationException: UserId not found. 

And the stack trace is not all that useful (to me)

How to find out why / where UserId is not available?


Mode Details:

My GrantResourceOwnerCredentials() :

 public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] {"*"}); var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>(); User user = await userManager.FindAsync(context.UserName, context.Password); if (user == null) // this is NOT null { context.SetError("invalid_grant", "The username or password is incorrect"); return; } // this line fails ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT"); var ticket = new AuthenticationTicket(oAuthIdentity, null); context.Validated(ticket); } 

And ApplicationUser (which, in my case, is just User )

 public partial class User : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim> { public int UserId { get; set; } public string Fullname { get; set; } public string Address { get; set; } public string ContactNumber { get; set; } } 
+6
source share
6 answers

As you found out, when debugging IdentityUser there is an Id , which in your case will be a user ID.

You need to remove the UserId from the User class, use the base Id from IdentityUser and rename the UserId column in the user table of the user to Id .

Any properties that you have in your User class should also have a corresponding column in your user table in the database. If not, you will get the same error for properties that do not match.

This would mean that Fullname , Address and ContactNumber must have the corresponding column names in the AspNetUsers table, otherwise you will get the same error for these properties.

+5
source

You have both UserId and Id properties in your User class - Id inherits from IdentityUser . The problem is that you probably configured UserId as the primary key for User .

The exception you get is ClaimsIdentityFactory.CreateAsync by the ClaimsIdentityFactory.CreateAsync method, on line 97 of UserManager.GetSecurityStampAsync . As you can see, user.Id used to get the security stamp.

If you look inside UserManager.GetSecurityStampAsync , you will see that the exception you get is thrown right here:

 public virtual async Task<string> GetSecurityStampAsync(TKey userId) { ThrowIfDisposed(); var securityStore = GetSecurityStore(); var user = await FindByIdAsync(userId).WithCurrentCulture(); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } return await securityStore.GetSecurityStampAsync(user).WithCurrentCulture(); } 

So, remove the UserId property from the User class and start using Id (inherited from IdentityUser ).

+3
source

I faced the same problem. After a big pain in my head, I could figure out a real problem. When you change the data type of the Id property of the User class to a string, Guid (). ToString () is assigned to the Id property in the constructor, and the same value is stored in the database, and Identity retrieves user data using this value.

However, if you changed the data type of the Id property to int and did not provide a value for this property in the constructor, Identity still tries to get the user data using the default int value (0), this raises the message "System.InvalidOperationException: UserId not found ".

I solved this by extracting the value from the database with the .ExecuteScalar () command and assigning the value to the user. Hope this helps someone encounter a similar problem.

+3
source

What does your ApplicationUser class look like? What does this method look like in your application?

 public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context){} 

Comments Taiseer about GrantResourceOwnerCredentials:

"we create an identifier for the registered user, this identity will contain all roles and claims for the authenticated user"

I had to add the ClaimTypes.NameIdentifier property to ClaimsIdentity to solve a similar problem. Here is the important part of my GrantResourceOwnerCredentials method:

 ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password); if (user == null) { context.SetError("invalid_grant", "The user name or password is incorrect."); return; } var identity = new ClaimsIdentity(context.Options.AuthenticationType); identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())); 
+2
source

In my case, this error occurred because I added another SignInManager to the Login method in Account Controller (following the example of adding a role). It executed SignInManager.PasswordSignInAsync and SignInManager.SignInAsync in the same method, and this calls GenerateUserIdentityAsync (...) twice in ApplicationUser, for which the first succeeded, and the second gave me the exception "UserId" Not Found.

0
source

Server = xxxx; Start Directory = xxxx ;; User ID = xxxx_user; Password = xxxx; where the user ID contains a space, not Server = xxxx; Initial Catalog = xxxx ;; UserID = xxxx_user; Password = xxx; WRONG!!!!!!! See https://www.connectionstrings.com/sql-azure/ for confirmation.

-1
source

All Articles