Class MFAStore
IZS.USER_MFA and IZS.USER_MFA_CODES of createMFATables.sql beside this class, and the statements on them. Nothing here knows what a code is: the rules are UserMFA's. The devices that are trusted not to be asked again have no table here: they are rows of the device tokens (DeviceTokenStore, CC-LOGIN-L5-DEVICE-TOKEN; CC-SIGNIN-MERGE-L5-L6-L8).The tables are created here, when they are not there (ready(Connection)), as the hub and the Push Notification engine create theirs: createBaseTables.sql runs in a database that has no tables at all, so a table added to it never reaches a database that exists. A database in which they cannot be created (no right to create a table) has no second factor: nobody can enrol, and nobody is enrolled.
Two statements carry a rule, so that it holds for every server that shares the database and for two requests at the same moment: acceptStep(Connection, long, long, long) moves the last accepted time step forward only, and tells whether it did, and useCode(Connection, long, int, long) marks a recovery code used only while it is not, and tells whether it did.
Every method takes the connection of its caller and commits nothing: the caller does.
- Author:
- Christopher Mindus
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordA recovery code, as stored.static final recordThe second factor of a user, as stored.Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringThe table of the recovery codes, and the table probed to tell whether the script ran to its end: the last one it creates.static final StringThe schema of the tables.static final StringThe name of the SQL script beside this class.static final StringThe table of the second factors.Method Summary
Modifier and TypeMethodDescriptionstatic booleanacceptStep(Connection conn, long uid, long step, long now) Accepts the code of a time step: the last accepted step moves forward to it, the failures are forgotten.static longcodeLastUsed(Connection conn, long uid) Gets the time the recovery code of a user that was used last was used.static longcodesCreated(Connection conn, long uid) Gets the time the recovery codes of a user were made.static voidcountFailure(Connection conn, long uid, long now) Counts an invalid code of a user.static booleanexists(Connection conn, long uid) Checks if a user has a second factor.static voidforgetFailures(Connection conn, long uid, long now) Forgets the invalid codes of a user after an accepted recovery code.static StringGets the class-loader resource name of the SQL script.static voidinsert(Connection conn, MFAStore.Row row) Inserts the second factor of a user, who has none.static MFAStore.Rowread(Connection conn, long uid) Reads the second factor of a user.static booleanready(Connection conn) Makes the tables ready: they exist, or they are created now.static booleanremove(Connection conn, long uid) Removes the second factor of a user and every recovery code.static booleanreplace(Connection conn, MFAStore.Row row) Replaces the second factor of a user, who has one, keeping its recovery codes: an authenticator app enrolled by a user whose second factor was a passkey, and the passkey that is left when the app is removed (CC-FIX-SIGNIN-2FA-CHOICE).static voidreplaceCodes(Connection conn, long uid, String[] hashes, long now) Replaces the recovery codes of a user: every code there is goes, used or not.static booleansetMethod(Connection conn, long uid, String method) Changes the method of the second factor of a user, and nothing else of it - its secret, its steps, its count of invalid codes and its recovery codes stay: an app beside a passkey the user chose, and the app when that passkey is gone (CC-FIX-SIGNIN-2FA-CHOICE).static List<MFAStore.Code> unusedCodes(Connection conn, long uid) Reads the recovery codes of a user that are not used.static booleanuseCode(Connection conn, long uid, int seq, long now) Uses a recovery code: it is marked used, only while it is not.
Field Details
SCHEMA
TABLE
CODES_TABLE
The table of the recovery codes, and the table probed to tell whether the script ran to its end: the last one it creates.- See Also:
SCRIPT
Method Details
getScriptResource
Gets the class-loader resource name of the SQL script.- Returns:
- The resource name,
com/iizix/server/user/mfa/createMFATables.sql.
ready
Makes the tables ready: they exist, or they are created now. The connection is committed when they are created.An error of the database is not "no tables" (CC-FIX-DERBY-ATTACH, TP-D-8): before, every
SQLExceptionof the probe read as "the tables are absent", sohasSecondFactoranswered "none" on a transient failure and a password alone signed in a user who has a factor under an optional policy. The probe now tells the two apart, and an error is thrown to the caller, every one of which fails closed.- Parameters:
conn- The connection.- Returns:
- true when the tables exist, false when they do not and cannot be created (logged): the database has no second factor then.
- Throws:
SQLException- When the database cannot tell whether the tables exist: whether a user has a second factor is then not known.
read
Reads the second factor of a user.- Parameters:
conn- The connection.uid- The user ID.- Returns:
- The row, null when the user has none.
- Throws:
SQLException- For SQL errors.
exists
Checks if a user has a second factor.- Parameters:
conn- The connection.uid- The user ID.- Returns:
- true when the user has one.
- Throws:
SQLException- For SQL errors.
insert
Inserts the second factor of a user, who has none.- Parameters:
conn- The connection.row- The row; its times and counts of failure are not written, they start at zero.- Throws:
SQLException- For SQL errors, among them a user who has a second factor already.
replace
Replaces the second factor of a user, who has one, keeping its recovery codes: an authenticator app enrolled by a user whose second factor was a passkey, and the passkey that is left when the app is removed (CC-FIX-SIGNIN-2FA-CHOICE).- Parameters:
conn- The connection.row- The row; its counts of failure are not written, they start at zero.- Returns:
- true when the user had a second factor, and it is replaced.
- Throws:
SQLException- For SQL errors.
setMethod
Changes the method of the second factor of a user, and nothing else of it - its secret, its steps, its count of invalid codes and its recovery codes stay: an app beside a passkey the user chose, and the app when that passkey is gone (CC-FIX-SIGNIN-2FA-CHOICE).- Parameters:
conn- The connection.uid- The user ID.method- The method.- Returns:
- true when the user had a second factor, and its method is changed.
- Throws:
SQLException- For SQL errors.
acceptStep
public static boolean acceptStep(Connection conn, long uid, long step, long now) throws SQLException Accepts the code of a time step: the last accepted step moves forward to it, the failures are forgotten. It moves forward only - the statement changes no row whose last accepted step is this one or a later one - which is what refuses a code that was accepted before, on this server or on another, and one of two requests that carry the same code.- Parameters:
conn- The connection.uid- The user ID.step- The time step of the code.now- The time, milliseconds since the epoch.- Returns:
- true when the step was accepted, false when the code is not new: its step, or a later one, was accepted before (or the user has no second factor).
- Throws:
SQLException- For SQL errors.
countFailure
Counts an invalid code of a user.- Parameters:
conn- The connection.uid- The user ID.now- The time, milliseconds since the epoch.- Throws:
SQLException- For SQL errors.
forgetFailures
Forgets the invalid codes of a user after an accepted recovery code.- Parameters:
conn- The connection.uid- The user ID.now- The time, milliseconds since the epoch.- Throws:
SQLException- For SQL errors.
remove
Removes the second factor of a user and every recovery code.- Parameters:
conn- The connection.uid- The user ID.- Returns:
- true when the user had a second factor.
- Throws:
SQLException- For SQL errors.
replaceCodes
public static void replaceCodes(Connection conn, long uid, String[] hashes, long now) throws SQLException Replaces the recovery codes of a user: every code there is goes, used or not.- Parameters:
conn- The connection.uid- The user ID.hashes- The hashes of the new codes, in their order.now- The time, milliseconds since the epoch.- Throws:
SQLException- For SQL errors.
codesCreated
Gets the time the recovery codes of a user were made.- Parameters:
conn- The connection.uid- The user ID.- Returns:
- The time, milliseconds since the epoch, zero when the user has none.
- Throws:
SQLException- For SQL errors.
codeLastUsed
Gets the time the recovery code of a user that was used last was used.- Parameters:
conn- The connection.uid- The user ID.- Returns:
- The time, milliseconds since the epoch, zero when none was used.
- Throws:
SQLException- For SQL errors.
unusedCodes
Reads the recovery codes of a user that are not used.- Parameters:
conn- The connection.uid- The user ID.- Returns:
- The codes in their order, empty when none is left.
- Throws:
SQLException- For SQL errors.
useCode
Uses a recovery code: it is marked used, only while it is not.- Parameters:
conn- The connection.uid- The user ID.seq- The number of the code.now- The time, milliseconds since the epoch.- Returns:
- true when the code is used by this call, false when it was used before.
- Throws:
SQLException- For SQL errors.