SpotifyAPI-NET icon indicating copy to clipboard operation
SpotifyAPI-NET copied to clipboard

RetryHandler is unable to update authorization - overwritten by authenticator

Open CrazyOrange opened this issue 5 years ago • 4 comments

Is it possible to use a custom RetryHandler to refresh the access token?

I've already tried to update the Authorization header of the request in HandleRetry but the retry will still throw a token expired exception.

Test code:

        public async Task<IResponse> HandleRetry(IRequest request, IResponse response, IRetryHandler.RetryFunc retry)
        {
            if (response.StatusCode == (HttpStatusCode)401)
            {
                var clientId = configuration.GetSection("Settings:ClientId").Value;
                var clientSecret = configuration.GetSection("Settings:ClientSecret").Value;
                var token = await this.tokenService.GetToken();

                var newResponse = await new OAuthClient().RequestToken(
                    new AuthorizationCodeRefreshRequest(clientId, clientSecret, token.RefreshToken)
                );

                token.AccessToken = newResponse.AccessToken;
                //await this.tokenService.EditToken(token);
                request.Headers["Authorization"] = $"Bearer {newResponse.AccessToken}";


                try
                {
                    var newResp = await retry(request);
                    return newResp;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            }

            return response;

        }

newResponse.isExpired is false btw.

CrazyOrange avatar Oct 22 '20 12:10 CrazyOrange

Looking at Fiddler I can see the request header still uses the old AccessToken.

CrazyOrange avatar Oct 22 '20 12:10 CrazyOrange

Hi,

This is probably because the authenticator is still applied after your retry call.

https://github.com/JohnnyCrazy/SpotifyAPI-NET/blob/b400d63087ce0eb78cd73b59a16cfd3fbf4f5907/SpotifyAPI.Web/Http/APIConnector.cs#L204-L215

I think your authenticator should take care of refreshing the token, similar to https://github.com/JohnnyCrazy/SpotifyAPI-NET/blob/b400d63087ce0eb78cd73b59a16cfd3fbf4f5907/SpotifyAPI.Web/Authenticators/AuthorizationCodeAuthenticator.cs

So your retry handler detects a 401, decideds to retry and the authenticator takes over and also sees that the token is expired and fetches a new one. Does this make sense? 😅

JohnnyCrazy avatar Oct 22 '20 12:10 JohnnyCrazy

Thanks for the hint. I got it working by creating an empty/dummy Authenticator so that my RetryHandler can take care of it. I don't want to be dependent on the last AuthorizationCodeTokenResponse so I would need to make an unnecessary call to the Spotify API just to find out if the token is still valid.

CrazyOrange avatar Oct 22 '20 14:10 CrazyOrange

Mh, true, currently there is no way to communicate between retry handler and authenticator, except for some hacky header passing. I will think of a way to make that better.

One performance note regarding your code: You're always creating a new OAuthClient when a 401 occurs. In the background, this will also create a new HTTPClient, which is discouraged if you care for performance. A shared SpotifyClientConfig would help here, since the HTTPClient is created with it and will be reused, it can be bassed to the constructor of OAuthClient

JohnnyCrazy avatar Oct 23 '20 07:10 JohnnyCrazy

Hi,

Thinking more about this, if folks want to use the retry handler to refresh the authorization, I think not using an authenticator or a custom one is the best choice. Some options I considered:

  • Create a runAuthenticator: boolean flag for the retry function. You could skip running the authenticator with this. Problem: The authenticator has outdated tokens.
  • Create some shared context, which can be shared between authenticator and retry handler. This is already supported by simply creating a custom authenticator/retry handler.

Closing this as I think the system is flexible enough to support these usecases.

JohnnyCrazy avatar Feb 10 '24 12:02 JohnnyCrazy