Add: Session control

Merged Akshay Bharambe requested to merge ab_Add_UserSessions into devbranch
+ 77
82
package jwtmdl
import (
"fmt"
"strings"
"time"
"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/authmdl/sessionmdl"
"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/errormdl"
"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl"
jwt "github.com/dgrijalva/jwt-go"
@@ -14,46 +15,15 @@ import (
// GlobalJWTKey - key to decode and encode token
var GlobalJWTKey string
// // DecodeTokenWithJWTKey decode token
// func DecodeTokenWithJWTKey(req *http.Request, jwtKey string) (jwt.MapClaims, error) {
// token, err := request.ParseFromRequest(req, request.OAuth2Extractor, func(token *jwt.Token) (interface{}, error) {
// b := ([]byte(jwtKey))
// return b, nil
// })
// if errormdl.CheckErr(err) != nil {
// loggermdl.LogError("Error while parsing JWT Token: ", errormdl.CheckErr(err))
// return nil, errormdl.CheckErr(err)
// }
// claims, ok := token.Claims.(jwt.MapClaims)
// if !errormdl.CheckBool1(ok) {
// loggermdl.LogError("Error while parsing claims to MapClaims")
// return nil, errormdl.Wrap("Error while getting claims")
// }
// return claims, nil
// }
// // DecodeToken decode token
// func DecodeToken(req *http.Request) (jwt.MapClaims, error) {
// token, err := request.ParseFromRequest(req, request.OAuth2Extractor, func(token *jwt.Token) (interface{}, error) {
// b := ([]byte(GlobalJWTKey))
// return b, nil
// })
// if errormdl.CheckErr(err) != nil {
// loggermdl.LogError("Error while parsing JWT Token: ", errormdl.CheckErr(err))
// return nil, errormdl.CheckErr(err)
// }
// claims, ok := token.Claims.(jwt.MapClaims)
// if !errormdl.CheckBool1(ok) {
// loggermdl.LogError("Error while parsing claims to MapClaims")
// return nil, errormdl.Wrap("Error while getting claims")
// }
// return claims, nil
// }
var keyFunc = func(key string) jwt.Keyfunc {
return func(*jwt.Token) (interface{}, error) {
return []byte(key), nil
}
}
type jwtCustomClaim struct {
UserID string `json:"userId"`
SessionId string `json:"sessionId,omitempty"`
Groups []string `json:"groups"`
ClientIP string `json:"clientIP"`
HitsCount int `json:"hitsCount"`
@@ -62,28 +32,79 @@ type jwtCustomClaim struct {
jwt.StandardClaims
}
// GenerateToken generates JWT token from Login object
func GenerateToken(loginID string, groups []string, clientIP string, metadata gjson.Result, expirationTime time.Duration) (string, error) {
func generate(claims jwtCustomClaim, key string) (string, error) {
return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(key))
}
// extract return token from header string
func extract(tokenReq string) (string, error) {
tokenArray := strings.Split(tokenReq, "Bearer")
if len(tokenArray) <= 1 {
return "", errormdl.Wrap("Provided JWT token is nil or invalid ")
}
return strings.Trim(tokenArray[1], " "), nil
}
// decode accepts a parsed token and error from parse operation.
func decode(token *jwt.Token, err error) (jwt.MapClaims, error) {
if err != nil {
loggermdl.LogError("Error while parsing JWT Token: ", err)
return nil, err
}
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
loggermdl.LogError("Error while parsing claims to MapClaims")
return nil, errormdl.Wrap("Error while getting claims")
}
// validate user session from session id present in token
if err := sessionmdl.ValidateSessionFromToken(claims); err != nil {
loggermdl.LogError("session validation failed with err:", err)
return nil, sessionmdl.ErrSessionValidationFailed
}
return claims, nil
}
func GenerateTokenWithOptions(args ...Option) (string, error) {
options := new(Options)
options.Key = GlobalJWTKey
for i := range args {
args[i](options)
}
claims := jwtCustomClaim{
UserID: loginID,
Groups: groups,
ClientIP: clientIP,
Metadata: metadata.String(),
ClientIP: options.ClientIP,
Groups: options.Groups,
Metadata: options.Metadata,
SessionId: options.Session.SessionId,
UserID: options.UserID,
StandardClaims: jwt.StandardClaims{
ExpiresAt: time.Now().Add(expirationTime).Unix(),
ExpiresAt: options.ExpiresAt,
},
}
// Create token with claims
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Generate encoded token and send it as response.
t, err := token.SignedString([]byte(GlobalJWTKey))
if errormdl.CheckErr(err) != nil {
loggermdl.LogError(err)
return t, errormdl.CheckErr(err)
t, err := generate(claims, options.Key)
if err != nil {
return "", err
}
if len(options.Session.SessionId) > 0 {
sessionmdl.Set(options.UserID, options.Session)
}
return t, nil
}
// GenerateToken generates JWT token from Login object
func GenerateToken(loginID string, groups []string, clientIP string, metadata gjson.Result, expirationTime time.Duration) (string, error) {
return GenerateTokenWithJWTKey(loginID, groups, clientIP, metadata, expirationTime, GlobalJWTKey)
}
// GenerateTokenWithJWTKey generates JWT token from Login object
func GenerateTokenWithJWTKey(loginID string, groups []string, clientIP string, metadata gjson.Result, expirationTime time.Duration, JWTKey string) (string, error) {
claims := jwtCustomClaim{
@@ -95,43 +116,17 @@ func GenerateTokenWithJWTKey(loginID string, groups []string, clientIP string, m
ExpiresAt: time.Now().Add(expirationTime).Unix(),
},
}
// Create token with claims
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Generate encoded token and send it as response.
t, err := token.SignedString([]byte(JWTKey))
if errormdl.CheckErr(err) != nil {
loggermdl.LogError(err)
return t, errormdl.CheckErr(err)
}
return t, nil
return generate(claims, JWTKey)
}
//GeneratePricipleObjUsingToken GeneratePricipleObjUsingToken
func GeneratePricipleObjUsingToken(tokenReq string, jwtKey string) (jwt.MapClaims, error) {
tokenArray := strings.Split(tokenReq, "Bearer")
if len(tokenArray) <= 1 {
return nil, errormdl.Wrap("Provided JWT token is nil or invalid ")
}
tokenFromRequest := strings.Trim(tokenArray[1], " ")
// get data i.e.Claims from token
token, err := jwt.Parse(tokenFromRequest, func(token *jwt.Token) (interface{}, error) {
// Don't forget to validate the alg is what you expect:
_, ok := token.Method.(*jwt.SigningMethodHMAC)
if !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return []byte(jwtKey), nil
})
token, err := extract(tokenReq)
if err != nil {
loggermdl.LogError("Error while parsing JWT Token: ", err)
return nil, err
}
claims, ok := token.Claims.(jwt.MapClaims)
if !errormdl.CheckBool1(ok) {
loggermdl.LogError("Error while parsing claims to MapClaims")
return nil, errormdl.Wrap("Error while getting claims")
}
return claims, nil
return decode(jwt.Parse(token, keyFunc(jwtKey)))
}