Future<AuthToken> refresh(String refreshToken, String clientID, String clientSecret, { List<AuthScope> requestedScopes })

Refreshes a valid AuthToken instance.

This method will refresh a AuthToken given the AuthToken's refreshToken for a given client ID. This method coordinates with this instance's storage to update the old token with a new access token and issue/expiration dates if successful. If not successful, it will throw an AuthRequestError.

Source

Future<AuthToken> refresh(
    String refreshToken, String clientID, String clientSecret, {List<AuthScope> requestedScopes}) async {
  if (clientID == null) {
    throw new AuthServerException(AuthRequestError.invalidClient, null);
  }

  AuthClient client = await clientForID(clientID);
  if (client == null) {
    throw new AuthServerException(AuthRequestError.invalidClient, null);
  }

  if (refreshToken == null) {
    throw new AuthServerException(AuthRequestError.invalidRequest, client);
  }

  var t = await storage.fetchTokenByRefreshToken(this, refreshToken);
  if (t == null || t.clientID != clientID) {
    throw new AuthServerException(AuthRequestError.invalidGrant, client);
  }

  if (clientSecret == null) {
    throw new AuthServerException(AuthRequestError.invalidClient, client);
  }

  if (client.hashedSecret != hashPassword(clientSecret, client.salt)) {
    throw new AuthServerException(AuthRequestError.invalidClient, client);
  }

  var updatedScopes = t.scopes;
  if ((requestedScopes?.length ?? 0) != 0) {
    // If we do specify scope
    for (var incomingScope in requestedScopes) {
      var hasExistingScopeOrSuperset = t.scopes
          .any((existingScope) => incomingScope.isSubsetOrEqualTo(existingScope));

      if (!hasExistingScopeOrSuperset) {
        throw new AuthServerException(AuthRequestError.invalidScope, client);
      }

      if (!client.allowsScope(incomingScope)) {
        throw new AuthServerException(AuthRequestError.invalidScope, client);
      }
    }

    updatedScopes = requestedScopes;
  } else if (client.supportsScopes) {
    // Ensure we still have access to same scopes if we didn't specify any
    for (var incomingScope in t.scopes) {
      if (!client.allowsScope(incomingScope)) {
        throw new AuthServerException(AuthRequestError.invalidScope, client);
      }
    }
  }

  var diff = t.expirationDate.difference(t.issueDate);
  var now = new DateTime.now().toUtc();
  var newToken = new AuthToken()
    ..accessToken = randomStringOfLength(32)
    ..issueDate = now
    ..expirationDate = now.add(new Duration(seconds: diff.inSeconds)).toUtc()
    ..refreshToken = t.refreshToken
    ..type = t.type
    ..scopes = updatedScopes
    ..resourceOwnerIdentifier = t.resourceOwnerIdentifier
    ..clientID = t.clientID;

  await storage.refreshTokenWithAccessToken(this, t.accessToken,
      newToken.accessToken, newToken.issueDate, newToken.expirationDate);

  return newToken;
}