Class RecoveryCodeService

java.lang.Object
com.codename1.backend.security.mfa.RecoveryCodeService

public final class RecoveryCodeService extends Object

Recovery codes: what signs a user in when their authenticator app is gone.

generate(String) makes ten, to be shown to the user once and never again -- the server keeps a salted PBKDF2 password hash of each and cannot show them a second time. Each works once, in place of a one-time code at sign-in. Generating again replaces whatever was left.

  • Field Details

  • Constructor Details

    • RecoveryCodeService

      public RecoveryCodeService(RecoveryCodeRepository repository)
      A service whose codes are hashed by defaultEncoder().
    • RecoveryCodeService

      public RecoveryCodeService(RecoveryCodeRepository repository, PasswordEncoder encoder)

      A service whose codes are hashed and verified by encoder, for codes imported from a system that stored them another way.

      Parameters
      • repository: where the hashes are kept
      • encoder: hashes new codes and verifies stored ones
  • Method Details

    • defaultEncoder

      public static PasswordEncoder defaultEncoder()

      The encoder recovery codes use unless another is given: a DelegatingPasswordEncoder that hashes new codes as {pbkdf2-sha256}, and verifies a stored hash by the {id} in front of it -- {pbkdf2-sha256}, or {sha256} for the hexadecimal SHA-256 of the code another system may have stored (Sha256HexPasswordEncoder). A hash with no {id} is PBKDF2, as every code this service made before ids were written.

      A code is compared in the normalized form a user's input is reduced to: lower case, without - or spaces. Codes imported as {sha256} must be hashed from that form.

    • generate

      public List<String> generate(String username)
      Makes COUNT new codes for username, replacing any they had.
      Returns:
      the codes, each written xxxxx-xxxxx: the only time they exist outside the user's keeping
    • consume

      public boolean consume(String username, String code)
      Uses a code up. At most four verifications run in this process, and at most one per username (case insensitive). A busy verifier returns false immediately; it does not consume a code or queue password-hashing work.
      Returns:
      whether code was one of username's unused codes
    • isCodeShaped

      public static boolean isCodeShaped(String code)
      Whether code is written as a recovery code is: ten letters and digits, with or without the dash. It says nothing about whether anybody has that code -- only that it is not something else, such as the digits of a one-time code.
    • remaining

      public int remaining(String username)
      How many codes username has left.