Class TotpService

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

public final class TotpService extends Object

Time-based one-time codes (RFC 6238): enrolling a user's authenticator app, and checking the codes it shows.

@Bean
TotpService totp(DataSource dataSource, Config config) {
    return new TotpService(JdbcTotpRepository.fromConfig(dataSource, config), "Acme");
}

Enrolment is two steps, so that nobody is locked out by an app that was never set up: beginEnrollment(String) makes a secret and returns it for the user to scan, and confirmEnrollment(String, String) takes a code from the app. Only then does the user have a second factor, and only then does a chain with http.mfa(...) ask for it.

Codes are six digits over SHA-1 that change every 30 seconds, which is what authenticator apps expect, and one step either side of the current one is accepted to allow for a clock that is off. A code is good once: the step of each accepted code is recorded, and a code of that step or an earlier one is refused afterwards -- including the same code sent twice at once.

  • Constructor Details

    • TotpService

      public TotpService(TotpRepository repository, String issuer)
      Parameters:
      issuer - the name an authenticator app shows beside the account; it may not contain a colon
  • Method Details

    • setDigits

      public void setDigits(int digits)
      The number of digits in a code: 6 unless set, or 8.
    • setPeriodSeconds

      public void setPeriodSeconds(int periodSeconds)
      How long a code lasts; 30 seconds unless set.
    • setTolerance

      public void setTolerance(int tolerance)
      How many steps either side of the current one are accepted; 1 unless set. Zero accepts the current code only.
    • setAlgorithm

      public void setAlgorithm(String algorithm)
      The hash: Hash.SHA1 unless set. Most authenticator apps support no other.
    • setClock

      public void setClock(Clock clock)
    • beginEnrollment

      public TotpEnrollment beginEnrollment(String username)
      Makes a new secret for username and returns what their app needs. Whatever they had before is replaced, and is not a second factor again until confirmEnrollment(String, String).
    • confirmEnrollment

      public boolean confirmEnrollment(String username, String code)
      Finishes an enrolment with a code from the user's app.
      Returns:
      whether code was right; false too when no enrolment is waiting
    • isEnabled

      public boolean isEnabled(String username)
      Whether username has a confirmed second factor.
    • verify

      public boolean verify(String username, String code)
      Checks a code at sign-in, and uses it up.
      Returns:
      whether code is a current code of username that has not been used
    • disable

      public boolean disable(String username)
      Removes the second factor of username.
      Returns:
      whether they had one
    • currentCode

      public String currentCode(String username)
      The code username's app shows now. For tests and for tools; a server has no other use for it.