Authorization header is lost on redirect

后端 未结 3 1340
独厮守ぢ
独厮守ぢ 2020-11-27 18:39

Below is the code that does authentication, generates the Authorization header, and calls the API.

Unfortunately, I get a 401 Unauthorized error followi

3条回答
  •  攒了一身酷
    2020-11-27 19:32

    I had a similar problem, but not quite the same. In my case, I also had the redirect problem, but security is implemented with OAuth, which also has the secondary, but related, problem that tokens sometimes expire.

    For that reason, I'd like to be able to configure an HttpClient to automatically go and refresh the OAuth token when it receives a 401 Unauthorized response, regardless of whether this happens because of a redirect, or a token expiration.

    The solution posted by Chris O'Neill shows the general steps to take, but I wanted to embed that behaviour inside of an HttpClient object, instead of having to surround all our HTTP code with an imperative check. We have a lot of existing code that uses a shared HttpClient object, so it'd be much easier to refactor our code if I could change the behaviour of that object.

    The following looks like it's working. I've only prototyped it so far, but it seems to be working. Much of our code base is in F#, so the code is in F#:

    open System.Net
    open System.Net.Http
    
    type TokenRefresher (refreshAuth, inner) =
        inherit MessageProcessingHandler (inner)
    
        override __.ProcessRequest (request, _) = request
    
        override __.ProcessResponse (response, cancellationToken) =
            if response.StatusCode <> HttpStatusCode.Unauthorized
            then response
            else
                response.RequestMessage.Headers.Authorization <- refreshAuth ()
                inner.SendAsync(response.RequestMessage, cancellationToken).Result
    

    This is a little class that takes care of refreshing the Authorization header if it receives a 401 Unauthorized response. It refreshes using an injected refreshAuth function, which has the type unit -> Headers.AuthenticationHeaderValue.

    Since this is still prototype code, I made the inner SendAsync call a blocking call, thereby leaving it as an exercise to the reader to implement it properly using an async workflow.

    Given a refresh function called refreshAuth, you can create a new HttpClient object like this:

    let client = new HttpClient(new TokenRefresher(refreshAuth, new HttpClientHandler ()))
    

    The answer posted by Chris O'Neill takes care to check that the new URL is still considered safe. I skipped that security consideration here, but you should strongly consider including a similar check before retrying the request.

提交回复
热议问题