How to add FormsAuthentication cookie to HttpClien

2019-05-24 11:26发布

问题:

I am trying to authenticate inside integration test by calling FormsAuthentication.SetAuthCookie("someUser", false);
After that I do need to call WebAPI and not receive unauthorized exception because I have authorized attribute applied. I am using this code to create auth cookie :

var cookie = FormsAuthentication.GetAuthCookie(name, rememberMe);
    var ticket = FormsAuthentication.Decrypt(cookie.Value);

    var newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration,
        ticket.IsPersistent, userData.ToJson(), ticket.CookiePath);
    var encTicket = FormsAuthentication.Encrypt(newTicket);

    /// Use existing cookie. Could create new one but would have to copy settings over...
    cookie.Value = encTicket;

Now I want to add this cookie to HttpRequestMessage inside new HttpClient and send this with my regular request in integration test.

I don't know how to add that auth cookie to HttpRequestMessage ?

回答1:

For manipulating cookies, you need to use WebRequestHandler along with HttpClient. For example,

 var handler = new WebRequestHandler();
 var client = new HttpClient(handler);
 // use handler to configure request such as add cookies to send to server

CookiContainer property will allow to access cookies collection.

On different note, I doubt if creating FormsAuthentication cookie on client will work. A same encryption key would be needed on both client/server. The best approach would be to replay the login request for actual web API - most probably, it would be a POST to login page with user credentials. Observe the same over browser using tool such as Fiddler and construct the same request within your http client.



回答2:

Almost 6 years late, but still may be helpful. The solution based on this one: https://blogs.taiga.nl/martijn/2016/03/10/asp-net-web-api-owin-authenticated-integration-tests-without-authorization-server/

First, while creating Owin TestServer you have to create DataProtector:

    private readonly TestServer _testServer;
    public IDataProtector DataProtector { get; private set; }

    public Server(OwinStartup startupConfig)
    {
        _testServer = TestServer.Create(builder =>
        {
            DataProtector = builder.CreateDataProtector(
                typeof(CookieAuthenticationMiddleware).FullName, DefaultAuthenticationTypes.ApplicationCookie, "v1");

            startupConfig.Configuration(builder);
        });
    }

Then generate cookie like this (use DataProtector created in previous step):

    public string GeterateCookie()
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Role, "your-role"),
            new Claim(ClaimTypes.UserData, "user-data"),
            new Claim(ClaimTypes.Name, "your-name")
        };

        var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie, ClaimTypes.Name, ClaimTypes.Role);

        var tdf = new TicketDataFormat(DataProtector);
        var ticket = new AuthenticationTicket(identity, new AuthenticationProperties {ExpiresUtc = DateTime.UtcNow.AddHours(1)});

        var protectedCookieValue = tdf.Protect(ticket);

        var cookie = new CookieHeaderValue("yourCookie", protectedCookieValue)
        {
            Path = "/",
            HttpOnly = true
        };

        return cookie.ToString();
    }

Make sure to set required claims, initialize ClaimsIdentity according to settings provided to UseCookieAuthentication method, and setting correct CookieName.

The last step is to add CookieHeader to your request:

    public Task<HttpResponseMessage> RequestAsync(HttpRequestMessage request)
    {
        request.Headers.Add("cookie", GenerateCookie());
        return _client.SendAsync(request);
    }