package mgoapi import ( "errors" "reflect" "time" "gitbase.de/gopackage/mgocrud/v2" jwt "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/gin" ) // LoginModel is interface for modules which can be used for the login route type LoginModel interface { LoginCheck(db *mgocrud.Database) (tokenData interface{}, err error) LoginResponse(token string) (interface{}, error) } func (api *API) loginPostHandler(m LoginModel) func(c *gin.Context) { return func(c *gin.Context) { lM := newModelOf(m).(LoginModel) if err := c.Bind(lM); err != nil { c.JSON(500, gin.H{ "error": err.Error(), }) return } session := api.DBSession.Copy() defer session.Close() db := session.DB(api.DBName) tokenData, err := lM.LoginCheck(db) if err != nil { c.JSON(500, gin.H{ "error": err.Error(), }) return } if tokenData == nil { c.JSON(403, gin.H{ "error": "login failed", }) return } // build jwt jwtToken := jwt.New(jwt.GetSigningMethod("HS256")) oType := reflect.TypeOf(tokenData) var objectType string if oType.Kind() == reflect.Ptr { objectType = oType.Elem().Name() } else { objectType = oType.Name() } if objectType == "" { objectType = oType.String() } jwtToken.Claims = jwt.MapClaims{ "object": tokenData, "type": objectType, "exp": time.Now().Add(time.Minute * 60).Unix(), } token, err := jwtToken.SignedString(api.jwtSecret) if err != nil { c.JSON(500, gin.H{ "error": err.Error(), }) return } response, err := lM.LoginResponse(token) if err != nil { c.JSON(500, gin.H{ "error": err.Error(), }) return } c.JSON(200, response) } } // ValidateAuthToken checks if token is valid and returns its data func (c *Context) ValidateAuthToken() (tokenObject map[string]interface{}, tokenType string, err error) { tokenObject = c.GetStringMap("validate-auth-token-object") if tokenObject != nil { tokenType = c.GetString("validate-auth-token-type") _err, _ := c.Get("validate-auth-token-err") if _err != nil { err = _err.(error) } return // return cached data } token := c.Request.Header.Get(c.API.authenticationHeader) if token == "" { return nil, "", errors.New("empty token") } jwtToken, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) { return []byte(c.API.jwtSecret), nil }) if jwtToken == nil || jwtToken.Claims == nil { return nil, "", err } if err := jwtToken.Claims.Valid(); err != nil { return nil, "", err } claims := jwtToken.Claims.(jwt.MapClaims) _object, ok := claims["object"].(map[string]interface{}) if !ok { return nil, "", errors.New("token object data is invalid") } _type, ok := claims["type"].(string) if !ok { return nil, "", errors.New("token object type is invalid") } c.Set("validate-auth-token-object", _object) c.Set("validate-auth-token-type", _type) c.Set("validate-auth-token-err", err) return _object, _type, err }