diff --git a/functions.lua b/functions.lua index a3dc6b0..f38edfb 100644 --- a/functions.lua +++ b/functions.lua @@ -199,4 +199,15 @@ function otp.is_player_enabled(name) local has_priv = minetest.check_player_privs(name, "otp_enabled") return has_secret and has_priv +end + +function otp.check_code(secret_b32, code, time) + time = time or os.time() + for _, t_offset in ipairs({0, -30, 30}) do + local expected_code = otp.generate_totp(secret_b32, time + t_offset) + if expected_code == code then + return true + end + end + return false end \ No newline at end of file diff --git a/functions.spec.lua b/functions.spec.lua index 7819fcb..57d7013 100644 --- a/functions.spec.lua +++ b/functions.spec.lua @@ -28,12 +28,12 @@ mtt.register("otp.hmac", function(callback) end) mtt.register("otp.generate_totp", function(callback) - local expected_code = 699847 + local expected_code = "699847" local secret_b32 = "N6JGKMEKU2E6HQMLLNMJKBRRGVQ2ZKV7" local unix_time = 1640995200 local code, valid_seconds = otp.generate_totp(secret_b32, unix_time) - assert(code == ""..expected_code) + assert(code == expected_code) assert(valid_seconds > 0) code, valid_seconds = otp.generate_totp(secret_b32) @@ -41,6 +41,21 @@ mtt.register("otp.generate_totp", function(callback) callback() end) +mtt.register("otp.check_code", function(callback) + local expected_code = "699847" + local secret_b32 = "N6JGKMEKU2E6HQMLLNMJKBRRGVQ2ZKV7" + local unix_time = 1640995200 + + assert(otp.check_code(secret_b32, expected_code, unix_time)) + assert(otp.check_code(secret_b32, expected_code, unix_time+30)) + assert(otp.check_code(secret_b32, expected_code, unix_time-30)) + assert(not otp.check_code(secret_b32, expected_code, unix_time-60)) + assert(not otp.check_code(secret_b32, expected_code, unix_time+60)) + assert(not otp.check_code(secret_b32, expected_code)) + + callback() +end) + mtt.register("otp.create_qr_png", function(callback) local url = "otpauth://totp/abc:myaccount?algorithm=SHA1&digits=6&issuer=abc&period=30&" .. "secret=N6JGKMEKU2E6HQMLLNMJKBRRGVQ2ZKV7" diff --git a/join.lua b/join.lua index 83ef63a..305466b 100644 --- a/join.lua +++ b/join.lua @@ -55,8 +55,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) local playername = player:get_player_name() local secret_b32 = otp.get_player_secret_b32(playername) - local expected_code = otp.generate_totp(secret_b32) - if expected_code == fields.code then + if otp.check_code(secret_b32, fields.code) then minetest.chat_send_player(playername, "OTP Code validation succeeded") otp_sessions[playername] = nil otp.regrant_privs(playername) diff --git a/onboard.lua b/onboard.lua index 1f4cc78..6645c3c 100644 --- a/onboard.lua +++ b/onboard.lua @@ -63,8 +63,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.code then local playername = player:get_player_name() local secret_b32 = otp.get_player_secret_b32(playername) - local expected_code = otp.generate_totp(secret_b32) - if expected_code == fields.code then + if otp.check_code(secret_b32, fields.code) then -- set priv local privs = minetest.get_player_privs(playername) privs.otp_enabled = true