sipd-auth/utils/jwt_manager.go
2025-09-16 08:32:11 +07:00

121 lines
3.5 KiB
Go

package utils
import (
"errors"
"fmt"
models "kemendagri/sipd/services/sipd_auth/model"
"os"
"strconv"
"time"
"github.com/golang-jwt/jwt/v4"
"github.com/jackc/pgx/v5/pgxpool"
)
type MyCustomClaim struct {
jwt.RegisteredClaims
Tahun int `json:"tahun"`
IdUser int64 `json:"id_user"`
IdDaerah int64 `json:"id_daerah"`
KodeProvinsi string `json:"kode_provinsi"`
KodeDdn string `json:"kode_ddn"`
IdSkpd int64 `json:"id_skpd"`
IdRole int `json:"id_role"`
IdPegawai int64 `json:"id_pegawai"`
SubDomainDaerah string `json:"sub_domain_daerah" xml:"sub_domain_daerah"`
}
type JWTManager struct {
secretKey string
issuer string
}
func NewJWTManager(secretKey, iss string) *JWTManager {
return &JWTManager{secretKey, iss}
}
func (m *JWTManager) Generate(dbConn *pgxpool.Pool, user models.User, tahun int, idPeg int64) (token, refreshToken string, jwtExpDuration time.Duration, err error) {
// ambil data durasi expired jwt dan refresh_token dari table sys config
var jwtExpiredMinutes, refreshTokenExpiredHour int64
jwtExpiredMinutes, err = strconv.ParseInt(os.Getenv("JWT_EXPIRED_MINUTES"), 10, 64)
refreshTokenExpiredHour, err = strconv.ParseInt(os.Getenv("REFRESH_TOKEN_EXPIRED_HOUR"), 10, 64)
jwtSub := fmt.Sprintf("%d.%d", user.IdUser, user.IdDaerah)
jwtExpDuration = time.Duration(jwtExpiredMinutes) * time.Minute
// Create jwt token
jwtClaims := MyCustomClaim{
RegisteredClaims: jwt.RegisteredClaims{
Issuer: m.issuer,
Subject: jwtSub,
ExpiresAt: jwt.NewNumericDate(time.Now().Add(jwtExpDuration)),
IssuedAt: &jwt.NumericDate{Time: time.Now()},
},
Tahun: tahun,
IdUser: user.IdUser,
IdDaerah: user.IdDaerah,
KodeProvinsi: user.KodeProvinsi,
KodeDdn: user.KodeDdn,
IdSkpd: user.IdSkpd,
IdRole: user.IdRole,
IdPegawai: idPeg,
SubDomainDaerah: user.SubDomainDaerah,
}
token, err = jwt.NewWithClaims(jwt.SigningMethodHS256, jwtClaims).SignedString([]byte(m.secretKey))
if err != nil {
return
}
// Create refresh token
refreshTokenClaims := MyCustomClaim{
RegisteredClaims: jwt.RegisteredClaims{
Issuer: m.issuer,
Subject: jwtSub,
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * time.Duration(refreshTokenExpiredHour))),
IssuedAt: &jwt.NumericDate{Time: time.Now()},
},
Tahun: tahun,
IdUser: user.IdUser,
IdDaerah: user.IdDaerah,
KodeProvinsi: user.KodeProvinsi,
KodeDdn: user.KodeDdn,
IdSkpd: user.IdSkpd,
IdRole: user.IdRole,
IdPegawai: idPeg,
SubDomainDaerah: user.SubDomainDaerah,
}
/*refreshTokenClaims := jwt.RegisteredClaims{
Issuer: m.issuer,
Subject: jwtSub,
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * time.Duration(refreshTokenExpiredHour))),
IssuedAt: &jwt.NumericDate{Time: time.Now()},
}*/
refreshToken, err = jwt.NewWithClaims(jwt.SigningMethodHS256, refreshTokenClaims).SignedString([]byte(m.secretKey))
if err != nil {
return
}
return
}
func (m *JWTManager) Verify(token string) (*MyCustomClaim, error) {
var r *MyCustomClaim
tDecoded, err := jwt.ParseWithClaims(token, &MyCustomClaim{}, func(token *jwt.Token) (interface{}, error) {
return []byte(m.secretKey), nil
})
if err != nil {
return r, err
}
if claims, ok := tDecoded.Claims.(*MyCustomClaim); ok && tDecoded.Valid {
if claims.ExpiresAt.Unix() < time.Now().Unix() {
return r, errors.New("token expired")
}
return claims, nil
}
return r, errors.New("invalid token")
}