feat: add utility functions and helpers

- Add JWT token generation and validation utilities
- Add password hashing with bcrypt for secure authentication
- Add pagination helper for API responses
- Add random string generation for tokens and IDs
- Add session management utilities
- Add admin user initialization functionality
This commit is contained in:
Björn Benouarets
2025-09-25 23:24:18 +02:00
parent 9a8a93061d
commit f509f6e524
6 changed files with 297 additions and 0 deletions

94
utils/session.go Normal file
View File

@@ -0,0 +1,94 @@
package utils
import (
"encoding/base64"
"fmt"
"strings"
"git.secnex.io/secnex/idp-api/api"
"github.com/gofiber/fiber/v2"
)
type AuthType string
const (
AuthTypeSession AuthType = "scn"
)
func ExtractBasicAuthFromHeader(header string, c *fiber.Ctx) (string, string, error) {
if header == "" {
return "", "", api.Error(c, "Unauthorized", fiber.StatusUnauthorized, fiber.Map{
"message": "Authorization header is required",
})
}
// Decode base64
basicDecoded, err := base64.StdEncoding.DecodeString(header)
if err != nil {
return "", "", api.Error(c, "Unauthorized", fiber.StatusUnauthorized, fiber.Map{
"message": "Invalid authorization header",
})
}
basicSplit := strings.Split(string(basicDecoded), ":")
return basicSplit[0], basicSplit[1], nil
}
func ExtractSessionFromHeader(header string, c *fiber.Ctx) (string, error) {
if header == "" {
return "", api.Error(c, "Unauthorized", fiber.StatusUnauthorized, fiber.Map{
"message": "Authorization header is required",
})
}
sessionSplit := strings.Split(header, ":")
if len(sessionSplit) != 2 {
return "", api.Error(c, "Unauthorized", fiber.StatusUnauthorized, fiber.Map{
"message": "Invalid authorization header",
})
}
authType := AuthType(sessionSplit[0])
if authType != AuthTypeSession {
return "", api.Error(c, "Unauthorized", fiber.StatusUnauthorized, fiber.Map{
"message": "Invalid authorization header",
})
}
sessionId, err := base64.StdEncoding.DecodeString(sessionSplit[1])
if err != nil {
return "", api.Error(c, "Unauthorized", fiber.StatusUnauthorized, fiber.Map{
"message": "Invalid authorization header",
})
}
return string(sessionId), nil
}
// ExtractSessionFromToken extracts session ID from a session token without Fiber context
// This is used for gRPC services where we don't have a Fiber context
func ExtractSessionFromToken(token string) (string, error) {
if token == "" {
return "", fmt.Errorf("session token is required")
}
sessionSplit := strings.Split(token, ":")
if len(sessionSplit) != 2 {
return "", fmt.Errorf("invalid session token format")
}
authType := AuthType(sessionSplit[0])
if authType != AuthTypeSession {
return "", fmt.Errorf("invalid auth type")
}
sessionId, err := base64.StdEncoding.DecodeString(sessionSplit[1])
if err != nil {
return "", fmt.Errorf("invalid session token encoding")
}
return string(sessionId), nil
}