title: Overriding OnTokenValidated JwtBearerEvents with Custom function .NET Core 2
body: <p>In my API project I am handling authentication with JwtBearer (users login using Azure). When the API is called the token is being validated with the defined Azure instance and this all works fine.</p>
  <p>When a token is being validated successfully, the logged in user is being inserted in our own database with the proper roles. The way this is being handled now is as follow:</p>
  <pre><code>// Add authentication (Azure AD)
  services
      .AddAuthentication(sharedOptions =&gt;
      {
          sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
          sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 
          sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 
      })
      .AddJwtBearer(options =&gt;
      {
          options.Audience = this.Configuration[&quot;AzureAd:ClientId&quot;];
          options.Authority = $&quot;{this.Configuration[&quot;AzureAd:Instance&quot;]}{this.Configuration[&quot;AzureAd:TenantId&quot;]}&quot;;
  
          options.Events = new JwtBearerEvents()
          {
              OnTokenValidated = context =&gt;
              {
                  // Check if the user has an OID claim
                  if (!context.Principal.HasClaim(c =&gt; c.Type == &quot;http://schemas.microsoft.com/identity/claims/objectidentifier&quot;))
                  {
                      context.Fail($&quot;The claim 'oid' is not present in the token.&quot;);
                  }
  
                  ClaimsPrincipal userPrincipal = context.Principal;
                  
                  // Check is user exists, if not then insert the user in our own database
                  CheckUser cu = new CheckUser(
                      context.HttpContext.RequestServices.GetRequiredService&lt;DBContext&gt;(),
                      context.HttpContext.RequestServices.GetRequiredService&lt;UserManager&lt;ApplicationUser&gt;&gt;(),
                      userPrincipal);
  
                  cu.CreateUser();
  
                  return Task.CompletedTask;
              },
          };
      });
  </code></pre>
  <p>This is working fine but it is not the most beautiful / proper way to do it. I would say I should use Dependency Injection / Overriding the <code>OnTokenValidated</code> event and integrate the '<code>CheckUser</code>' logic there so the <code>startup</code> class stays uncluttered.</p>
  <p>Sadly my knowledge about the DI is lacking and I am not entirely sure what the best way is to handle this properly. Therefore I looked a bit around and found a post which was exactly describing my problem:</p>
  <p><a href="https://stackoverflow.com/questions/46818694/problems-handling-ontokenvalidated-with-a-delegate-assigned-in-startup-cs">Problems handling OnTokenValidated with a delegate assigned in startup.cs</a></p>
  <p>After reading this post I tried to modify it a bit with my own logic, I ended up with the following:</p>
  <p><strong>In the Startup:</strong></p>
  <pre><code>services.AddScoped&lt;UserValidation&gt;();
  
  services
      .AddAuthentication(sharedOptions =&gt;
      {
          sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
          sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
          sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 
      })
      .AddJwtBearer(options =&gt;
      {
          options.Audience = this.Configuration[&quot;AzureAd:ClientId&quot;];
          options.Authority = $&quot;{this.Configuration[&quot;AzureAd:Instance&quot;]}{this.Configuration[&quot;AzureAd:TenantId&quot;]}&quot;;
  
          options.EventsType = typeof(UserValidation);
      });
  </code></pre>
  <p><strong>The Custom JwtBearerEvents class:</strong></p>
  <pre><code>public class UserValidation : JwtBearerEvents
  {
      private string UserID { get; set; }
  
      private string UserEmail { get; set; }
  
      private string UserName { get; set; }
  
      public override async Task TokenValidated(TokenValidatedContext context)
      {
          try
          {
              TRSContext context2 = context.HttpContext.RequestServices.GetRequiredService&lt;TRSContext&gt;();
              UserManager&lt;ApplicationUser&gt; userManager = context.HttpContext.RequestServices.GetRequiredService&lt;UserManager&lt;ApplicationUser&gt;&gt;();
  
              ClaimsPrincipal userPrincipal = context.Principal;
  
              this.UserID = userPrincipal.Claims.First(c =&gt; c.Type == &quot;http://schemas.microsoft.com/identity/claims/objectidentifier&quot;).Value;
  
              if (userPrincipal.HasClaim(c =&gt; c.Type == &quot;http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress&quot;))
              {
                  this.UserEmail = userPrincipal.Claims.First(c =&gt; c.Type == &quot;http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress&quot;).Value;
              }
  
              if (userPrincipal.HasClaim(c =&gt; c.Type == &quot;name&quot;))
              {
                  this.UserName = userPrincipal.Claims.First(c =&gt; c.Type == &quot;name&quot;).Value;
              }
  
              var checkUser = userManager.FindByIdAsync(this.UserID).Result;
              if (checkUser == null)
              {
                  checkUser = new ApplicationUser
                  {
                      Id = this.UserID,
                      Email = this.UserEmail,
                      UserName = this.UserEmail,
                  };
  
                  var result = userManager.CreateAsync(checkUser).Result;
  
                  // Assign Roles
                  if (result.Succeeded)
                  {
                      return;  
                  }
                  else
                  {
                      throw new Exception(result.Errors.First().Description);
                  }
              }
          }
          catch (Exception)
          {
              throw;
          }
      }
  }
  </code></pre>
  <p>This is however not working for some reason. There is no error and <code>UserValidation</code> is never being hit (tried to set a debug point but it never hits) and it doesn't insert new users (it does when using the old code).</p>
  <p>Anyone knows what I am doing wrong here or perhaps has some better ideas how to handle this?</p>