In this Golang Web Development Series #31, we're building a complete Golang HTTP User Authentication System from scratch with the backend MySQL database by using Golang's official MySQL Database Driver. The Golang HTTP Authentication will consist of Golang User Registration, Golang Login Auth, Golang Password Reset, Golang Change Password, Golang Set Cookie, Golang Web Assembly (WASM), Golang Map Token, Golang Persisted Token, etc. with step by step guide here in Golang's Web Development Series.
#MaharlikansCode
#GolangWebDevelopment31
#GolangUserAuthenticationSystem
#MySQLDatabase
#YabiSeries11
#GolangWASM
#GolangWebAssembly
#GolangTutorial
#LearnGolangWebDevelopment
#Golang
#LifeAsSoftwareDeveloper
#Maharlikans
#FilipinoSoftwareDeveloper
Get Linode Account:
https://www.linode.com/?r=6aae17162e9...
If you go with extra mile for buying me a cup of coffee, I appreciate it guys: https://ko-fi.com/maharlikanscode
A simple, lightweight JavaScript API for handling browser cookies
https://github.com/js-cookie/js-cookie
Convert epoch to human-readable date and vice versa
https://www.epochconverter.com/
For Google Chrome cookie storage:
chrome://settings/cookies/detail?site=127.0.0.1&search=cookie
Source code:
yabi/helpers.go:
package yabi
import (
"fmt"
"net/http"
"strings"
"github.com/itrepablik/itrlog"
"github.com/itrepablik/tago"
"github.com/itrepablik/timaan"
)
func LoginRequired(endpoint func(http.ResponseWriter, *http.Request), secretKey string) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(YabiCookieName)
if err != nil {
itrlog.Error(err)
LogOut(w, r, secretKey) // Trigger the log-out event
return
}
userName, err := tago.Decrypt(cookie.Value, secretKey)
fmt.Println("userName LoginRequired: ", userName)
if err != nil {
itrlog.Error(err)
LogOut(w, r, secretKey)
return
}
// Extract the Timaan token payload
tok, err := timaan.DecodePayload(userName)
if err != nil {
itrlog.Error(err)
LogOut(w, r, secretKey) // Trigger the log-out event
return
}
payLoad := tok.Payload
for field, val := range payLoad {
fmt.Println(field, " : ", val)
}
if strings.TrimSpace(tok.TokenKey) == userName {
endpoint(w, r) // load whatever the requested protected pages
} else {
// otherwise, logout asap for unauthorized user
LogOut(w, r, secretKey) // Trigger the log-out event
}
})
}
// LogOut will be called when the user has been properly logout from the system.
func LogOut(w http.ResponseWriter, r *http.Request, secretKey string) {
// Read cookie and get the cookie here and decrypt it.
cookie, err := r.Cookie(YabiCookieName)
if err != nil {
itrlog.Error(err)
ReAuth(w, r) // Back to login page
return
}
// Decrypt the cookie encrypted username.
userName, err := tago.Decrypt(cookie.Value, secretKey)
if err != nil {
itrlog.Error(err)
ReAuth(w, r) // Back to login page
return
}
// Delete the specified username once logout
isTokenRemove, err := timaan.UT.Remove(userName)
if err != nil {
itrlog.Error(err)
ReAuth(w, r) // Back to login page
return
}
fmt.Println("isTokenRemove: ", isTokenRemove)
itrlog.Info("isTokenRemove: ", isTokenRemove)
// Delete from the "yabi_user_token" table as well
// ************to follow***************
// Expire the cookie immediately.
cookie = &http.Cookie{
Name: YabiCookieName,
Value: "",
Path: "/",
MaxAge: -1,
}
http.SetCookie(w, cookie)
itrlog.Warn("User has been log-out: ", userName)
ReAuth(w, r) // Back to the login page
}
// ReAuth will redirect the user's to the login page to re-authenticate if not authenticated.
func ReAuth(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/login", 302)
}
api/dashboard.go:
package api
import (
"gowebapp/config"
"gowebapp/yabi"
"html/template"
"net/http"
"github.com/gorilla/csrf"
"github.com/gorilla/mux"
)
// DashboardRouters are the collection of all URLs for the Dashboard App.
func DashboardRouters(r *mux.Router) {
r.HandleFunc("/dashboard", yabi.LoginRequired(Dashboard, config.MyEncryptDecryptSK)).Methods("GET")
}
// Dashboard function is to render the user's registration page.
func Dashboard(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles(config.SiteRootTemplate+"dashboard/index.html",
config.SiteHeaderDashTemplate, config.SiteFooterDashTemplate))
data := contextData{
"PageTitle": "Dashboard - " + config.SiteShortName,
"PageMetaDesc": config.SiteShortName + " dashboard, managing your user's transactions.",
"CanonicalURL": r.RequestURI,
"CsrfToken": csrf.Token(r),
"Settings": config.SiteSettings,
}
tmpl.Execute(w, data)
}
Get the full source codes:
https://github.com/maharlikanscode/Go...