title: Reuse token for service to service communication
body: <p>I'm trying to secure communication between two services using OAuth (from now on referred to as consumer and provider). </p>
  
  <p>Let's imagine that the consumer just started up. Now multiple http calls arrive to it almost simultaneously. The consumer needs to communicate with the provider in order to process the requests. I would very much like to have the consumer reuse a single token for this communication (instead of fetching a new token for each and every incoming request). First when the token expires, a new token should be fetched.</p>
  
  <p>How to achieve this?</p>
  
  <pre><code>   public class TokenProvider
     {
          private readonly HttpClient _httpClient;
          private Token _token;
          private object _lock = new object();
  
          public TokenProvider(HttpClient httpClient)
          {
              _httpClient = httpClient;
          }
  
          public async Task&lt;string&gt; GetTokenAsync()
          {
              if (_token != null &amp;&amp; !_token.IsExpired())
              {
                  return _token;
              }
              else
              {
                  string oauthPostBody = string.Format(
                      "grant_type=client_credentials&amp;client_id={0}&amp;client_secret={1}", "fakeClientId", "fakeSecret");
                  var tokenEndpoint = ...;
                  var response = await _httpClient.PostAsync(tokenEndpoint.Uri, new StringContent(oauthPostBody));
                  var responseContent = await response.Content.ReadAsStringAsync();
                  var jsonResponse = JsonConvert.DeserializeObject&lt;dynamic&gt;(responseContent);
  
                  lock (_lock)
                  {
                      if (_token == null || _token.IsExpired())
                      {
                          string expiresIn = jsonResponse.expires_in;
                          _token = new Token(jsonResponse.access_token, int.Parse(expiresIn));
                      }
                      return _token;
                  }
              }
          }
  
          private class Token
          {
              private readonly string _token;
              private readonly DateTime _expirationDateTime;
  
              public Token(string token, int expiresIn)
              {
                  _token = token;
                  _expirationDateTime = DateTime.UtcNow.AddSeconds(expiresIn);
              }
  
              public bool IsExpired()
              {
                  return DateTime.UtcNow &gt; _expirationDateTime;
              }
  
              public static implicit operator string(Token token)
              {
                  return token._token;
              }
          }
      }
  </code></pre>
  
  <p>However, I have my doubts that the above is the way to go. This suspicion is based on, among other things, compiler optimizations; see <a href="https://stackoverflow.com/a/5821201/4169214">this post</a> by Eric Lippert. </p>
  
  <p>I'm trying to do such that the token can be read by many threads at once, but only updated by a single. I've also looked into ReaderWriterLockSlim, but this doesn't seem to help solve my problem.
  (Note that it gets even more complicated by the fact that I have an async call in GetTokenAsync.) </p>
  
  <p><strong>Update</strong>
  Based on @EricLippert remarks, I've updated the code:</p>
  
  <pre><code>public class TokenProvider
  {
      private readonly HttpClient _httpClient;
      private readonly IApplicationConfig _config;
      private Token _token;
      private AsyncReaderWriterLock _lock = new AsyncReaderWriterLock();
  
      public TokenProvider(HttpClient httpClient, IApplicationConfig config)
      {
          _httpClient = httpClient;
          _config = config;
      }
  
      public bool TryGetExistingToken(out string token)
      {
          using (_lock.ReaderLock())
          {
              if (_token != null)
              {
                  token = _token;
                  return true;
              }
              else
              {
                  token = null;
                  return false;
              }
          }
      }
  
      public async Task&lt;string&gt; GetNewTokenAsync()
      {
          using (await _lock.WriterLockAsync())
          {
              if (_token != null &amp;&amp; !_token.IsExpired())
              {
                  return _token;
              }
              else
              {
                  var clientId = _config.Get&lt;string&gt;("oauth.clientId");
                  var secret = _config.Get&lt;string&gt;("oauth.sharedSecret");
                  string oauthPostBody = string.Format(
                      "grant_type=client_credentials&amp;client_id={0}&amp;client_secret={1}", clientId, secret);
                  var queueEndpoint = _config.GetUri("recommendationQueue.host");
                  var tokenPath = _config.Get&lt;string&gt;("recommendationQueue.path.token");
                  var tokenEndpoint = new UriBuilder(queueEndpoint) {Path = tokenPath};
                  var response = await _httpClient.PostAsync(tokenEndpoint.Uri, new StringContent(oauthPostBody));
                  var responseContent = await response.Content.ReadAsStringAsync();
                  var jsonResponse = JsonConvert.DeserializeObject&lt;dynamic&gt;(responseContent);
  
                  if (_token == null || _token.IsExpired())
                  {
                      string expiresIn = jsonResponse.expires_in;
                      string accessToken = jsonResponse.access_token;
                      _token = new Token(accessToken, int.Parse(expiresIn));
                  }
                  return _token;
              }
          }
      }
  
      private class Token
      {
          private readonly string _token;
          private readonly DateTime _expirationDateTime;
  
          public Token(string token, int expiresIn)
          {
              _token = token;
              _expirationDateTime = DateTime.UtcNow.AddSeconds(expiresIn);
          }
  
          public bool IsExpired()
          {
              return DateTime.UtcNow &gt; _expirationDateTime;
          }
  
          public static implicit operator string(Token token)
          {
              return token._token;
          }
      }
  }
  </code></pre>
  
  <p>I'm using this <a href="https://github.com/StephenCleary/AsyncEx/wiki/AsyncReaderWriterLock" rel="nofollow noreferrer">AsyncReaderWriterLock</a> by Stephen Cleary.
  Is this a better approach? Or have I just digged myself into an even larger hole?</p>