- Refactory cookie and API session handle. Insolated y routes and controllers (api-auth.go, app-auth.go).
- Cookie lifetime with sliding expiration - Fix bug single global expiresAt in JWT, now each token has unique ExpiresAt
This commit is contained in:
parent
bf8e2e90ec
commit
10ded026df
10 changed files with 358 additions and 304 deletions
|
|
@ -3,8 +3,6 @@ package hooks
|
|||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.smarteching.com/goffee/core"
|
||||
|
|
@ -14,90 +12,45 @@ import (
|
|||
|
||||
var CheckSessionCookie core.Hook = func(c *core.Context) {
|
||||
|
||||
pass := true
|
||||
token := ""
|
||||
usercookie, err := c.GetCookie()
|
||||
if err != nil {
|
||||
pass := false
|
||||
|
||||
}
|
||||
token = usercookie.Token
|
||||
if token == "" {
|
||||
pass = false
|
||||
} else {
|
||||
payload, err := c.GetJWT().DecodeToken(token)
|
||||
if err != nil {
|
||||
pass = false
|
||||
} else {
|
||||
|
||||
userAgent := c.GetUserAgent()
|
||||
hashedCacheKey := core.CreateAuthTokenHashedCacheKey(uint(c.CastToInt(payload["userID"])), userAgent)
|
||||
|
||||
cachedToken, err := c.GetCache().Get(hashedCacheKey)
|
||||
if err != nil {
|
||||
pass = false
|
||||
} else if cachedToken != token {
|
||||
pass = false
|
||||
} else {
|
||||
var user models.User
|
||||
res := c.GetGorm().Where("id = ?", payload["userID"]).First(&user)
|
||||
if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) {
|
||||
pass = false
|
||||
}
|
||||
}
|
||||
// Validate the cookie based session through the core session. This also
|
||||
// transparently performs sliding expiration renewal when applicable.
|
||||
session := c.GetSession()
|
||||
if session.Init(c) {
|
||||
// ensure the authenticated user still exists in the database
|
||||
var user models.User
|
||||
res := c.GetGorm().Where("id = ?", session.GetUserID()).First(&user)
|
||||
if res.Error == nil || errors.Is(res.Error, gorm.ErrRecordNotFound) {
|
||||
pass = true
|
||||
}
|
||||
}
|
||||
// if have session redirect protected page
|
||||
|
||||
if pass {
|
||||
c.Response.Redirect("/appsample").ForceSendResponse()
|
||||
c.Next()
|
||||
} else {
|
||||
c.Response.Redirect("/applogin").ForceSendResponse()
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
|
||||
}
|
||||
|
||||
var AuthCheck core.Hook = func(c *core.Context) {
|
||||
var APIAuthCheck core.Hook = func(c *core.Context) {
|
||||
|
||||
// check if template engine is enable
|
||||
TemplateEnableStr := os.Getenv("TEMPLATE_ENABLE")
|
||||
if TemplateEnableStr == "" {
|
||||
TemplateEnableStr = "false"
|
||||
}
|
||||
TemplateEnable, _ := strconv.ParseBool(TemplateEnableStr)
|
||||
|
||||
token := ""
|
||||
|
||||
if TemplateEnable {
|
||||
usercookie, err := c.GetCookie()
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
token = usercookie.Token
|
||||
if token == "" {
|
||||
c.Response.Redirect("/applogin").ForceSendResponse()
|
||||
return
|
||||
}
|
||||
|
||||
} else {
|
||||
tokenRaw := c.GetHeader("Authorization")
|
||||
token = strings.TrimSpace(strings.Replace(tokenRaw, "Bearer", "", 1))
|
||||
if token == "" {
|
||||
c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{
|
||||
"message": "unauthorized",
|
||||
})).ForceSendResponse()
|
||||
return
|
||||
}
|
||||
// --- API/bearer flow ---
|
||||
tokenRaw := c.GetHeader("Authorization")
|
||||
token := strings.TrimSpace(strings.Replace(tokenRaw, "Bearer", "", 1))
|
||||
if token == "" {
|
||||
c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{
|
||||
"message": "unauthorized",
|
||||
})).ForceSendResponse()
|
||||
return
|
||||
}
|
||||
|
||||
payload, err := c.GetJWT().DecodeToken(token)
|
||||
if err != nil {
|
||||
if TemplateEnable {
|
||||
c.Response.Redirect("/applogin").ForceSendResponse()
|
||||
} else {
|
||||
c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{
|
||||
"message": "unauthorized",
|
||||
})).ForceSendResponse()
|
||||
}
|
||||
c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{
|
||||
"message": "unauthorized",
|
||||
})).ForceSendResponse()
|
||||
return
|
||||
}
|
||||
userAgent := c.GetUserAgent()
|
||||
|
|
@ -106,24 +59,16 @@ var AuthCheck core.Hook = func(c *core.Context) {
|
|||
cachedToken, err := c.GetCache().Get(hashedCacheKey)
|
||||
if err != nil {
|
||||
// user signed out
|
||||
if TemplateEnable {
|
||||
c.Response.Redirect("/applogin").ForceSendResponse()
|
||||
} else {
|
||||
c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{
|
||||
"message": "unauthorized",
|
||||
})).ForceSendResponse()
|
||||
}
|
||||
c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{
|
||||
"message": "unauthorized",
|
||||
})).ForceSendResponse()
|
||||
return
|
||||
}
|
||||
if cachedToken != token {
|
||||
// using old token replaced with new one after recent signin
|
||||
if TemplateEnable {
|
||||
c.Response.Redirect("/applogin").ForceSendResponse()
|
||||
} else {
|
||||
c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{
|
||||
"message": "unauthorized",
|
||||
})).ForceSendResponse()
|
||||
}
|
||||
c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{
|
||||
"message": "unauthorized",
|
||||
})).ForceSendResponse()
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -132,13 +77,9 @@ var AuthCheck core.Hook = func(c *core.Context) {
|
|||
if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) {
|
||||
// error with the database
|
||||
c.GetLogger().Error(res.Error.Error())
|
||||
if TemplateEnable {
|
||||
c.Response.Redirect("/applogin").ForceSendResponse()
|
||||
} else {
|
||||
c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]interface{}{
|
||||
"message": "internal error",
|
||||
})).ForceSendResponse()
|
||||
}
|
||||
c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]interface{}{
|
||||
"message": "internal error",
|
||||
})).ForceSendResponse()
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue