adds onCredentialsRefreshed callback support in Client class, adds onCredentialsRefreshed callback parameter in resourceOwnerPasswordGrant
diff --git a/lib/src/client.dart b/lib/src/client.dart
index 367d583..7986b5e 100644
--- a/lib/src/client.dart
+++ b/lib/src/client.dart
@@ -67,6 +67,9 @@
   Credentials get credentials => _credentials;
   Credentials _credentials;
 
+  /// Callback to be invoked whenever the credentials refreshed.
+  CredentialsRefreshedCallback _onCredentialsRefreshed;
+
   /// Whether to use HTTP Basic authentication for authorizing the client.
   final bool _basicAuth;
 
@@ -86,9 +89,11 @@
   Client(this._credentials,
       {this.identifier,
       this.secret,
+      CredentialsRefreshedCallback onCredentialsRefreshed,
       bool basicAuth = true,
       http.Client httpClient})
       : _basicAuth = basicAuth,
+        _onCredentialsRefreshed = onCredentialsRefreshed,
         _httpClient = httpClient == null ? new http.Client() : httpClient {
     if (identifier == null && secret != null) {
       throw new ArgumentError("secret may not be passed without identifier.");
@@ -156,6 +161,10 @@
         basicAuth: _basicAuth,
         httpClient: _httpClient);
 
+    if (_onCredentialsRefreshed != null) {
+      _onCredentialsRefreshed(_credentials);
+    }
+
     return this;
   }
 
diff --git a/lib/src/credentials.dart b/lib/src/credentials.dart
index 343f12d..e8a161a 100644
--- a/lib/src/credentials.dart
+++ b/lib/src/credentials.dart
@@ -13,6 +13,9 @@
 import 'parameters.dart';
 import 'utils.dart';
 
+/// Type of the callback when credentials are refreshed.
+typedef CredentialsRefreshedCallback = void Function(Credentials);
+
 /// Credentials that prove that a client is allowed to access a resource on the
 /// resource owner's behalf.
 ///
diff --git a/lib/src/resource_owner_password_grant.dart b/lib/src/resource_owner_password_grant.dart
index 13d8f28..a3c16f5 100644
--- a/lib/src/resource_owner_password_grant.dart
+++ b/lib/src/resource_owner_password_grant.dart
@@ -10,6 +10,7 @@
 import 'client.dart';
 import 'handle_access_token_response.dart';
 import 'utils.dart';
+import 'credentials.dart';
 
 /// Obtains credentials using a [resource owner password grant][].
 ///
@@ -49,6 +50,7 @@
     String secret,
     Iterable<String> scopes,
     bool basicAuth = true,
+    CredentialsRefreshedCallback onCredentialsRefreshed,
     http.Client httpClient,
     String delimiter,
     Map<String, dynamic> getParameters(
@@ -84,5 +86,8 @@
       response, authorizationEndpoint, startTime, scopes, delimiter,
       getParameters: getParameters);
   return new Client(credentials,
-      identifier: identifier, secret: secret, httpClient: httpClient);
+      identifier: identifier,
+      secret: secret,
+      httpClient: httpClient,
+      onCredentialsRefreshed: onCredentialsRefreshed);
 }
diff --git a/test/client_test.dart b/test/client_test.dart
index ec52589..9284d28 100644
--- a/test/client_test.dart
+++ b/test/client_test.dart
@@ -64,6 +64,37 @@
       await client.read(requestUri);
       expect(client.credentials.accessToken, equals('new access token'));
     });
+
+    test("that onCredentialsRefreshed is called", () async {
+      var callbackCalled = false;
+
+      var expiration = new DateTime.now().subtract(new Duration(hours: 1));
+      var credentials = new oauth2.Credentials('access token',
+          refreshToken: 'refresh token',
+          tokenEndpoint: tokenEndpoint,
+          expiration: expiration);
+      var client = new oauth2.Client(credentials,
+          identifier: 'identifier',
+          secret: 'secret',
+          httpClient: httpClient, onCredentialsRefreshed: (credentials) {
+        callbackCalled = true;
+      });
+
+      httpClient.expectRequest((request) {
+        return new Future.value(new http.Response(
+            jsonEncode(
+                {'access_token': 'new access token', 'token_type': 'bearer'}),
+            200,
+            headers: {'content-type': 'application/json'}));
+      });
+
+      httpClient.expectRequest((request) {
+        return new Future.value(new http.Response('good job', 200));
+      });
+
+      await client.read(requestUri);
+      expect(callbackCalled, equals(true));
+    });
   });
 
   group('with valid credentials', () {
diff --git a/test/resource_owner_password_grant_test.dart b/test/resource_owner_password_grant_test.dart
index 04d1537..65e67d6 100644
--- a/test/resource_owner_password_grant_test.dart
+++ b/test/resource_owner_password_grant_test.dart
@@ -3,8 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn("vm")
-
 import 'dart:convert';
+import 'dart:mirrors';
 
 import 'package:http/http.dart' as http;
 import 'package:oauth2/oauth2.dart' as oauth2;
@@ -46,6 +46,29 @@
       expect(client.credentials.accessToken, equals('2YotnFZFEjr1zCsicMWpAA'));
     });
 
+    test('passes the onCredentialsRefreshed callback to the client', () async {
+      expectClient.expectRequest((request) async {
+        return new http.Response(success, 200,
+            headers: {'content-type': 'application/json'});
+      });
+
+      var onCredentialsRefreshedCallback = (oauth2.Credentials credentials) {};
+
+      var client = await oauth2.resourceOwnerPasswordGrant(
+          authEndpoint, 'username', 'userpass',
+          identifier: 'client',
+          secret: 'secret',
+          httpClient: expectClient,
+          onCredentialsRefreshed: onCredentialsRefreshedCallback);
+
+      var reflection = reflect(client);
+      var sym = MirrorSystem.getSymbol(
+          '_onCredentialsRefreshed', reflection.type.owner);
+
+      expect(reflection.getField(sym).reflectee,
+          equals(onCredentialsRefreshedCallback));
+    });
+
     test('builds correct request when using query parameters for client',
         () async {
       expectClient.expectRequest((request) async {