add `onCredentialsRefreshed` parameter to `AuthorizationCodeGrant`
diff --git a/lib/src/authorization_code_grant.dart b/lib/src/authorization_code_grant.dart
index 6b28290..526ab9f 100644
--- a/lib/src/authorization_code_grant.dart
+++ b/lib/src/authorization_code_grant.dart
@@ -9,6 +9,7 @@
 
 import 'client.dart';
 import 'authorization_exception.dart';
+import 'credentials.dart';
 import 'handle_access_token_response.dart';
 import 'parameters.dart';
 import 'utils.dart';
@@ -71,6 +72,11 @@
   /// documentation.
   final Uri tokenEndpoint;
 
+  /// Callback to be invoked whenever the credentials are refreshed.
+  ///
+  /// This will be passed as-is to the constructed [Client].
+  CredentialsRefreshedCallback _onCredentialsRefreshed;
+
   /// Whether to use HTTP Basic authentication for authorizing the client.
   final bool _basicAuth;
 
@@ -107,6 +113,9 @@
   /// [httpClient] is used for all HTTP requests made by this grant, as well as
   /// those of the [Client] is constructs.
   ///
+  /// [onCredentialsRefreshed] will be called by the constructed [Client]
+  /// whenever the credentials are refreshed.
+  ///
   /// The scope strings will be separated by the provided [delimiter]. This
   /// defaults to `" "`, the OAuth2 standard, but some APIs (such as Facebook's)
   /// use non-standard delimiters.
@@ -126,11 +135,13 @@
       String delimiter,
       bool basicAuth = true,
       http.Client httpClient,
+      CredentialsRefreshedCallback onCredentialsRefreshed,
       Map<String, dynamic> getParameters(MediaType contentType, String body)})
       : _basicAuth = basicAuth,
         _httpClient = httpClient == null ? new http.Client() : httpClient,
         _delimiter = delimiter ?? ' ',
-        _getParameters = getParameters ?? parseJsonParameters;
+        _getParameters = getParameters ?? parseJsonParameters,
+        _onCredentialsRefreshed = onCredentialsRefreshed;
 
   /// Returns the URL to which the resource owner should be redirected to
   /// authorize this client.
@@ -289,7 +300,8 @@
         identifier: this.identifier,
         secret: this.secret,
         basicAuth: _basicAuth,
-        httpClient: _httpClient);
+        httpClient: _httpClient,
+        onCredentialsRefreshed: _onCredentialsRefreshed);
   }
 
   /// Closes the grant and frees its resources.
diff --git a/test/authorization_code_grant_test.dart b/test/authorization_code_grant_test.dart
index ec6e71b..babdb78 100644
--- a/test/authorization_code_grant_test.dart
+++ b/test/authorization_code_grant_test.dart
@@ -289,4 +289,50 @@
       })));
     });
   });
+
+  group('onCredentialsRefreshed', () {
+    test('is correctly propagated', () async {
+      var isCallbackInvoked = false;
+      var grant = new oauth2.AuthorizationCodeGrant(
+          'identifier',
+          Uri.parse('https://example.com/authorization'),
+          Uri.parse('https://example.com/token'),
+          secret: 'secret',
+          basicAuth: false,
+          httpClient: client, onCredentialsRefreshed: (credentials) {
+        isCallbackInvoked = true;
+      });
+
+      grant.getAuthorizationUrl(redirectUrl);
+      client.expectRequest((request) {
+        return new Future.value(new http.Response(
+            jsonEncode({
+              'access_token': 'access token',
+              'token_type': 'bearer',
+              "expires_in": -3600,
+              "refresh_token": "refresh token",
+            }),
+            200,
+            headers: {'content-type': 'application/json'}));
+      });
+
+      var oauth2Client = await grant.handleAuthorizationCode('auth code');
+
+      client.expectRequest((request) {
+        return new Future.value(new http.Response(
+            jsonEncode(
+                {'access_token': 'new access token', 'token_type': 'bearer'}),
+            200,
+            headers: {'content-type': 'application/json'}));
+      });
+
+      client.expectRequest((request) {
+        return new Future.value(new http.Response('good job', 200));
+      });
+
+      await oauth2Client.read(Uri.parse("http://example.com/resource"));
+
+      expect(isCallbackInvoked, equals(true));
+    });
+  });
 }