title: mvc custom oauth server does not redirect to login page on unauthorized
body: <p>I setup my own oauth authorization Server (<strong>NO</strong> Login via Facebook, Google and co). Unfortunately my server does not redirect to the login page after the Authorize-Endpoint is hit. Why doesn't the middleware redirect to my login page?</p>
  
  <p>I followed some tutorials:</p>
  
  <ol>
  <li><a href="http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server" rel="nofollow noreferrer">OWIN OAuth 2.0 Authorization Server</a></li>
  <li><a href="https://stackoverflow.com/a/25928738/3782012">OAuth custom provider c#</a> (Which is by the way the only code example i found for client login into custom oauth server. Thanks to @MatthiasRamp. All other stuff I read is about how to login with the social media Clients which is very frustrating)</li>
  <li><a href="https://stackoverflow.com/a/25722828/3782012">MVC 5 application - implement OAuth Authorization code flow</a> </li>
  </ol>
  
  <p>This is what I made shortend on my oauth server side:</p>
  
  <ol>
  <li><code>Startup.Auth.cs</code> use active Cookie Authentication with Loginpath</li>
  <li><code>Startup.Auth.cs</code> use passive Cookie Authentication</li>
  <li><code>Startup.Auth.cs</code> use authorization Server with AuthorizeEndpointPath</li>
  <li><code>SecurityController/Authorize</code> calls <code>Authentication.challenge()</code> to change the status to <strong>401</strong></li>
  </ol>
  
  <p>One point in the <a href="https://stackoverflow.com/a/25722828/3782012">post</a> from @Satish P he described:  </p>
  
  <blockquote>
    <ul>
    <li>Redirect the client to a login page</li>
    </ul>
  </blockquote>
  
  <p>For this purpose I set the property <a href="https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&amp;l=EN-US&amp;k=k(Microsoft.Owin.Security.Cookies.CookieAuthenticationOptions.LoginPath);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2);k(DevLang-csharp)&amp;rd=true" rel="nofollow noreferrer"><code>CookieAuthenticationOptions.LoginPath</code></a> which tells me</p>
  
  <blockquote>
    <p>The LoginPath property informs the middleware that it should change an <strong>outgoing 401</strong> Unauthorized status code  <strong>into a 302 redirection</strong> onto the given login path.</p>
  </blockquote>
  
  <p>This is my <code>Startup.Auth.cs</code> including <code>LoginPath</code>:</p>
  
  <pre><code>public void ConfigureAuth(IAppBuilder app)
      {
          // 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
          {
              AuthenticationType = "Application",
              AuthenticationMode = AuthenticationMode.Passive,
              LoginPath = new PathString("/Security/Login"),
              LogoutPath = new PathString("/Security/Logout")
          });
  
          // Enable the External Sign In Cookie.
          app.SetDefaultSignInAsAuthenticationType("External");
          app.UseCookieAuthentication(new CookieAuthenticationOptions
          {
              AuthenticationType = "External",
              AuthenticationMode = AuthenticationMode.Passive,
              CookieName = CookieAuthenticationDefaults.CookiePrefix + "External",
              ExpireTimeSpan = TimeSpan.FromMinutes(5),
          });
  
          // The UseOAuthAuthorizationServer extension method is to setup the authorization server. The setup options are: [...]
          app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
          {
              AuthorizeEndpointPath = new PathString("/Security/Authorize"),
              TokenEndpointPath = new PathString("/Token"),
              ApplicationCanDisplayErrors = true,
  #if DEBUG
              AllowInsecureHttp = true,
  #endif
              // Authorization server provider which controls the lifecycle of Authorization Server
              Provider = new ApplicationOAuthProvider(PublicClientId)
          });
       }
  </code></pre>
  
  <p>I created a class which derives from <a href="https://msdn.microsoft.com/de-de/library/microsoft.owin.security.oauth.oauthauthorizationserverprovider(v=vs.111).aspx" rel="nofollow noreferrer"><code>OAuthAuthorizationServerProvider</code></a>.</p>
  
  <pre><code>public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
  {
      public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
      {
          // [Check username and pw here]
          var oAuthIdentity = new ClaimsIdentity(new GenericIdentity(context.UserName, OAuthDefaults.AuthenticationType), context.Scope.Select(x =&gt; new Claim("urn:oauth:scope", x)));
          var cookiesIdentity = new ClaimsIdentity(new GenericIdentity(context.UserName, CookieAuthenticationDefaults.AuthenticationType), context.Scope.Select(x =&gt; new Claim("urn:oauth:scope", x)));
  
          AuthenticationProperties properties = CreateProperties(context.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)
      {
          var grantType = context.Parameters.SingleOrDefault(p =&gt; p.Key == "grant_type").Value;
          if (grantType != null)
          {
              if (grantType[0] == "authorization_code")
              {
                  string clientId;
                  string clientSecret;
                  if (context.TryGetBasicCredentials(out clientId, out clientSecret) || context.TryGetFormCredentials(out clientId, out clientSecret))
                  {
                      if (clientId == Clients.ClientApp.Id &amp;&amp; clientSecret == Clients.ClientApp.Secret)
                      {
                          context.Validated();
                      }
                  }
              }
          }
          return Task.FromResult&lt;object&gt;(null);
      }  
      public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
      {        
          if (context.ClientId == Clients.ClientApp.Id)
          {
              context.Validated(Clients.ClientApp.RedirectUrl);
          }
  
          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 this is the where the redirect should happen because challenge will change the response to unauthorized (401). Instead of the redirect to the login page it wants to return the authorize view.</p>
  
  <pre><code>public ActionResult Authorize()
      {           
          if (Response.StatusCode != 200)
          {
              return View("AuthorizeError");
          }
  
          var authType = DefaultAuthenticationTypes.ApplicationCookie;
          var authentication = HttpContext.GetOwinContext().Authentication;
          var ticket = authentication.AuthenticateAsync(authType).Result;
          var identity = ticket != null ? ticket.Identity : null;
          if (identity == null)
          {
              authentication.Challenge(authType);           
          }
          else
          {
              // login stuff
          }      
  
          return View();
      }
  </code></pre>