Files
vpn-panel/internal/session/session.go
T

65 lines
1.3 KiB
Go

package session
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"errors"
"strings"
"time"
"github.com/google/uuid"
)
const cookieName = "vpn_panel_session"
const maxAge = 7 * 24 * time.Hour
type Data struct {
UserID uuid.UUID `json:"uid"`
Email string `json:"email"`
Role string `json:"role"`
Exp int64 `json:"exp"`
}
func CookieName() string { return cookieName }
func Sign(secret string, d Data) (string, error) {
d.Exp = time.Now().Add(maxAge).Unix()
payload, err := json.Marshal(d)
if err != nil {
return "", err
}
b64 := base64.RawURLEncoding.EncodeToString(payload)
sig := sign(secret, b64)
return b64 + "." + sig, nil
}
func Verify(secret, token string) (*Data, error) {
parts := strings.Split(token, ".")
if len(parts) != 2 {
return nil, errors.New("invalid token")
}
if sign(secret, parts[0]) != parts[1] {
return nil, errors.New("bad signature")
}
raw, err := base64.RawURLEncoding.DecodeString(parts[0])
if err != nil {
return nil, err
}
var d Data
if err := json.Unmarshal(raw, &d); err != nil {
return nil, err
}
if time.Now().Unix() > d.Exp {
return nil, errors.New("expired")
}
return &d, nil
}
func sign(secret, payload string) string {
m := hmac.New(sha256.New, []byte(secret))
m.Write([]byte(payload))
return base64.RawURLEncoding.EncodeToString(m.Sum(nil))
}