server added
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
package auxjwt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/lestrrat-go/jwx/jwa"
|
||||
"github.com/lestrrat-go/jwx/jwt"
|
||||
)
|
||||
|
||||
const (
|
||||
SessionIDKey = "sessionId"
|
||||
jwtAlg = jwa.HS256
|
||||
)
|
||||
|
||||
func MakeJWTToken(issuer, subject string, sessionID int64, lifetime time.Duration, secret []byte) ([]byte, int64, error) {
|
||||
var err error
|
||||
|
||||
issueTime := time.Now()
|
||||
expireTime := time.Now().Add(lifetime)
|
||||
expireUnix := expireTime.Unix()
|
||||
|
||||
token := jwt.New()
|
||||
token.Set(jwt.IssuerKey, issuer)
|
||||
token.Set(jwt.SubjectKey, subject)
|
||||
token.Set(jwt.ExpirationKey, expireTime)
|
||||
token.Set(jwt.IssuedAtKey, issueTime)
|
||||
token.Set(jwt.IssuedAtKey, issueTime)
|
||||
token.Set(SessionIDKey, sessionID)
|
||||
|
||||
tokenBytes, err := jwt.Sign(token, jwtAlg, []byte(secret))
|
||||
if err != nil {
|
||||
return tokenBytes, expireUnix, err
|
||||
}
|
||||
return tokenBytes, expireUnix, err
|
||||
}
|
||||
|
||||
func GetJWTSessionID(tokenBytes, secret []byte) (int64, error) {
|
||||
var err error
|
||||
var sessionID int64
|
||||
|
||||
parseOpt := []jwt.ParseOption{
|
||||
jwt.WithVerify(jwtAlg, secret),
|
||||
jwt.WithValidator(jwt.IsExpirationValid()),
|
||||
jwt.WithValidate(true),
|
||||
}
|
||||
token, err := jwt.Parse(tokenBytes, parseOpt...)
|
||||
if err != nil {
|
||||
return sessionID, err
|
||||
}
|
||||
|
||||
anyValue, exists := token.Get(SessionIDKey)
|
||||
if !exists {
|
||||
err := errors.New("Token does not include value is sessionId")
|
||||
return sessionID, err
|
||||
}
|
||||
|
||||
fValue, convOk := anyValue.(float64)
|
||||
if !convOk {
|
||||
err := errors.New("Cannont convert value of sessionId to float64")
|
||||
return sessionID, err
|
||||
}
|
||||
|
||||
sessionID = int64(math.Round(fValue))
|
||||
return sessionID, err
|
||||
}
|
||||
|
||||
func ValidateJWTToken(tokenBytes []byte, issuer, subject string, secret []byte) error {
|
||||
|
||||
parseOpt := []jwt.ParseOption{
|
||||
jwt.WithVerify(jwtAlg, secret),
|
||||
jwt.WithValidator(jwt.IsExpirationValid()),
|
||||
jwt.WithValidate(true),
|
||||
}
|
||||
token, err := jwt.Parse(tokenBytes, parseOpt...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
validateOpt := []jwt.ValidateOption{
|
||||
jwt.WithSubject(subject),
|
||||
jwt.WithIssuer(issuer),
|
||||
jwt.WithValidator(jwt.IsIssuedAtValid()),
|
||||
jwt.WithValidator(jwt.IsExpirationValid()),
|
||||
}
|
||||
err = jwt.Validate(token, validateOpt...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package auxjwt
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestJWTGood(t *testing.T) {
|
||||
const issuer = "Issuer"
|
||||
const subject = "Subject"
|
||||
const lifetime = 10 * time.Second
|
||||
secret := []byte("12345")
|
||||
var sessionId int64 = 123456789
|
||||
|
||||
var err error
|
||||
tokenBytes, _, err := MakeJWTToken(issuer, subject, sessionId, lifetime, secret)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, tokenBytes)
|
||||
|
||||
recvSessionID, err := GetJWTSessionID(tokenBytes, secret)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, sessionId, recvSessionID)
|
||||
|
||||
err = ValidateJWTToken(tokenBytes, issuer, subject, secret)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestJWTTimeExpired(t *testing.T) {
|
||||
|
||||
const issuer = "Issuer"
|
||||
const subject = "Subject"
|
||||
const lifetime = 1 * time.Second
|
||||
secret := []byte("12345")
|
||||
var sessionId int64 = 123456789
|
||||
|
||||
var err error
|
||||
tokenBytes, _, err := MakeJWTToken(issuer, subject, sessionId, lifetime, secret)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, tokenBytes)
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
err = ValidateJWTToken(tokenBytes, issuer, subject, secret)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestJWTWrongSecret(t *testing.T) {
|
||||
|
||||
const issuer = "Issuer"
|
||||
const subject = "Subject"
|
||||
const lifetime = 10 * time.Second
|
||||
secret := []byte("12345")
|
||||
var sessionId int64 = 123456789
|
||||
|
||||
var err error
|
||||
tokenBytes, _, err := MakeJWTToken(issuer, subject, sessionId, lifetime, secret)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, tokenBytes)
|
||||
|
||||
secret = []byte("12345+1")
|
||||
err = ValidateJWTToken(tokenBytes, issuer, subject, secret)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestJWTWrongIssuer(t *testing.T) {
|
||||
var issuer = "Issuer"
|
||||
const subject = "Subject"
|
||||
const lifetime = 10 * time.Second
|
||||
secret := []byte("12345")
|
||||
var sessionId int64 = 123456789
|
||||
|
||||
var err error
|
||||
tokenBytes, _, err := MakeJWTToken(issuer, subject, sessionId, lifetime, secret)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, tokenBytes)
|
||||
|
||||
issuer = "mr.santa"
|
||||
err = ValidateJWTToken(tokenBytes, issuer, subject, secret)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestJWTWrongSubject(t *testing.T) {
|
||||
const issuer = "Issuer"
|
||||
var subject = "Subject"
|
||||
const lifetime = 10 * time.Second
|
||||
secret := []byte("12345")
|
||||
var sessionId int64 = 123456789
|
||||
|
||||
var err error
|
||||
tokenBytes, _, err := MakeJWTToken(issuer, subject, sessionId, lifetime, secret)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, tokenBytes)
|
||||
|
||||
subject = "$$$"
|
||||
|
||||
err = ValidateJWTToken(tokenBytes, issuer, subject, secret)
|
||||
require.Error(t, err)
|
||||
}
|
||||
Reference in New Issue
Block a user