130 lines
2.9 KiB
Go
130 lines
2.9 KiB
Go
package mgoapi
|
|
|
|
import (
|
|
"errors"
|
|
"reflect"
|
|
"time"
|
|
|
|
jwt "github.com/dgrijalva/jwt-go"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
mgo "gopkg.in/mgo.v2"
|
|
)
|
|
|
|
// LoginModel is interface for modules which can be used for the login route
|
|
type LoginModel interface {
|
|
LoginCheck(db *mgo.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
|
|
}
|