Add JWT authentication for admin dashboard login
This commit is contained in:
@@ -49,6 +49,7 @@ func main() {
|
|||||||
runFetchPosts()
|
runFetchPosts()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Run initial fetch on startup
|
// Run initial fetch on startup
|
||||||
go func() {
|
go func() {
|
||||||
runFetchPosts()
|
runFetchPosts()
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"CatsOfMastodonBotGo/internal/auth"
|
||||||
"CatsOfMastodonBotGo/internal/services"
|
"CatsOfMastodonBotGo/internal/services"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -10,6 +11,7 @@ import (
|
|||||||
type AppContext struct {
|
type AppContext struct {
|
||||||
Db *gorm.DB
|
Db *gorm.DB
|
||||||
PostService *services.PostService
|
PostService *services.PostService
|
||||||
|
Jwt *auth.JwtTokenGenerator
|
||||||
AdminPassword string
|
AdminPassword string
|
||||||
Instance string
|
Instance string
|
||||||
Tag string
|
Tag string
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
// "github.com/gin-gonic/gin"
|
|
||||||
// "gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// type AppWebContext struct {
|
|
||||||
// Db *gorm.DB
|
|
||||||
// GinEngine *gin.Engine
|
|
||||||
// }
|
|
@@ -1,2 +1,58 @@
|
|||||||
package auth
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JwtTokenGenerator struct {
|
||||||
|
Key string
|
||||||
|
Issuer string
|
||||||
|
Audience string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewJwtTokenGenerator(key string, issuer string, audience string) *JwtTokenGenerator {
|
||||||
|
return &JwtTokenGenerator{
|
||||||
|
Key: key,
|
||||||
|
Issuer: issuer,
|
||||||
|
Audience: audience,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JwtTokenGenerator) GenerateToken(claims map[string]interface{}) (string, error) {
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||||
|
"exp": time.Now().AddDate(0, 0, 3).Unix(),
|
||||||
|
"iat": time.Now().Unix(),
|
||||||
|
"iss": j.Issuer,
|
||||||
|
"aud": j.Audience,
|
||||||
|
})
|
||||||
|
for k, v := range claims {
|
||||||
|
token.Claims.(jwt.MapClaims)[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return token.SignedString([]byte(j.Key))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gin middleware
|
||||||
|
func (j *JwtTokenGenerator) GinMiddleware() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
token, err := c.Request.Cookie("token")
|
||||||
|
if err != nil {
|
||||||
|
c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = jwt.Parse(token.Value, func(t *jwt.Token) (interface{}, error) {
|
||||||
|
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
|
return nil, jwt.ErrSignatureInvalid
|
||||||
|
}
|
||||||
|
return []byte(j.Key), nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
@@ -2,6 +2,7 @@ package helpers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"CatsOfMastodonBotGo/internal"
|
"CatsOfMastodonBotGo/internal"
|
||||||
|
"CatsOfMastodonBotGo/internal/auth"
|
||||||
"CatsOfMastodonBotGo/internal/services"
|
"CatsOfMastodonBotGo/internal/services"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@@ -27,6 +28,22 @@ func SetupAppContext() *internal.AppContext {
|
|||||||
adminPassword = "catsaregood"
|
adminPassword = "catsaregood"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Jwt params
|
||||||
|
secret := os.Getenv("CAOM_JWT_SECRET")
|
||||||
|
if secret == "" {
|
||||||
|
log.Fatal("No jwt secret provided, using default secret 'secret'")
|
||||||
|
}
|
||||||
|
issuer := os.Getenv("CAOM_JWT_ISSUER")
|
||||||
|
if issuer == "" {
|
||||||
|
log.Println("No jwt issuer provided, using default issuer 'CatsOfMastodonBotGo'")
|
||||||
|
issuer = "CatsOfMastodonBotGo"
|
||||||
|
}
|
||||||
|
audience := os.Getenv("CAOM_JWT_AUDIENCE")
|
||||||
|
if audience == "" {
|
||||||
|
log.Println("No jwt audience provided, using default audience 'CatsOfMastodonBotGo'")
|
||||||
|
audience = "CatsOfMastodonBotGo"
|
||||||
|
}
|
||||||
|
|
||||||
// Setup database
|
// Setup database
|
||||||
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{Logger: logger.Default.LogMode(logger.Warn)})
|
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{Logger: logger.Default.LogMode(logger.Warn)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -37,10 +54,15 @@ func SetupAppContext() *internal.AppContext {
|
|||||||
//Setup PostService
|
//Setup PostService
|
||||||
var postService = services.NewPostService(db)
|
var postService = services.NewPostService(db)
|
||||||
|
|
||||||
|
// Setup Jwt
|
||||||
|
var jwt = auth.NewJwtTokenGenerator(secret, issuer, audience)
|
||||||
|
|
||||||
// Inititlize AppContext
|
// Inititlize AppContext
|
||||||
var appContext = &internal.AppContext{
|
var appContext = &internal.AppContext{
|
||||||
Db: db,
|
Db: db,
|
||||||
PostService: postService,
|
PostService: postService,
|
||||||
|
Jwt: jwt,
|
||||||
|
AdminPassword: adminPassword,
|
||||||
Instance: instance,
|
Instance: instance,
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
}
|
}
|
||||||
|
@@ -47,8 +47,18 @@ func (appContext *AdminDashboardHandler) Login(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if input.Password == appContext.AppContext.AdminPassword {
|
if input.Password == appContext.AppContext.AdminPassword {
|
||||||
c.JSON(200, gin.H{
|
token, err := appContext.AppContext.Jwt.GenerateToken(map[string]interface{}{"role": "admin"})
|
||||||
"YouAreOn": "AdminDashboardHomePage",
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Token generation failed"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.SetCookie("token", token, 3600, "/", "", false, true)
|
||||||
|
c.JSON(http.StatusOK, gin.H{"message": "Login successful"})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
c.JSON(401, gin.H{
|
||||||
|
"YouAreOn": "Unauthorized",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user