data = { users = { ["admin"] = { password = "admin" } } } function save_data() db = fs.open("auth.db", "w") db.write(textutils.serialize(data)) db.close() end function load_data() if fs.exists("auth.db") then db = fs.open("auth.db", "r") db_contents = db.readAll() db.close() data = textutils.unserialize(db_contents) end end function generate_token(user) local token = hash(user .. os.time() .. math.random()) data.users[user].token = token return token end function convert_password(password) return hash(password .. "3m&LmNm7") end -- Does a complex hash of a string to make it harder to guess function hash(str) local hash = 0 local len = string.len(str) local byte = 0 for i = 1, len do byte = string.byte(str, i) hash = bit32.band(hash * 31 + byte, 0xFFFFFFFF) end return hash end function log(str) io.write("[" .. os.time() .. "] " .. str .. "\n") end load_data() math.randomseed(os.time()) while true do client_id, msg = rednet.receive("auth") request = msg if request.action == nil then rednet.send(client_id, "invalid request", "auth") end if request.action == "register" then if request.username == nil or request.password == nil then rednet.send(client_id, "invalid request", "auth") end if data.users[request.username] ~= nil then rednet.send(client_id, "user already exists", "auth") end data.users[request.username] = { password = convert_password(request.password) } save_data() rednet.send(client_id, "ok", "auth") log(request.username .. " registered") end if request.action == "login" then if request.username == nil or request.password == nil then rednet.send(client_id, "invalid request", "auth") elseif data.users[request.username] == nil then rednet.send(client_id, "user not found", "auth") log(request.username .. " failed log in attempt") elseif convert_password(request.password) == data.users[request.username].password then local token = generate_token(request.username) rednet.send(client_id, token, "auth") log(request.username .. " logged in") else rednet.send(client_id, "invalid password", "auth") end end if request.action == "token" then if request.token == nil or request.token == "" or request.token == -1 then rednet.send(client_id, "invalid request", "auth") else for user, userdata in pairs(data.users) do if userdata.token == request.token then rednet.send(client_id, user, "auth") end end rednet.send(client_id, "invalid token", "auth") end end if request.action == "profile" then if request.username == nil then rednet.send(client_id, "invalid request", "auth") end local profile = {} if data.users[request.username].profile_data ~= nil then profile = data.users[request.username].profile_data else profile.display_name = request.username end profile.username = request.username rednet.send(client_id, data.users[request.username], "auth") end if request.action == "update_profile" then if request.username == nil or request.token == nil then rednet.send(client_id, "invalid request", "auth") end if data.users[request.username].token == request.token then if request.profile_data ~= nil then data.users[request.username].profile_data = request.profile_data end save_data() rednet.send(client_id, "ok") log(request.username .. " updated their profile", "auth") else rednet.send(client_id, "invalid token", "auth") end end end