title: Flow of authorize attribute in rest API controller for debugging using OAuth and OWIN and identity
body: <p>Hi i am making a rest web api project in which i selected individual user account.
  By Default its created account controller and ApplicationOAuthProvider and Startup.Auth.cs .</p>
  
  <p>And Values controller is decorated with [Authorize] attribute which is authorizing request using bearer token is valid or not.</p>
  
  <p>So i want to know answer of below question </p>
  
  <ul>
  <li>what is the flow of Authorize attribute, how Authorize attribute flow
  decide that token is valid or expire. where or in which class and
  method its check that. for example i am making a request with bearer
  token how my application decide that it is valid token or its expiry
  in any class</li>
  <li>how i can capture bearer token in database and based on this token
  and its expiry i want to customize authorize attribute on
  authorization policy like if token is valid in database i need to do some operation</li>
  </ul>
  
  <p>i am using visual studio 2017 and latest owin packages</p>
  
  <p>my Startup.Auth.cs class </p>
  
  <pre><code>public partial class Startup
  {
      public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
  
      public static string PublicClientId { get; private set; }
  
      // For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864
      public void ConfigureAuth(IAppBuilder app)
      {
          // Configure the db context and user manager to use a single instance per request
          app.CreatePerOwinContext(ApplicationDbContext.Create);
          app.CreatePerOwinContext&lt;ApplicationUserManager&gt;(ApplicationUserManager.Create);
  
          // Enable the application to use a cookie to store information for the signed in user
          // and to use a cookie to temporarily store information about a user logging in with a third party login provider
          app.UseCookieAuthentication(new CookieAuthenticationOptions());
          app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
  
          // Configure the application for OAuth based flow
          PublicClientId = "self";
          OAuthOptions = new OAuthAuthorizationServerOptions
          {
              TokenEndpointPath = new PathString("/Token"),
              Provider = new ApplicationOAuthProvider(PublicClientId),
              AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
              AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
              // In production mode set AllowInsecureHttp = false
              AllowInsecureHttp = true
          };
          //OAuthOptions = new OAuthAuthorizationServerOptions
          //{
          //    TokenEndpointPath = new PathString("/api/Account/Login"),
          //    Provider = new ApplicationOAuthProvider(PublicClientId),
          //    RefreshTokenProvider = new SimpleRefreshTokenProvider(),
          //    AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(5),
          //    AllowInsecureHttp = true,
          //};
          // Enable the application to use bearer tokens to authenticate users
          app.UseOAuthBearerTokens(OAuthOptions);
  
          // Uncomment the following lines to enable logging in with third party login providers
          //app.UseMicrosoftAccountAuthentication(
          //    clientId: "",
          //    clientSecret: "");
  
          //app.UseTwitterAuthentication(
          //    consumerKey: "",
          //    consumerSecret: "");
  
          //app.UseFacebookAuthentication(
          //    appId: "",
          //    appSecret: "");
  
          //app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
          //{
          //    ClientId = "",
          //    ClientSecret = ""
          //});
      }
  
  
  
  }
  </code></pre>
  
  <p>my ApplicationOAuthProvider.cs</p>
  
  <pre><code>public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
  {
      private readonly string _publicClientId;
  
      public ApplicationOAuthProvider(string publicClientId)
      {
          if (publicClientId == null)
          {
              throw new ArgumentNullException("publicClientId");
          }
  
          _publicClientId = publicClientId;
      }
  
      public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
      {
          var userManager = context.OwinContext.GetUserManager&lt;ApplicationUserManager&gt;();
  
          ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
  
          if (user == null)
          {
              context.SetError("invalid_grant", "The user name or password is incorrect.");
              return;
          }
  
          ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
             OAuthDefaults.AuthenticationType);
          ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
              CookieAuthenticationDefaults.AuthenticationType);
  
          AuthenticationProperties properties = CreateProperties(user.UserName);
          AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
          context.Validated(ticket);
          context.Request.Context.Authentication.SignIn(cookiesIdentity);
      }
  
      public override Task TokenEndpoint(OAuthTokenEndpointContext context)
      {
          foreach (KeyValuePair&lt;string, string&gt; property in context.Properties.Dictionary)
          {
              context.AdditionalResponseParameters.Add(property.Key, property.Value);
          }
  
          return Task.FromResult&lt;object&gt;(null);
      }
  
      public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
      {
          // Resource owner password credentials does not provide a client ID.
          if (context.ClientId == null)
          {
              context.Validated();
          }
  
          return Task.FromResult&lt;object&gt;(null);
      }
      //public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
      //{
      //    string clientId;
      //    string clientSecret;
      //    if (context.TryGetBasicCredentials(out clientId, out clientSecret))
      //    {
      //        if (clientSecret == "secret")
      //        {
      //            context.OwinContext.Set&lt;string&gt;("as:client_id", clientId);
      //            context.Validated();
      //        }
      //    }
      //    return Task.FromResult&lt;object&gt;(null);
      //}
  
      public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
      {
          if (context.ClientId == _publicClientId)
          {
              Uri expectedRootUri = new Uri(context.Request.Uri, "/");
  
              if (expectedRootUri.AbsoluteUri == context.RedirectUri)
              {
                  context.Validated();
              }
          }
  
          return Task.FromResult&lt;object&gt;(null);
      }
  
      public static AuthenticationProperties CreateProperties(string userName)
      {
          IDictionary&lt;string, string&gt; data = new Dictionary&lt;string, string&gt;
          {
              { "userName", userName }
          };
          return new AuthenticationProperties(data);
      }
  }
  </code></pre>
  
  <p>and  Account controller</p>
  
  <pre><code>[Authorize]
  [RoutePrefix("api/Account")]
  public class AccountController : ApiController
  {
      private const string LocalLoginProvider = "Local";
      private ApplicationUserManager _userManager;
  
      public AccountController()
      {
      }
  
      public AccountController(ApplicationUserManager userManager,
          ISecureDataFormat&lt;AuthenticationTicket&gt; accessTokenFormat)
      {
          UserManager = userManager;
          AccessTokenFormat = accessTokenFormat;
      }
  
      public ApplicationUserManager UserManager
      {
          get
          {
              return _userManager ?? Request.GetOwinContext().GetUserManager&lt;ApplicationUserManager&gt;();
          }
          private set
          {
              _userManager = value;
          }
      }
  
      public ISecureDataFormat&lt;AuthenticationTicket&gt; AccessTokenFormat { get; private set; }
  
      // GET api/Account/UserInfo
      [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
      [Route("UserInfo")]
      public UserInfoViewModel GetUserInfo()
      {
          ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
  
          return new UserInfoViewModel
          {
              Email = User.Identity.GetUserName(),
              HasRegistered = externalLogin == null,
              LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null
          };
      }
  
      // POST api/Account/Logout
      [Route("Logout")]
      public IHttpActionResult Logout()
      {
          Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
          //HttpContext.Current.GetOwinContext().Authentication.SignOut(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie);
         // Request.GetOwinContext().Authentication.SignOut();
  
         // Request.GetOwinContext().Authentication.SignOut(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie);
          return Ok();
      }
  
      // GET api/Account/ManageInfo?returnUrl=%2F&amp;generateState=true
      [Route("ManageInfo")]
      public async Task&lt;ManageInfoViewModel&gt; GetManageInfo(string returnUrl, bool generateState = false)
      {
          IdentityUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
  
          if (user == null)
          {
              return null;
          }
  
          List&lt;UserLoginInfoViewModel&gt; logins = new List&lt;UserLoginInfoViewModel&gt;();
  
          foreach (IdentityUserLogin linkedAccount in user.Logins)
          {
              logins.Add(new UserLoginInfoViewModel
              {
                  LoginProvider = linkedAccount.LoginProvider,
                  ProviderKey = linkedAccount.ProviderKey
              });
          }
  
          if (user.PasswordHash != null)
          {
              logins.Add(new UserLoginInfoViewModel
              {
                  LoginProvider = LocalLoginProvider,
                  ProviderKey = user.UserName,
              });
          }
  
          return new ManageInfoViewModel
          {
              LocalLoginProvider = LocalLoginProvider,
              Email = user.UserName,
              Logins = logins,
              ExternalLoginProviders = GetExternalLogins(returnUrl, generateState)
          };
      }
  
      // POST api/Account/ChangePassword
      [Route("ChangePassword")]
      public async Task&lt;IHttpActionResult&gt; ChangePassword(ChangePasswordBindingModel model)
      {
          if (!ModelState.IsValid)
          {
              return BadRequest(ModelState);
          }
  
          IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword,
              model.NewPassword);
  
          if (!result.Succeeded)
          {
              return GetErrorResult(result);
          }
  
          return Ok();
      }
  
      // POST api/Account/SetPassword
      [Route("SetPassword")]
      public async Task&lt;IHttpActionResult&gt; SetPassword(SetPasswordBindingModel model)
      {
          if (!ModelState.IsValid)
          {
              return BadRequest(ModelState);
          }
  
          IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
  
          if (!result.Succeeded)
          {
              return GetErrorResult(result);
          }
  
          return Ok();
      }
  
      // POST api/Account/AddExternalLogin
      [Route("AddExternalLogin")]
      public async Task&lt;IHttpActionResult&gt; AddExternalLogin(AddExternalLoginBindingModel model)
      {
          if (!ModelState.IsValid)
          {
              return BadRequest(ModelState);
          }
  
          Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
  
          AuthenticationTicket ticket = AccessTokenFormat.Unprotect(model.ExternalAccessToken);
  
          if (ticket == null || ticket.Identity == null || (ticket.Properties != null
              &amp;&amp; ticket.Properties.ExpiresUtc.HasValue
              &amp;&amp; ticket.Properties.ExpiresUtc.Value &lt; DateTimeOffset.UtcNow))
          {
              return BadRequest("External login failure.");
          }
  
          ExternalLoginData externalData = ExternalLoginData.FromIdentity(ticket.Identity);
  
          if (externalData == null)
          {
              return BadRequest("The external login is already associated with an account.");
          }
  
          IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(),
              new UserLoginInfo(externalData.LoginProvider, externalData.ProviderKey));
  
          if (!result.Succeeded)
          {
              return GetErrorResult(result);
          }
  
          return Ok();
      }
  
      // POST api/Account/RemoveLogin
      [Route("RemoveLogin")]
      public async Task&lt;IHttpActionResult&gt; RemoveLogin(RemoveLoginBindingModel model)
      {
          if (!ModelState.IsValid)
          {
              return BadRequest(ModelState);
          }
  
          IdentityResult result;
  
          if (model.LoginProvider == LocalLoginProvider)
          {
              result = await UserManager.RemovePasswordAsync(User.Identity.GetUserId());
          }
          else
          {
              result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(),
                  new UserLoginInfo(model.LoginProvider, model.ProviderKey));
          }
  
          if (!result.Succeeded)
          {
              return GetErrorResult(result);
          }
  
          return Ok();
      }
  
      // GET api/Account/ExternalLogin
      [OverrideAuthentication]
      [HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
      [AllowAnonymous]
      [Route("ExternalLogin", Name = "ExternalLogin")]
      public async Task&lt;IHttpActionResult&gt; GetExternalLogin(string provider, string error = null)
      {
          if (error != null)
          {
              return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
          }
  
          if (!User.Identity.IsAuthenticated)
          {
              return new ChallengeResult(provider, this);
          }
  
          ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
  
          if (externalLogin == null)
          {
              return InternalServerError();
          }
  
          if (externalLogin.LoginProvider != provider)
          {
              Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
              return new ChallengeResult(provider, this);
          }
  
          ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,
              externalLogin.ProviderKey));
  
          bool hasRegistered = user != null;
  
          if (hasRegistered)
          {
              Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
  
               ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
                  OAuthDefaults.AuthenticationType);
              ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,
                  CookieAuthenticationDefaults.AuthenticationType);
  
              AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
              Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
          }
          else
          {
              IEnumerable&lt;Claim&gt; claims = externalLogin.GetClaims();
              ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
              Authentication.SignIn(identity);
          }
  
          return Ok();
      }
  
      // GET api/Account/ExternalLogins?returnUrl=%2F&amp;generateState=true
      [AllowAnonymous]
      [Route("ExternalLogins")]
      public IEnumerable&lt;ExternalLoginViewModel&gt; GetExternalLogins(string returnUrl, bool generateState = false)
      {
          IEnumerable&lt;AuthenticationDescription&gt; descriptions = Authentication.GetExternalAuthenticationTypes();
          List&lt;ExternalLoginViewModel&gt; logins = new List&lt;ExternalLoginViewModel&gt;();
  
          string state;
  
          if (generateState)
          {
              const int strengthInBits = 256;
              state = RandomOAuthStateGenerator.Generate(strengthInBits);
          }
          else
          {
              state = null;
          }
  
          foreach (AuthenticationDescription description in descriptions)
          {
              ExternalLoginViewModel login = new ExternalLoginViewModel
              {
                  Name = description.Caption,
                  Url = Url.Route("ExternalLogin", new
                  {
                      provider = description.AuthenticationType,
                      response_type = "token",
                      client_id = Startup.PublicClientId,
                      redirect_uri = new Uri(Request.RequestUri, returnUrl).AbsoluteUri,
                      state = state
                  }),
                  State = state
              };
              logins.Add(login);
          }
  
          return logins;
      }
  
      // POST api/Account/Register
      [AllowAnonymous]
      [Route("Register")]
      public async Task&lt;IHttpActionResult&gt; Register(RegisterBindingModel model)
      {
          if (!ModelState.IsValid)
          {
              return BadRequest(ModelState);
          }
  
          var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
  
          IdentityResult result = await UserManager.CreateAsync(user, model.Password);
  
          if (!result.Succeeded)
          {
              return GetErrorResult(result);
          }
  
          return Ok();
      }
  
      // POST api/Account/RegisterExternal
      [OverrideAuthentication]
      [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
      [Route("RegisterExternal")]
      public async Task&lt;IHttpActionResult&gt; RegisterExternal(RegisterExternalBindingModel model)
      {
          if (!ModelState.IsValid)
          {
              return BadRequest(ModelState);
          }
  
          var info = await Authentication.GetExternalLoginInfoAsync();
          if (info == null)
          {
              return InternalServerError();
          }
  
          var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
  
          IdentityResult result = await UserManager.CreateAsync(user);
          if (!result.Succeeded)
          {
              return GetErrorResult(result);
          }
  
          result = await UserManager.AddLoginAsync(user.Id, info.Login);
          if (!result.Succeeded)
          {
              return GetErrorResult(result); 
          }
          return Ok();
      }
  
      protected override void Dispose(bool disposing)
      {
          if (disposing &amp;&amp; _userManager != null)
          {
              _userManager.Dispose();
              _userManager = null;
          }
  
          base.Dispose(disposing);
      }
  
      #region Helpers
  
      private IAuthenticationManager Authentication
      {
          get { return Request.GetOwinContext().Authentication; }
      }
  
      private IHttpActionResult GetErrorResult(IdentityResult result)
      {
          if (result == null)
          {
              return InternalServerError();
          }
  
          if (!result.Succeeded)
          {
              if (result.Errors != null)
              {
                  foreach (string error in result.Errors)
                  {
                      ModelState.AddModelError("", error);
                  }
              }
  
              if (ModelState.IsValid)
              {
                  // No ModelState errors are available to send, so just return an empty BadRequest.
                  return BadRequest();
              }
  
              return BadRequest(ModelState);
          }
  
          return null;
      }
  
      private class ExternalLoginData
      {
          public string LoginProvider { get; set; }
          public string ProviderKey { get; set; }
          public string UserName { get; set; }
  
          public IList&lt;Claim&gt; GetClaims()
          {
              IList&lt;Claim&gt; claims = new List&lt;Claim&gt;();
              claims.Add(new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider));
  
              if (UserName != null)
              {
                  claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider));
              }
  
              return claims;
          }
  
          public static ExternalLoginData FromIdentity(ClaimsIdentity identity)
          {
              if (identity == null)
              {
                  return null;
              }
  
              Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier);
  
              if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer)
                  || String.IsNullOrEmpty(providerKeyClaim.Value))
              {
                  return null;
              }
  
              if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer)
              {
                  return null;
              }
  
              return new ExternalLoginData
              {
                  LoginProvider = providerKeyClaim.Issuer,
                  ProviderKey = providerKeyClaim.Value,
                  UserName = identity.FindFirstValue(ClaimTypes.Name)
              };
          }
      }
  
      private static class RandomOAuthStateGenerator
      {
          private static RandomNumberGenerator _random = new RNGCryptoServiceProvider();
  
          public static string Generate(int strengthInBits)
          {
              const int bitsPerByte = 8;
  
              if (strengthInBits % bitsPerByte != 0)
              {
                  throw new ArgumentException("strengthInBits must be evenly divisible by 8.", "strengthInBits");
              }
  
              int strengthInBytes = strengthInBits / bitsPerByte;
  
              byte[] data = new byte[strengthInBytes];
              _random.GetBytes(data);
              return HttpServerUtility.UrlTokenEncode(data);
          }
      }
  
      #endregion
  
  
  }
  </code></pre>