/*
* This file is part of sdbapi
* Copyright (C) 2022 Jonni Liljamo <jonni@liljamo.com>
*
* Licensed under GPL-3.0-only.
* See LICENSE for licensing information.
*/
package auth
import (
"api/db"
"errors"
"os"
"time"
"github.com/golang-jwt/jwt/v4"
)
var JWTSecret = []byte(os.Getenv("SDBAPI_JWT_SECRET"))
type JWTClaims struct {
Username string `json:"username"`
Email string `json:"email"`
jwt.RegisteredClaims
}
func NewJWTToken(username string, email string) (token string, err error) {
claims := JWTClaims{
Username: username,
Email: email,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(1 * time.Hour)),
},
}
jwtClaims := jwt.NewWithClaims(jwt.SigningMethodHS512, claims)
token, err = jwtClaims.SignedString(JWTSecret)
return
}
func ValidateJWTToken(userToken string) (claims *JWTClaims, err error) {
token, err := jwt.ParseWithClaims(
userToken,
&JWTClaims{},
func(token *jwt.Token) (interface{}, error) {
return []byte(JWTSecret), nil
},
)
if err != nil {
return
}
if !token.Valid {
err = errors.New("token not valid")
return
}
claims, ok := token.Claims.(*JWTClaims)
if !ok {
err = errors.New("could not parse JWT claims")
return
}
if claims.ExpiresAt.Unix() < time.Now().Local().Unix() {
err = errors.New("token is expired")
return
}
// Auth should match a registered user
// NOTE: Technically auth should always match a registered user, but just in-case.
// TOFIX: Or, now that I think about it, I should run some tests to see if this
// truly is just dumb to check.
_, uerr := db.GetUserByEmail(claims.Email)
if uerr != nil {
err = errors.New("user does not exist")
return
}
return
}