public async Task <RetrieveTokenResult> RetrieveTokenAsync(string accessToken) { var cachedToken = await _tokenCache.RetrieveAsync(accessToken); if (cachedToken != null) { _logger.WriteVerbose("Token was found in cache. Performing expiry validation"); //WSP doesn't add time skew. If the token is about expire, we'd rather rely on the Authorization Server to validate the token for us. if (cachedToken.ExpiresUtc > DateTimeOffset.UtcNow) { return(new RetrieveTokenResult(cachedToken)); } _logger.WriteEntry(Log.TokenFromCacheExpired(accessToken)); } var client = _clientFactory(); _logger.WriteEntry(Log.AttemptRetrieveTokenFromAuthorizationServer(accessToken)); var response = await client.GetAsync($"?{accessToken}"); if (response.StatusCode == HttpStatusCode.NotFound) { _logger.WriteEntry(Log.TokenInformationNotFound(accessToken)); return(new RetrieveTokenResult(null)); } if (response.StatusCode == HttpStatusCode.Unauthorized) { var str = await response.Content.ReadAsStringAsync(); var json = JObject.Parse(str); var expiry = json["expired"]; if (expiry != null && expiry.Value <int>() == 1) { return(RetrieveTokenResult.AsExpired()); } var error = json["error"].Value <string>(); throw new InvalidOperationException( $@"Unknown error while processing response from access token retrieval. Got status code '{response.StatusCode}' and error: '{error}'"); } var responseStream = await response.Content.ReadAsStreamAsync(); using (var reader = new StreamReader(responseStream)) { using (var jsonReader = new JsonTextReader(reader)) { var token = new JsonSerializer().Deserialize <OioIdwsToken>(jsonReader); if (token != null) { //cache on WSP to reduce round trips to AS. await _tokenCache.StoreAsync(accessToken, token); _logger.WriteVerbose("Cached token"); } return(new RetrieveTokenResult(token)); } } }