Select Git revision
session.go 4.43 KiB
package auth
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"github.com/aws/aws-lambda-go/events"
"github.com/google/uuid"
"github.com/thoas/go-funk"
"gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/date_utils"
"gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/handler_utils"
"time"
)
type SessionToken struct {
IP string `json:"ip"`
UserAgent string `json:"user_agent"`
TimeCreated time.Time `json:"time_created"`
Token string `json:"session_token"`
}
// SignSessionTokenWithKey signs the session token string using the secret.
func SignSessionTokenWithKey(secretKey string, sessionTokenString string) string {
signer := hmac.New(sha256.New, []byte(secretKey))
signer.Write([]byte(sessionTokenString))
return hex.EncodeToString(signer.Sum(nil))
}
// GetSessionTokenString creates a unique session token string from the API request.
func GetSessionTokenString(request events.APIGatewayProxyRequest) (string, error) {
sessionToken := SessionToken{
IP: request.RequestContext.Identity.SourceIP,
UserAgent: handler_utils.FindHeaderValue(request.Headers, "user-agent"),
TimeCreated: date_utils.CurrentDate().Round(time.Second),
Token: uuid.New().String(),
}
sessionTokenBytes, err := json.Marshal(sessionToken)
return string(sessionTokenBytes), err
}
// GetSignedSessionTokenString creates a unique session token string from the API request and signs it using the secret.
func GetSignedSessionTokenString(request events.APIGatewayProxyRequest, secretKey string) (string, error) {
sessionTokenBytes, err := GetSessionTokenString(request)
if err != nil {
return "", err
}
return SignSessionTokenWithKey(secretKey, sessionTokenBytes), nil
}
// ValidateJWTWithSessionTokens attempts to validate the JWT string by signing each session token using the secret, and
// using the resulting signed session token to validate the JWT. If the JWT can be validated using a session token, the
// JsonWebToken is returned, otherwise nil is returned. If the JWT is expired, nil is returned along with the session token.
func ValidateJWTWithSessionTokens(jsonWebTokenString string, secretKey string, sessionTokens []string) (validJsonWebToken *JsonWebToken, expiredSessionToken *string) {
// Test each session token to find one that is valid
for _, sessionToken := range sessionTokens {
jsonWebToken, err := ValidateJWTWithSessionToken(jsonWebTokenString, secretKey, sessionToken)
if err == nil {
return &jsonWebToken, nil
} else if err.Error() == "token has expired" {
return nil, &sessionToken
}
}
return nil, nil
}
// FindAndRemoveCurrentSessionToken attempts to validate the JWT string by signing each session token using the secret,
// and using the resulting signed session token to validate the JWT. If the JWT is successfully validated with one of