authenticate method

Future<bool> authenticate(
  1. String atsign,
  2. AtClientPreference atClientPreference, {
  3. OnboardingStatus? status,
  4. String? jsonData,
  5. String? decryptKey,
})

Returns true on successfully authenticating atsign with cramSecret/privateKey. if pkam is successful, encryption keys will be set for the user.

Implementation

Future<bool> authenticate(
    String atsign, AtClientPreference atClientPreference,
    {OnboardingStatus? status, String? jsonData, String? decryptKey}) async {
  /**ToDo Use OnboardingStatus enum instead of using
      atClientPreferences.cramSecret == null to know if atSign is new or existing
      If status == OnboardingStatus.ACTIVATE, then atSign is new, so perform initial auth and
      generate RSA key-pair
      If status == OnboardingStatus.RESTORE then use use atKeys file to login into existing atSign
   */
  /**
   * The authentication is performed either by CRAM authentication or PKAM authentication
   * 1. If AtClientPreference.cramSecret is populated, then atSign is considered as new atSign.
   * So, perform CRAM auth and if successful, generate PKAM key-pair and encryption key-pair
   * and store them into key-chain manager and return true, else false.
   * 2. If AtClientPreference.privateKey is populated, then atSign is considered as existing atSign.
   * So, first verify if .atKeys file provided have valid key-pair. Perform PKAM auth to validate the
   * key-pair. If successful, store the keys into key-chain manager and return true, else false.
   **/
  // _formatAtSign method checks if atSign is prefixed with '@',
  // If '@' is not prefixed, prefixes '@' and returns @sign.
  // If atSign is null or empty, returns empty string.
  atsign = _formatAtSign(atsign);
  // atSign is mandatory to authenticate. So, if atSign is empty return
  // false to indicate authentication is not successful
  if (atsign.isEmpty) {
    _logger.severe('Authentication failed. Null or empty atSign found.');
    return false;
  }
  AtChops? atChops;
  if (atClientPreference.cramSecret.isNull) {
    // If JSON data (encrypted keys from .atKeys file) or decrypt key is null or empty,
    // cannot process authentication. Hence return false.
    //
    // "isNull" is an extension on String class that checks if String is null or empty.
    if ((jsonData.isNull) || (decryptKey.isNull)) {
      _logger.severe(
          'Authentication failed. Encrypted keys from atKeys file not found for the atSign $atsign.');
      return false;
    }
    var decryptedAtKeysMap = _decodeAndDecryptKeys(jsonData!, decryptKey!);
    atChops = createAtChops(decryptedAtKeysMap);
    // Inside "_validateAtKeys", performs PKAM auth using atChops.
    // If PKAM auth fails, UnAuthenticatedException is returned which is handled in the caller method.
    var isValidAtKeysFile = await _validateAtKeys(atChops, atsign,
        atClientPreference.rootDomain, atClientPreference.rootPort);
    if (!isValidAtKeysFile) {
      _logger.severe(
          'Authentication failed. Invalid atKeys file found for the atSign $atsign.');
      return false;
    }
    //If atKeys are valid, store keys to keychain manager
    await _storeToKeyChainManager(atsign, decryptedAtKeysMap);
  }
  // Perform the initial auth using CRAM Secret and then
  // Generate the PKAM and encryption key-pair and create the atChops instance.
  else {
    atClientAuthenticator ??= AtClientAuthenticator();
    var isAuthenticated = await atClientAuthenticator!
        .performInitialAuth(atsign, atClientPreference);
    // If authentication is failed, return false.
    if (!isAuthenticated) {
      return isAuthenticated;
    }
    // The "getKeysFromKeyChainManager" fetches PKAM key-pair and encryption key-pair
    // from the keychain. throws exception if any of the key is null or empty.
    // The createAtChops method takes PKAM and encryption key-pair map and returns
    // atChops instance with fields initialized.
    atChops = createAtChops(await getKeysFromKeyChainManager(atsign));
  }
  await _init(atsign, atClientPreference, atChops);
  await _sync();
  // persist keys to the local-keystore
  await persistKeys(atsign);
  return true;
}