I have an api end point for people to call the service, I only want the GetCacheToken running one at a time if the cache has expired.
Apparently I have 3 calls or more call getCacheToken at the same time via getAccessToken, and it processes synchronously(not sure why), when it await _client.SendAsync(requestData); it will refresh the refresh token and the old refresh token wont be valid anymore.
So the first call went thru, and second and third failed, because they all using the old token to pass it in the send request.
Is there a way to lock the process when the cache is expired? As Lock cannot use on await calls. Thanks
Thought it would be handled by async await but no luck
[System.Web.Http.HttpGet]
[System.Web.Http.Route("getAccessToken")]
public async Task<string> getAccessToken()
{
return await cacheToken.GetCacheToken();
}
private static readonly SemaphoreSlim _mutex = new SemaphoreSlim(1,1);
public async Task<string> GetCacheToken()
{
ObjectCache cache = MemoryCache.Default;
var cacheToken = cache.Get("refreshToken", null);
string refreshToken = cacheToken == null ? GetToken() : cacheToken.ToString();
if (!cache.Contains("apiToken"))
{
//it prevent multiple threads call to update refreshtoken at the same time
await _mutex.WaitAsync();
try
{
//Log.Information("Access token " + cache.Get("apiToken", null));
var isNull = cache.Get("refreshToken", null) == null ? "Yes " : "No ";
var logtime = DateTime.Now.ToString("O");
Log.Information("refresh token is null : " + isNull + DateTime.Now.ToString("O") + " " + logtime);
Log.Information(
"refresh token : " + refreshToken + " " + DateTime.Now.ToString("O") + " " + logtime);
var httpContent = new StringContent("", Encoding.UTF8, "application/x-www-form-urlencoded");
var dict = new Dictionary<string, string>();
dict.Add("grant_type", "refresh_token");
dict.Add("refresh_token", refreshToken);
var requestData = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://oauth2.sky.blackbaud.com/token"),
Content = new FormUrlEncodedContent(dict)
};
requestData.Headers.Authorization = new AuthenticationHeaderValue("Basic", Settings.BasicAuth);
var results = await _client.SendAsync(requestData);
Log.Information("run time " + DateTime.Now);
var resultResponse = results.Content.ReadAsStringAsync().Result;
try
{
results.EnsureSuccessStatusCode();
var result = _js.Deserialize<TokenModel>(resultResponse);
//token expires in one hour from blackbaud
var expiration = DateTimeOffset.Now.AddMinutes(55);
cache.Set("apiToken", result.access_token, expiration);
cache.Set("refreshToken", result.refresh_token, expiration);
await UpdateToken(result.access_token, result.refresh_token);
Log.Information("refresh token after update : " + cache.Get("refreshToken", null) +
DateTime.Now.ToString("O"));
}
catch (Exception e)
{
var exceptionMessage = $"ResultMessage : {resultResponse} Exception: {e}.";
Log.Exception(e, exceptionMessage);
throw;
}
}
finally
{
_mutex.Release();
}
}
return cache.Get("apiToken", null).ToString();
}
here's the log
12 Jul 2019 12:00:10.847
ResultMessage : {"error":"invalid_grant"} Exception: System.Net.Http.HttpRequestException: Response status code does not indicate success: 400 (Bad Request). at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() at RaisersEdge.Infrastructure.Cache.<GetCacheToken>d__3.MoveNext().Exception: HttpRequestException {"Message":"Response status code does not indicate success: 400 (Bad Request).","Data":[],…Stack: at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() at RaisersEdge.Infrastructure.Cache.<GetCacheToken>d__3.MoveNext()Category: Exception
12 Jul 2019 12:00:10.841
run time 12/07/2019 12:00:10 PM
12 Jul 2019 12:00:09.981
refresh token : 03124379add64a90850961e6a2021d6e 2019-07-12T12:00:09.9813412+12:00 2019-07-12T12:00:09.9813412+12:00
12 Jul 2019 12:00:09.981
refresh token is null : No 2019-07-12T12:00:09.9813412+12:00 2019-07-12T12:00:09.9813412+12:00
12 Jul 2019 12:00:09.980
refresh token after update : f0b569cfa2254bbfbd78e9d84ddd66ae2019-07-12T12:00:09.9803523+12:00
12 Jul 2019 12:00:09.951
run time 12/07/2019 12:00:09 PM
12 Jul 2019 12:00:08.970
refresh token : 03124379add64a90850961e6a2021d6e 2019-07-12T12:00:08.9212759+12:00 2019-07-12T12:00:08.9192713+12:00
12 Jul 2019 12:00:08.942
refresh token is null : Yes 2019-07-12T12:00:08.9192713+12:00 2019-07-12T12:00:08.9192713+12:00