title: sub claim is missing Identity Server 4 with Mongo DB
body: <p>I am using Identity Server 4 with MongoDB to create an identity portal.</p>
  
  <pre><code>services.AddIdentityServer().AddMongoRepository()
                  .AddMongoDbForAspIdentity&lt;ApplicationUser, IdentityRole&gt;(Configuration)
                  .AddClients()
                  .AddIdentityApiResources()
                  .AddPersistedGrants()
                  .AddDeveloperSigningCredential();
  
  
  app.UseMongoDbForIdentityServer();
              app.UseIdentityServer();
  </code></pre>
  
  <p>Here is the Mongo Db Repository</p>
  
  <pre><code>namespace IdentityServer.Extension
  {
      public static class IdentityServerBuilderExtensions
      {/// &lt;summary&gt;
       /// Adds mongo repository (mongodb) for IdentityServer
       /// &lt;/summary&gt;
       /// &lt;param name="builder"&gt;&lt;/param&gt;
       /// &lt;returns&gt;&lt;/returns&gt;
          public static IIdentityServerBuilder AddMongoRepository(this IIdentityServerBuilder builder)
          {
              builder.Services.AddTransient&lt;IRepository, Repository&gt;();
              return builder;
          }
  
          /// &lt;summary&gt;
          /// Adds mongodb implementation for the "Asp Net Core Identity" part (saving user and roles)
          /// &lt;/summary&gt;
          /// &lt;remarks&gt;&lt;![CDATA[
          /// Contains implemenations for
          /// - IUserStore&lt;T&gt;
          /// - IRoleStore&lt;T&gt;
          /// ]]&gt;&lt;/remarks&gt;
          public static IIdentityServerBuilder AddMongoDbForAspIdentity&lt;TIdentity, TRole&gt;(this IIdentityServerBuilder builder, IConfigurationRoot configuration) where
              TIdentity : ApplicationUser where TRole : Microsoft.AspNetCore.Identity.MongoDB.IdentityRole
          {
  
              //User Mongodb for Asp.net identity in order to get users stored
              var configurationOptions = configuration.Get&lt;MongoDbConfigurationOptions&gt;();
              var client = new MongoClient(configurationOptions.MongoConnection);
              var database = client.GetDatabase(configurationOptions.MongoDatabaseName);
  
              // Configure Asp Net Core Identity / Role to use MongoDB
              builder.Services.AddSingleton&lt;IUserStore&lt;TIdentity&gt;&gt;(x =&gt;
              {
                  var usersCollection = database.GetCollection&lt;TIdentity&gt;("Identity_Users");
                  IndexChecks.EnsureUniqueIndexOnNormalizedEmail(usersCollection);
                  IndexChecks.EnsureUniqueIndexOnNormalizedUserName(usersCollection);
                  return new UserStore&lt;TIdentity&gt;(usersCollection);
              });
  
              builder.Services.AddSingleton&lt;IRoleStore&lt;TRole&gt;&gt;(x =&gt;
              {
                  var rolesCollection = database.GetCollection&lt;TRole&gt;("Identity_Roles");
                  IndexChecks.EnsureUniqueIndexOnNormalizedRoleName(rolesCollection);
                  return new RoleStore&lt;TRole&gt;(rolesCollection);
              });
              builder.Services.AddIdentity&lt;TIdentity, TRole&gt;().AddDefaultTokenProviders();
  
  
              return builder;
          }
  
          /// &lt;summary&gt;
          /// Configure ClientId / Secrets
          /// &lt;/summary&gt;
          /// &lt;param name="builder"&gt;&lt;/param&gt;
          /// &lt;param name="configurationOption"&gt;&lt;/param&gt;
          /// &lt;returns&gt;&lt;/returns&gt;
          public static IIdentityServerBuilder AddClients(this IIdentityServerBuilder builder)
          {
              builder.Services.AddTransient&lt;IClientStore, CustomClientStore&gt;();
              builder.Services.AddTransient&lt;ICorsPolicyService, InMemoryCorsPolicyService&gt;();
              return builder;
          }
  
  
          /// &lt;summary&gt;
          /// Configure API  &amp;  Resources
          /// Note: Api's have also to be configured for clients as part of allowed scope for a given clientID 
          /// &lt;/summary&gt;
          /// &lt;param name="builder"&gt;&lt;/param&gt;
          /// &lt;returns&gt;&lt;/returns&gt;
          public static IIdentityServerBuilder AddIdentityApiResources(this IIdentityServerBuilder builder)
          {
              builder.Services.AddTransient&lt;IResourceStore, CustomResourceStore&gt;();
              return builder;
          }
  
          /// &lt;summary&gt;
          /// Configure Grants
          /// &lt;/summary&gt;
          /// &lt;param name="builder"&gt;The builder.&lt;/param&gt;
          /// &lt;returns&gt;&lt;/returns&gt;
          public static IIdentityServerBuilder AddPersistedGrants(this IIdentityServerBuilder builder)
          {
              builder.Services.TryAddSingleton&lt;IPersistedGrantStore, CustomPersistedGrantStore&gt;();
              return builder;
          }
  
      }
  }
  </code></pre>
  
  <p><strong>Account Controller</strong> </p>
  
  <p>private readonly SignInManager _signInManager;
          private readonly UserManager _userManager;</p>
  
  <pre><code>    public AccountController(
          IIdentityServerInteractionService interaction,
          IClientStore clientStore,
          IAuthenticationSchemeProvider schemeProvider,
          IEventService events, UserManager&lt;ApplicationUser&gt; userManager, SignInManager&lt;ApplicationUser&gt; signInManager)
      {
          _signInManager = signInManager;
          _userManager = userManager;
          _interaction = interaction;
          _clientStore = clientStore;
          _schemeProvider = schemeProvider;
          _events = events;
      }
  
  if (ModelState.IsValid)
              {
                  // This doesn't count login failures towards account lockout
                  // To enable password failures to trigger account lockout, set lockoutOnFailure: true
                  var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password,
                      model.RememberLogin, lockoutOnFailure: true); 
                  if (result.Succeeded)
                  {
                      var user = await _userManager.FindByNameAsync(model.UserName);
                      await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.Email, clientId: context?.ClientId));
  
                      // only set explicit expiration here if user chooses "remember me". 
                      // otherwise we rely upon expiration configured in cookie middleware.
                      AuthenticationProperties props = null;
                      if (AccountOptions.AllowRememberLogin &amp;&amp; model.RememberLogin)
                      {
                          props = new AuthenticationProperties
                          {
                              IsPersistent = true,
                              ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                          };
                      };
  
                      // issue authentication cookie with subject ID and username
                      await HttpContext.SignInAsync(user.Id, user.UserName, props);
  
                      if (context != null)
                      {
                          if (await _clientStore.IsPkceClientAsync(context.ClientId))
                          {
                              // if the client is PKCE then we assume it's native, so this change in how to
                              // return the response is for better UX for the end user.
                              return View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl });
                          }
  
                          // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                          return Redirect(model.ReturnUrl);
                      }
  
                      // request for a local page
                      if (Url.IsLocalUrl(model.ReturnUrl))
                      {
                          return Redirect(model.ReturnUrl);
                      }
                      else if (string.IsNullOrEmpty(model.ReturnUrl))
                      {
                          return Redirect("~/");
                      }
                      else
                      {
                          // user might have clicked on a malicious link - should be logged
                          throw new Exception("invalid return URL");
                      }
                  }
  
                  await _events.RaiseAsync(new UserLoginFailureEvent(model.UserName, "invalid credentials", clientId:context?.ClientId));
                  ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
              }
  </code></pre>
  
  <p>Exception when running this line of code</p>
  
  <pre><code>var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password,model.RememberLogin, lockoutOnFailure: false);
  </code></pre>
  
  <p>Exception Error </p>
  
  <pre><code>System.InvalidOperationException: sub claim is missing
     at IdentityServer4.Hosting.IdentityServerAuthenticationService.AssertRequiredClaims(ClaimsPrincipal principal)
     at IdentityServer4.Hosting.IdentityServerAuthenticationService.AugmentPrincipal(ClaimsPrincipal principal)
     at IdentityServer4.Hosting.IdentityServerAuthenticationService.SignInAsync(HttpContext context, String scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
     at Microsoft.AspNetCore.Identity.SignInManager`1.SignInWithClaimsAsync(TUser user, AuthenticationProperties authenticationProperties, IEnumerable`1 additionalClaims)
     at Microsoft.AspNetCore.Identity.SignInManager`1.SignInOrTwoFactorAsync(TUser user, Boolean isPersistent, String loginProvider, Boolean bypassTwoFactor)
     at Microsoft.AspNetCore.Identity.SignInManager`1.PasswordSignInAsync(TUser user, String password, Boolean isPersistent, Boolean lockoutOnFailure)
     at Microsoft.AspNetCore.Identity.SignInManager`1.PasswordSignInAsync(String userName, String password, Boolean isPersistent, Boolean lockoutOnFailure)
     at IdentityServer.AccountController.Login(LoginInputModel model, String button) in /Users/macbook/Projects/IdentityPortal/IdentityServer/Quickstart/Account/AccountController.cs:line 116
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/2aWKn.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/2aWKn.png" alt="added screen shot"></a></p>