first commit
This commit is contained in:
111
accounts/jwt.go
Normal file
111
accounts/jwt.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
type jwtClaims struct {
|
||||
UserID uint `json:"user_id"`
|
||||
Role string `json:"role"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
const (
|
||||
RoleAdmin = "admin"
|
||||
RoleUser = "user"
|
||||
)
|
||||
|
||||
func GenerateTokens(userID uint, role string) (string, string, error) {
|
||||
accessSecret := os.Getenv("JWT_SECRET")
|
||||
refreshSecret := os.Getenv("JWT_REFRESH_SECRET")
|
||||
if accessSecret == "" || refreshSecret == "" {
|
||||
return "", "", fmt.Errorf("JWT secrets are not set")
|
||||
}
|
||||
|
||||
normalizedRole := normalizeRole(role)
|
||||
|
||||
// Access Token
|
||||
accessClaims := jwtClaims{
|
||||
UserID: userID,
|
||||
Role: normalizedRole,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
},
|
||||
}
|
||||
accessToken := jwt.NewWithClaims(jwt.SigningMethodHS256, accessClaims)
|
||||
accessString, err := accessToken.SignedString([]byte(accessSecret))
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// Refresh Token
|
||||
refreshClaims := jwtClaims{
|
||||
UserID: userID,
|
||||
Role: normalizedRole,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(7 * 24 * time.Hour)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
},
|
||||
}
|
||||
refreshToken := jwt.NewWithClaims(jwt.SigningMethodHS256, refreshClaims)
|
||||
refreshString, err := refreshToken.SignedString([]byte(refreshSecret))
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
return accessString, refreshString, nil
|
||||
}
|
||||
|
||||
func ParseAccessToken(tokenString string) (uint, error) {
|
||||
secret := os.Getenv("JWT_SECRET")
|
||||
claims, err := parseTokenClaims(tokenString, secret)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return claims.UserID, nil
|
||||
}
|
||||
|
||||
func ParseRefreshToken(tokenString string) (uint, error) {
|
||||
secret := os.Getenv("JWT_REFRESH_SECRET")
|
||||
claims, err := parseTokenClaims(tokenString, secret)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return claims.UserID, nil
|
||||
}
|
||||
|
||||
func parseAccessClaims(tokenString string) (*jwtClaims, error) {
|
||||
secret := os.Getenv("JWT_SECRET")
|
||||
return parseTokenClaims(tokenString, secret)
|
||||
}
|
||||
|
||||
func parseTokenClaims(tokenString, secret string) (*jwtClaims, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &jwtClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(secret), nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if claims, ok := token.Claims.(*jwtClaims); ok && token.Valid {
|
||||
claims.Role = normalizeRole(claims.Role)
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("invalid token")
|
||||
}
|
||||
|
||||
func normalizeRole(role string) string {
|
||||
switch role {
|
||||
case RoleAdmin:
|
||||
return RoleAdmin
|
||||
default:
|
||||
return RoleUser
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user