Below is the code that does authentication, generates the Authorization header, and calls the API.
Unfortunately, I get a 401 Unauthorized
error followi
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.