0

I have this scenario: Xamarin.Forms App connected with Web Api 2. I make all requests and get the data i want. Now when the session token expires, i need to refresh the token but don't logout the user. The user don't need to know when token is refreshed. How to organize this, add in every request if statement when i send it and check if token expires. This is one of my requests:

   public async Task<User> GetProfileSetup()
        {
            try
            {
                if (CrossConnectivity.Current.IsConnected)
                {
                    string token = DependencyService.Get<ISharedFunctions>().GetAccessToken();

                    client.DefaultRequestHeaders.Clear();
                    client.DefaultRequestHeaders.Add("Accept", "application/json");
                    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);

                    var response = await client.GetAsync(@"api/Profile/GetProfilSetup");
                    if (response.IsSuccessStatusCode)
                    {
                        string jsonMessage;
                        using (Stream responseStream = await response.Content.ReadAsStreamAsync())
                        {
                            jsonMessage = new StreamReader(responseStream).ReadToEnd();
                        }
                        User user = JsonConvert.DeserializeObject<User>(jsonMessage);


                        return user;
                    }
                    else
                    {
                        var m = response.Content.ToString();
                        return null;
                    }

                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                string error = ex.Message;
                return null;

            }
        }

P.S I have Methods for GetToken and RefreshToken in my Api and they are working, just how to organize Refreshing ?

Razzzz
  • 381
  • 2
  • 17

1 Answers1

1

It really depends on what libraries are you using on your project. But let's say you're using plain c# to handled your HTTP calls.

[OPTION 1] Polly

I can recommend you looking at Polly

It's a great library with a lot of features. You can use the Retry policy to handled expired tokens:

var _unauthorizedPolicy = Policy
    .Handle<Exception>(ex => ex.StatusCode == HttpStatusCode.Unauthorized) // check here for your exception to be the right one
    .RetryAsync(3, async (exception, retryCount, context) =>
    {
        try
        {
            var token = await _authService.RefreshToken();
            // save the new token or whatever you need to store it
        }
        catch (Exception ex)
        {
            // RefreshToken failed, you should probably sign out the user
            SignOut();
        }
    });

What this does is that Polly will try to execute your normal HTTP call and in case it fails and the cause is specified in Handle, then a retry mechanism is fired that will try to refresh the token and then retry your request. In the end, in case the token cannot be refreshed, you sign out the user. Of course, all this can be customized, check Polly's documentation is pretty well written.

Please note that inside Handle<T> you must put the right exception. I just used Exception as a placeholder since I'm not sure what Exception is thrown in your case.

Then you would call your method with this policy:

var result = await _unauthorizedPolicy.ExecuteAsync(() => GetProfileSetup())

And you can reuse that policy for any call, no need to create it every time.

[OPTION 2] DelegatingHandler

I will like here another StackOverflow answer: How to Refresh a token using IHttpClientFactory

Basically you can intercept every HTTP call made via a HttpClient and refresh/add a token to your requests.

Note that that answer does not obligate you to use IHttpClientFactory, it also works for a simple HttpClient.

Also a little bit off-topic. You might want to look up for libraries to handle htt calls such as Retrofit. It will really reduce the amount of boilerplate code.

  • Its plain C# with HttpClient – Razzzz Mar 04 '20 at 08:00
  • With Polly i add in my BaseViewModel and Inherit in every action? And what type of Exception is Unauthorized 401 call ? – Razzzz Mar 04 '20 at 08:06
  • My idea is in every call i make i got HttpResponseMessage . I need to check if HttpResponseMessage is Unauthorized 401 Status Code i need to call the refresh token – Razzzz Mar 04 '20 at 08:35
  • Yes, you can add that policy in you base class and that use it in every other view model as I've shown you in how to use the Policy. As for the exception, My guess is that it's a HttpException but I cannot be sure. You could try the policy just by using Handle put a breakpoint and see exactly what exception is thrown in case of a 401. – Ghimpu Lucian Eduard Mar 04 '20 at 08:49
  • Aham thanks. And one more question is there any function or Handler who can read all responses maybe in AppStart() to define and check all responses – Razzzz Mar 04 '20 at 09:00