title: How to write in memory integration test for a WebApi secured by OpenId Connect, cookie authentication and hosted by NancyFx and Owin
body: <p>I have a WabApi project which uses Owin and NancyFX. The api is secured by OpenId Connect and cookie authentication.</p>
  
  <p>I have to write some in memory integration tests using HttpClient, which is quite easy as long as you don't try to use authentication based on OpenId Connect and cookie.</p>
  
  <p>Does anyone know how to prepare a proper authentication cookie for HttpClient to let it connect with WebApi as authenticated user?</p>
  
  <p>Currently I'm able to do some http calls to get the proper access token, id token etc. from OpenId Connect provider (implemented by IdentityServer v3), but I have no idea how to prepare authentication cookie for HttpClient.</p>
  
  <p>PS: I uses Hybrid flow for OpenId Connect</p>
  
  <p>Below you can find some of my files. </p>
  
  <p>Server project:
  AppStartup for WebApi:</p>
  
  <p>The server application hosts WebApi and OpenId Connect provider (IdentityServer v3) at the same time, so its app starup looks like this:</p>
  
  <pre><code>public class ServerAppStartup
  {
      public static void Configuration(IAppBuilder app)
      {          
          app.Map("/identity", idsrvApp =&gt;
          {
              var factory = new IdentityServerServiceFactory {...};
              idsrvApp.UseIdentityServer(new IdentityServerOptions
              {
                  SiteName = "server app",
                  SigningCertificate = ...,
                  RequireSsl = false,
                  Factory = factory,
                  AuthenticationOptions = new AuthenticationOptions {
                      RememberLastUsername = true 
                  },
                  EnableWelcomePage = false
              });
          });
  
          app.SetDefaultSignInAsAuthenticationType("ClientCookie");
  
          app.UseCookieAuthentication(new CookieAuthenticationOptions
          {
              AuthenticationMode = AuthenticationMode.Active,
              AuthenticationType = "ClientCookie",
              CookieName = CookieAuthenticationDefaults.CookiePrefix + "ClientCookie",
              ExpireTimeSpan = TimeSpan.FromMinutes(5)
          });
  
          app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
          {
              AuthenticationMode = AuthenticationMode.Active,
              AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType,
              SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType(),
  
              Authority = options.BaseUrl+ "identity",
  
              ClientId = options.ClientId,                
              RedirectUri = options.RedirectUri,
              PostLogoutRedirectUri = options.PostLogoutRedirectUri,
  
              ResponseType = "code id_token",
              Scope = "openid profile offline_access",                                
  
              Notifications = new OpenIdConnectAuthenticationNotifications
              {
                  AuthorizationCodeReceived = async n =&gt;
                  {
                      /* stuff to get ACCESS TOKEN from CODE TOKEN */
                  },
  
                  RedirectToIdentityProvider = n =&gt;
                  {                       
                      if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                      {
                          var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
  
                          if (idTokenHint != null)
                          {
                              n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                          }
                      }
  
                      return Task.FromResult(0);
                  }
              }
          }            
  
          JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary&lt;string, string&gt;();        
  
          app.UseNancy();
          app.UseStageMarker(PipelineStage.MapHandler);
      }
  </code></pre>
  
  <p>Sample nancy module (something like controller in MVC or WebApi):</p>
  
  <pre><code>using System;
  using Nancy.ModelBinding;
  using Nancy.Security;
  namespace Server.Modules
  {
      public class UsersModule : BaseModule  
      {
          public UsersModule() : base("/users")
          {
              Get["/getall"] = parameters =&gt;
              {
                  this.RequiresMSOwinAuthentication();
                  ...
                  return ...;
              };
          }
      }
  }
  </code></pre>
  
  <p>Integration test project:</p>
  
  <p>Test server to let me run WebApi in memory:</p>
  
  <pre><code> public class TestServer: IDisposable
  {
      private Func&lt;IDictionary&lt;string, object&gt;, Task&gt; _appFunc;
      public static CookieContainer CookieContainer;      
      public Uri BaseAddress { get; set; }
      // I uses OwinHttpMessageHandler becaouse it can handle http redirections
      public OwinHttpMessageHandler Handler { get; private set; }
      public HttpClient HttpClient =&gt; new HttpClient(Handler) { BaseAddress = BaseAddress };
  
      public static TestServer Create()
      {
          CookieContainer = new CookieContainer();           
          var result = new TestServer();
  
          var appBuilder = new AppBuilder();
          appBuilder.Properties["host.AppName"] = "WebApi server";
  
          /* Use configuration of server app */
          ServerAppStartup.Configuration(appBuilder);
  
          result._appFunc = appBuilder.Build();
          result.Handler = new OwinHttpMessageHandler(result._appFunc)
          {
              AllowAutoRedirect = true,
              AutoRedirectLimit = 1000,
              CookieContainer = CookieContainer,
              UseCookies = true          
          };          
  
          return result;
      }
  
      public void Dispose()
      {           
          Handler.Dispose();
          GC.SuppressFinalize(this);
      }
  }
  </code></pre>
  
  <p>Sample test:</p>
  
  <pre><code>namespace ServerSpec.Specs.Users
  {
      public class GetAllUsersSpec
      {   
          private TestServer _server;
  
          public GetAllUsersSpec(){
              server = TestServer.create();
          }
  
          [Fact]
          public void should_return_all_users()
          {
              /* here I will get error because http client or rather its cookie handler has no authentication cookie */
              var users = Get("/users/getall");
              ...
          }
  
          public TResponse Get&lt;TResponse&gt;(string urlFragment)
          {
              var client = server.HttpClient();
  
              var httpResponse = client.GetAsync(urlFragment).Result;
              httpResponse.EnsureSuccessStatusCode();
              return httpResponse.Content.ReadAsAsync&lt;TResponse&gt;().Result;
          }
      }       
  }
  </code></pre>