121 lines
3.9 KiB
Plaintext
121 lines
3.9 KiB
Plaintext
Module Auth
|
|
EnableExplicit
|
|
|
|
;- Private helpers
|
|
Procedure.s GetFormField(PostData.s, Field.s)
|
|
; Parse a single field from application/x-www-form-urlencoded body
|
|
Protected Count = CountString(PostData, "&") + 1, i
|
|
Protected Pair.s, Key.s
|
|
|
|
For i = 1 To Count
|
|
Pair = StringField(PostData, i, "&")
|
|
Key = StringField(Pair, 1, "=")
|
|
If Key = Field
|
|
ProcedureReturn URLDecoder(StringField(Pair, 2, "="))
|
|
EndIf
|
|
Next
|
|
ProcedureReturn ""
|
|
EndProcedure
|
|
|
|
Procedure SetSessionCookie(*Request, Token.s)
|
|
FastCGI::WriteResponseHeader(*Request, "Set-Cookie",
|
|
#SESSION_COOKIE + "=" + Token +
|
|
"; Path=/; HttpOnly; SameSite=Strict; Max-Age=" + #SESSION_MAX_AGE)
|
|
EndProcedure
|
|
|
|
Procedure ClearSessionCookie(*Request)
|
|
FastCGI::WriteResponseHeader(*Request, "Set-Cookie",
|
|
#SESSION_COOKIE + "=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0")
|
|
EndProcedure
|
|
|
|
;- Public handlers
|
|
Procedure HandleLogin(*Request)
|
|
Protected PostData.s = FastCGI::GetPostData(*Request)
|
|
Protected Username.s = GetFormField(PostData, "username")
|
|
Protected Password.s = GetFormField(PostData, "password")
|
|
|
|
If Username = "" Or Password = ""
|
|
General::RespondJSON(*Request, ~"{\"success\":false,\"error\":\"Missing credentials\"}")
|
|
ProcedureReturn
|
|
EndIf
|
|
|
|
Protected ValidUser.s = Database::ValidateCredentials(Username, Password)
|
|
|
|
If ValidUser <> ""
|
|
Protected UserID.i = Database::FindUser(ValidUser)
|
|
Protected Token.s = Database::CreateSession(UserID, ValidUser)
|
|
SetSessionCookie(*Request, Token)
|
|
FastCGI::WriteResponseHeader(*Request, "Content-Type", "application/json; charset=utf-8")
|
|
FastCGI::WriteResponseHeader(*Request, "Cache-Control", "no-cache, no-store")
|
|
FastCGI::WriteResponseString(*Request, ~"{\"success\":true,\"username\":\"" + ValidUser + ~"\"}")
|
|
FastCGI::FinishResponse(*Request)
|
|
Else
|
|
; Uniform error - don't reveal which field was wrong
|
|
General::RespondJSON(*Request, ~"{\"success\":false,\"error\":\"Invalid username or password\"}")
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure HandleLogout(*Request)
|
|
Protected Token.s = FastCGI::GetCookie(*Request, #SESSION_COOKIE)
|
|
If Token <> ""
|
|
Database::DeleteSession(Token)
|
|
EndIf
|
|
ClearSessionCookie(*Request)
|
|
General::RespondJSON(*Request, ~"{\"success\":true}")
|
|
EndProcedure
|
|
|
|
Procedure HandleCheck(*Request)
|
|
Protected Token.s = FastCGI::GetCookie(*Request, #SESSION_COOKIE)
|
|
Protected Username.s = ""
|
|
|
|
If Token <> ""
|
|
Username = Database::ValidateSession(Token)
|
|
EndIf
|
|
|
|
If Username <> ""
|
|
General::RespondJSON(*Request, ~"{\"authenticated\":true,\"username\":\"" + Username + ~"\"}")
|
|
Else
|
|
General::RespondJSON(*Request, ~"{\"authenticated\":false}")
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure.s GetSessionUser(*Request)
|
|
Protected Token.s = FastCGI::GetCookie(*Request, #SESSION_COOKIE)
|
|
If Token <> ""
|
|
ProcedureReturn Database::ValidateSession(Token)
|
|
EndIf
|
|
ProcedureReturn ""
|
|
EndProcedure
|
|
|
|
Procedure HandleChangePassword(*Request)
|
|
Protected Username.s = GetSessionUser(*Request)
|
|
If Username = ""
|
|
General::RespondJSON(*Request, ~"{\"error\":\"Unauthorized\"}", "401 Unauthorized")
|
|
ProcedureReturn
|
|
EndIf
|
|
|
|
Protected CurrentPwd.s = General::GetPostField(*Request, "current_password")
|
|
Protected NewPwd.s = General::GetPostField(*Request, "new_password")
|
|
|
|
If CurrentPwd = "" Or NewPwd = ""
|
|
General::RespondJSON(*Request, ~"{\"error\":\"Missing fields\"}")
|
|
ProcedureReturn
|
|
EndIf
|
|
|
|
If Database::ValidateCredentials(Username, CurrentPwd) = ""
|
|
General::RespondJSON(*Request, ~"{\"error\":\"Current password is incorrect\"}")
|
|
ProcedureReturn
|
|
EndIf
|
|
|
|
Protected UserID.i = Database::FindUser(Username)
|
|
Database::ChangePassword(UserID, NewPwd)
|
|
General::RespondJSON(*Request, ~"{\"success\":true}")
|
|
EndProcedure
|
|
|
|
EndModule
|
|
|
|
; IDE Options = PureBasic 6.30 (Windows - x64)
|
|
; CursorPosition = 29
|
|
; Folding = B5
|
|
; EnableXP
|
|
; DPIAware |