Files
NexaVPN/backend/internal/auth/token.go
nessi 830491cb0d chore: initial project scaffold with admin web, backend, desktop client, and deployment setup
Add monorepo structure for NexaVPN WireGuard control plane including:
- .gitignore for node_modules, build artifacts, and environment files
- README with project overview, monorepo layout, and quick start guide
- Admin web UI with React, Vite, TypeScript, and nginx reverse proxy
- API client with type definitions for users, devices, policies, gateways, and audit logs
- Admin pages for dashboard, users, devices, policies, g
2026-03-15 16:32:34 +01:00

78 lines
1.8 KiB
Go

package auth
import (
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/google/uuid"
)
func NewRefreshToken() (plain string, hashed string, err error) {
raw := make([]byte, 32)
if _, err = rand.Read(raw); err != nil {
return "", "", err
}
plain = base64.RawURLEncoding.EncodeToString(raw)
sum := sha256.Sum256([]byte(plain))
hashed = base64.RawURLEncoding.EncodeToString(sum[:])
return plain, hashed, nil
}
func SignAccessToken(secret, issuer string, ttl time.Duration, claims Claims) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"iss": issuer,
"sub": claims.UserID.String(),
"username": claims.Username,
"role": claims.Role,
"session_id": claims.Session.String(),
"exp": time.Now().Add(ttl).Unix(),
"iat": time.Now().Unix(),
})
return token.SignedString([]byte(secret))
}
func ParseAccessToken(secret string, tokenString string) (Claims, error) {
claims := Claims{}
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (any, error) {
return []byte(secret), nil
})
if err != nil || !token.Valid {
return claims, err
}
mapClaims, ok := token.Claims.(jwt.MapClaims)
if !ok {
return claims, jwt.ErrTokenMalformed
}
subject, ok := mapClaims["sub"].(string)
if !ok {
return claims, jwt.ErrTokenMalformed
}
sessionValue, ok := mapClaims["session_id"].(string)
if !ok {
return claims, jwt.ErrTokenMalformed
}
userID, err := uuid.Parse(subject)
if err != nil {
return claims, err
}
sessionID, err := uuid.Parse(sessionValue)
if err != nil {
return claims, err
}
claims.UserID = userID
claims.Session = sessionID
claims.Username, _ = mapClaims["username"].(string)
claims.Role, _ = mapClaims["role"].(string)
return claims, nil
}