Tutorial for Livecode Server log in system

Alex Tweedly alex at tweedly.net
Tue Mar 26 13:36:15 EDT 2024

Hi Tim,

I guess my first response would be - don't.

Specifically, don't store or use passwords. Users have a bad habit of 
re-using the same passwords, so even if your site has no personal or 
valuable info about your users, the fact that passwords get re-used 
means you are storing valuable info, and so you're taking on a moral 
responsibility to keep it very safe.

If you do have passwords, then you need to have a recovery mechanism for 
when users forget their pssword. 99% of the time, that involves emailing 
them a recovery link, or temp password, or ... So in effect the password 
has the same (or less) security than their email account - so you might 
as well just use the email account.

Nowadays I always use this style of password-free accounts. I would have 
sent a copy of the known, tested, etc. code - but it's all embedded in 
lots of my libraries, etc. and was tricky to unravel. So I've sent a 
very bare-bones version; tested but not all corner cases (e.g. I didn't 
wait a week to ensure time-outs happened properly :-).

Overview: The user asks for a code to login with, that gets emailed to 
them, and then they type that code in to the next screen. Once that's 
successfully done, you set up a cookie in their browser, valid for some 
reasonable length of time such as 7 days, and you're done. Any script 
that wants to can take the getCurrentUser() code to check that they are 
logged in properly.

Internally, it's done by creating a temporary code (6 digits, which is 
recorded along with their email and expires within 15 minutes), and once 
they have verified that code, you give them a new code which is a UUID 
(so essentially un-guessable) which lasts for the 7 days.

Other than that, I hope it's reasonably straightforward .....




set the errormode to inline

function getCurrentUser
    local tCookie, tCodes, tExpires
    put $_COOKIE["myusercookie"] into tCookie
    if tCookie is empty then
       return empty
    end if

    -- codes are stored as code,email,expirydate (in seconds)
    put URL ("file:codes.txt") into tCodes
    filter tCodes with (tCookie & comma & "*")
    put item 3 of line -1 of tCodes into tExpires
    if seconds() > tExpires then
       return empty
       return item 2 of line -1 of tCodes
    end if
end getCurrentUser

function shellEscape pText
-- keep this at the end because it messes up Coda colouring
    repeat for each char tChar in "\`!$" & quote
       replace tChar with "\" & tChar in pText
    end repeat
    return pText
end shellEscape

function wrapQ pText
    return quote & pText & quote
end wrapQ

on askforemail
  put "<p><form  method='post' action='simplelogin.lc'>"
  put "    <label for='email'>My email is </label>"
  put "    <input type='email' name='email' value=''>"
  put "    <button type='submit'  value='havecode'>Submit my email 
  put "</form>"
end askforemail

on askforcode
  put "<p><form  method='post' action='simplelogin.lc'>"
  put "    <label for='code'>My code is </label>"
  put "    <input name='code' value=''>"
  put "    <button type='submit' value='havecode'>Submit my code </button>"
  put "</form>"
end askforcode

on askforlogout
  put "<form  method='post' action='simplelogin.lc'>"
  put "    <input type='hidden' name='logout' value='true'>"
  put "    <button type='submit'  value='logout'>Log me out now</button>"
  put "</form>"
end askforlogout

-- real code start here

put getCurrentUser() into tUser

if $_POST["logout"] AND tUser is not empty then
    put $_COOKIE["myusercookie"] into tCode
    put tCode & comma & tUser & comma & (the seconds-1) &CR after \
        URL ("file:codes.txt")
   put "Successfully logged out."
   exit to top
end if

if tUser is not empty then -- ask them if they want to log out
   put "Already logged in as " & tUser
   exit to top
end if

put $_POST["code"] into tCode
if tCode is not empty then
   -- we need to compare this code with what is pending
   put URL ("file:codes.txt") into tPending
   put ( tCode & comma & "*") into tFilter
   filter tPending with tFilter
   put line -1 of tPending into tPending
   if the seconds <= item 3 of tPending then  -- found a match pending
      put item 2 of tPending into tEmail
      put uuid("random") into tCode
      put tCode & comma & tEmail & comma & (the seconds+60*60*24*7) &CR 
after \
        URL ("file:codes.txt")
      put cookie "myusercookie" with tCode until (the seconds + 60 * 60 
* 24 * 7)
      put "Successfully logged in"
      exit to top
   end if
   -- no match for the code
   put "Code not matched. Please try again or give different email 
   put $_POST["email"] into tEmail
end if

if tEmail is not empty then
   -- have email address - generate a code and ask user for it
   put random(999999) into tSix
   put format("%06d", tSix) into tSix

   -- put this following line in for quick and easy testing !!
   -- be sure to take it out later !!!
   put "should email" && tSix && "to you.<p>"

   -- build the message header, adding the from, to and subject details
   -- we also put any cc addresses in here, but not bcc (bcc addresses 

   put "info at kilmelford.com" into pFrom   -- CHANGE KILMELFORD.COM
   put tEmail into pTo
   put "From:" && pFrom  & return & \
        "To:" && tEmail & return & \
        "Subject: Login code for kilmelford.com" & \
         return into tMsg

    put "Content-Type: text/plain;" & return & return after tMsg
    put "Your code is" && tSix && "and it will expire in 15 minutes" 
after tMsg

    -- send the mail by piping the message we have just built to the 
sendmail command
    get shell("echo" && wrapQ(shellEscape(tMsg)) && "| 
/usr/sbin/sendmail" && \
          wrapQ(shellEscape(pTo)) && "-f" && wrapQ(shellEscape(pFrom)))

   put the seconds into tEndTime
   add 15 * 60 to tEndTime
   put tSix & comma & tEmail & comma & tEndTime &CR after \
        URL ("file:codes.txt")

   exit to top

end if


-- end of simplelogin.lc

More information about the use-livecode mailing list